[Rod Stephens Books]
Index Books Python Examples About Rod Contact
[Mastodon] [Bluesky]
[Build Your Own Ray Tracer With Python]

[Beginning Database Design Solutions, Second Edition]

[Beginning Software Engineering, Second Edition]

[Essential Algorithms, Second Edition]

[The Modern C# Challenge]

[WPF 3d, Three-Dimensional Graphics with WPF and C#]

[The C# Helper Top 100]

[Interview Puzzles Dissected]

Title: Draw text filled with a gradient brush using PIL in Python

[Text that's filled with gradient brushes and then outlined with PIL in Python]

This post continues the series on gradient brushes, this time to fill text with a gradient brush.

pil_fill_text

The following pil_fill_text method uses a gradient brush to fill some text on a PIL image.

def pil_fill_text(image, brush, text, font, x, y, align, anchor): '''Fill the polygon with the brush.''' dr = ImageDraw.Draw(image) # Get the text's bounding box. bounds = dr.textbbox((x, y), text, font=font, align=align, anchor=anchor) # Get the filled bounding rectangle. rect_image = brush.make_image(bounds) # Translate the points. xmin, ymin, xmax, ymax = bounds xmin = int(xmin) ymin = int(ymin) xmax = int(xmax) ymax = int(ymax) x -= xmin y -= ymin # Make a mask image. wid = xmax - xmin hgt = ymax - ymin mask = Image.new('L', (wid, hgt), 'black') dr = ImageDraw.Draw(mask) dr.multiline_text((x, y), text=text, fill='white', font=font, anchor=anchor, align=align) # Draw the filled rectangle on the PIL image. image.paste(rect_image, (xmin, ymin), mask)

This method creates am ImageDraw.Draw object associated with the image and then calls its textbbox function to see how much room the text will require. It uses then uses the brush's make_image function to make a rectangle big enough to hold the text and filled with the brush. (See the earlier examples in the series for details about how that works. For example, see Make a RadialGradientBrush class for use with PIL in Python.)

Next, the code calculates the text's translated anchor point. We want to draw the text at the point (x, y) but the image we will draw on is located at the origin, so we need to move the text.

Now the program makes a mask image having the same size as the brush's filled rectangle. Initially the mask is black, and then the code draws the text on it in white.

The code finishes by copying the mask's filled rectangle onto the destination image. It uses the mask to copy only the parts of the image that correspond to the text.

Main Program

The following code shows how the main program draws the text on the lower left.

cx = round(margin + rect_wid / 2) cy += rect_hgt + margin center = (cx, cy) # See how big the text will be so we can make the gradient fit. text = 'Python' font = ImageFont.truetype('times.ttf', 80) align = 'center' anchor = 'mm' text_bounds = dr.textbbox(center, text, font=font, align=align, anchor=anchor) start_point = (0, text_bounds[1]) end_point = (0, text_bounds[3]) colors = [] for i in range(20): colors.append((255, 0, 0, 255)) colors.append((255, 255, 0, 255)) offsets = None radius = None brush = RadialMultiGradientBrush(center, colors, offsets, radius) pil_fill_text(image, brush, text, font, cx, cy, align, anchor) if show_points: pil_draw_circle(dr, center, 3, None, 'black') dr.rectangle(text_bounds, outline='black')

This code defines the text it will display and then creates a big font. It uses the ImageDraw.Draw object's textbbox function to see how big the text will be. This isn't actually necessary to draw the text; the code uses it to figure out where it should position the text.

Next, the code defines a colors list, repeating red and yellow several times. It uses the colors to create a RadialMultiGradientBrush and then calls pil_fill_text to fill the text with the brush.

Finally, if show_points is True, the program draws a circle at the brush's center point and draws a rectangle around the text.

Conclusion

The key technique is using the text as a mask so you can copy a filled rectangle onto the result image only in the places indicated by the mask. You can use this technique more generally to display just about any drawn image.

Download the example to experiment with it and to see additional details.

© 2024 - 2025 Rocky Mountain Computer Consulting, Inc. All rights reserved.