Title: Fill text with random circles with PIL in Python
This example is very similar to the previous one Fill text with random lines with PIL in Python except it fills the text with random circles instead of random lines, so without further ado, here's the code that draws the circle-filled text.
def fill_shapes(self):
# Make an image to draw on.
self.canvas.update()
wid = self.canvas.winfo_width()
hgt = self.canvas.winfo_height()
image = Image.new('RGBA', (wid, hgt))
dr = ImageDraw.Draw(image)
# Fill with a gradient.
start_point = (0, 0)
end_point = (0, hgt)
start_color = [255, 255, 255, 255]
end_color = [0, 0, 255, 255]
brush = LinearGradientBrush(start_point, end_point,
start_color, end_color)
bounds = (0, 0, wid, hgt)
pil_fill_rectangle(image, brush, bounds)
# Get text metrics.
text = 'Random\nCircles'
font = ImageFont.truetype('times.ttf', 150)
align = 'center'
anchor = 'mm'
cx = wid / 2
cy = hgt / 2
text_bounds = dr.textbbox((cx, cy), text, font=font,
align=align, anchor=anchor)
# Make the text fill image.
text_xmin, text_ymin, text_xmax, text_ymax = text_bounds
text_wid = math.floor(text_xmax - text_xmin)
text_hgt = math.floor(text_ymax - text_ymin)
fill_image = Image.new('RGBA', (text_wid, text_hgt))
fill_dr = ImageDraw.Draw(fill_image)
cx -= text_xmin
cy -= text_ymin
# Fill the image with random circles.
max_radius = 50
min_radius = 10
thickness = 2
num_lines = 100
for i in range(num_lines):
# Pick a random point in the region.
px = random.uniform(text_xmin, text_xmax)
py = random.uniform(text_ymin, text_ymax)
# Pick a random radius.
radius = random.uniform(min_radius, max_radius)
x1 = px - radius
y1 = py - radius
x2 = px + radius
y2 = py + radius
# Generate a random color.
r = random.randint(50, 255)
g = random.randint(50, 255)
b = random.randint(0, 255)
color = (r, g, b, 255)
# Fill the circle.
fill_dr.ellipse((x1, y1, x2, y2), fill=color)
# Make the image brush.
brush = ImageBrush(fill_image)
# Fill the text.
cx = wid / 2
cy = hgt / 2
thickness = 1
pil_draw_outline_text(dr, cx, cy, text, 'blue', font, anchor, align,
thickness)
pil_fill_text(image, brush, text, font, cx, cy, align, anchor)
# Display the result.
self.photo_image = ImageTk.PhotoImage(image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo_image)
This code is mostly similar to the previous example but there are a few differences. This code creates the background image and fills it with a gradient as before. It then gets the bounding box for the text and creates a text background image of that size. The program then enters a loop where it picks a random point within the background image and draws a circle with a random radius and color.
After it has drawn the random circles, the program uses an ImageBrush to fill the text with the background image.
Conclusion
Like the previous example, this one's results change every time you run the program. You could seed the random number generator to get consistent "random" circles each time. You could also change the program to pick from some other collection of random colors, draw the circles' outlines, and so forth.
As before, the ImageBrush class makes it pretty easy to fill shapes (like text) with just about anything. Download the example to experiment with it and to see additional details.
|