FreeType sub-pixel text rendering
I was wondering if it would be possible to add sub-pixel rendering support into Pillow.
Pillow uses FreeType under the hood for TrueType fonts. FreeType supports sub-pixel rendering, but Pillow's current way of rendering text doesn't allow for sub-pixel rendering in the first place.
I actually think Pillow does support this, as of Pillow 9.4.0, thanks to #6722
The test add in that PR draws 'par' and then 'adise' immediately after it. In the below modified version of that code, you can see that the length of 'par' is not an integer.
If I draw the text 'paradise' twice, once with the non-integer position of 'adise' and once with a rounded position, the text is rendered differently. I've added a vertical line and scaled the result up to demonstrate it more clearly.
from PIL import Image, ImageDraw, ImageFont
im = Image.new("RGB", (230, 110))
expected = im.copy()
expected_draw = ImageDraw.Draw(expected)
font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 48)
expected_draw.text((0, 0), "paradise", font=font)
draw = ImageDraw.Draw(im)
# Act
draw.text((0, 0), "par", font=font)
draw.text((0, 55), "par", font=font)
length = draw.textlength("par", font=font)
print(length) # 86.390625
draw.text((length, 0), "adise", font=font)
draw.text((int(length), 55), "adise", font=font)
draw.line((176, 0, 176, 110), (255, 0, 0))
im.resize((230*5, 110*5), Image.NONE).save("out.png")
Are you using an older version of Pillow? Were you thinking of something else? Are you using a different API?
@radarhere That is not sub-pixel rendering. Sub-pixel rendering is when each color channel is rendered separately to produce text that looks sharper on an LCD display. From the OP linked page, to enable sub-pixel rendering, the FT_PIXEL_MODE_LCD flag is required. However, because this technology depends on the LCD panel sub-pixel arrangement, it is not as simple as simply enabling this flag, a new API for selecting the LCD sub-pixel arrangement is needed.
What #6722 does is slightly adjust the positioning of glyphs (which are always aligned to the pixel grid) when a non-integer coordinate is specified. I'm not sure whether it relates to sub-pixel rendering (i.e. whether the coordinates would get rounded to a sub-pixel grid), but sub-pixel rendering is a separate concept.
Ah, right, apologies. I just read 'sub-pixel text rendering' and presumed that it was text rendered at a position specified with less than a pixel.