8

I have the function that generates character images from a font file using PIL. For the current example, it generates a white background image and a red character text. What I want now is that instead of pure red or any other color I can generate a gradient color. Is this possible with my current code? I have seen this post but it didn't help me.

Edit 1:

Currently, I am generating English alphabet images from font files using PIL. The fonts variable in my code has N number of ".ttf" files. lets suppose N=3 all in different styles e.g. style1, style2, style3. My current code will always generate these N different styles with fixed white background and fixed red character color. As shown in the below figure.

Style1

Style2

Style3

Instead of red color for the characters, I would like to apply gradients for each style. i.e. all characters in style1 font images should have the same gradient, style 2 font style should have a different gradient from style1 characters but should be the same for all of its characters and so on. As shown below (styles are different from the above images. Its just for demonstration of what I want).

gradient Style1

gradient Style2

gradient Style3

My code so far:

fonts = glob.glob(os.path.join(fonts_dir, '*.ttf'))
for font in fonts:
  image = Image.new('RGB', (IMAGE_WIDTH, IMAGE_HEIGHT), color='white')
  font = ImageFont.truetype(font, 150)
  drawing = ImageDraw.Draw(image)
  w, h = drawing.textsize(character, font=font)
  drawing.text(
  ((IMAGE_WIDTH-w)/2, (IMAGE_HEIGHT-h)/2),
  character,
  fill='red',
  font=font
  )
  image.save(file_path, 'PNG')
Ammar Ul Hassan
  • 826
  • 1
  • 18
  • 48

1 Answers1

9

One fairly easy way of doing it is to draw the text in white on a black background and then use that as the alpha/transparency channel over a background with a gradient.

Here's a background gradient:

enter image description here

#!/usr/bin/env python3

from PIL import Image, ImageDraw, ImageFont

w, h = 400, 150
image = Image.open('gradient.jpg').rotate(90).resize((w,h))
font = ImageFont.truetype('/System/Library/Fonts/MarkerFelt.ttc', 80)

# Create new alpha channel - solid black
alpha = Image.new('L', (w,h))
draw = ImageDraw.Draw(alpha)
draw.text((20,10),'Some Text',fill='white',font=font)
alpha.save('alpha.png')

# Use text cutout as alpha channel for gradient image
image.putalpha(alpha)
image.save('result.png')
 

The alpha.png looks like this:

enter image description here

And the result.png looks like this:

enter image description here

Note that the area around the text is transparent. but you can easily paste it onto a white or black background. So, say you wanted the background yellow, add the following to the bottom of the code above:

solid = Image.new('RGB', (w,h), 'yellow')
solid.paste(image,image)
solid.save('result2.png')

enter image description here

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • Thanks, Mark for this creative solution. Actually, in my current scenario, I have N font files that all have 26 characters from A to Z. What I really want is to apply N different gradient colors to all these N font files. However, the characters in the Nth font file should have a consistent gradient color. If I apply the logic of your current answer on my problem it will generate all characters of the same font in different gradient colors (the font is “MarkerFelt.ttc” but result2.png all characters have different gradients because of the gradient.jpg). – Ammar Ul Hassan Aug 04 '20 at 13:51
  • I don't understand what you want. Please try to improve the example image and description in your question. Thank you. – Mark Setchell Aug 04 '20 at 13:59
  • Mark please check out my Edit1 in the question. I hope you understand. – Ammar Ul Hassan Aug 05 '20 at 01:12
  • 2
    Sorry, as far as I can see, my suggestion is ideal. You can use the same, or a different gradient wherever you want - it is completely repeatable and deterministic if you want it that way, or random if you don't. I fail to see the problem. You can rotate the gradient 90 degrees if you want each letter to have the same gradient, surely? Or draw each letter one-at-a-time on the same piece of rainbow and append them? – Mark Setchell Aug 05 '20 at 07:57
  • "You can rotate the gradient 90 degrees if you want each letter to have the same gradient" can you guide me on how to rotate the gradient like that? – Ammar Ul Hassan Aug 05 '20 at 08:10
  • 1
    I added in the rotation of the gradient to my answer. Please have another look. – Mark Setchell Aug 05 '20 at 08:19