Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImageDraw renders TrueType characters too skinny on 16-bit grayscale images compared to RGB ones #5591

Closed
iprotsyuk opened this issue Jul 7, 2021 · 3 comments · Fixed by #5598

Comments

@iprotsyuk
Copy link

iprotsyuk commented Jul 7, 2021

What did you do?

I tried to render a line of text on a 16-bit grayscale image using a TrueType font and the ImageDraw module.

What did you expect to happen?

I expected the shape of characters to be determined only by the actual font file and size, both of which I specified when initializing an instance of ImageFont.FreeTypeFont.

What actually happened?

For some reason the characters appear very skinny compared to the same line of text being rendered with the same font over an RGB image of the same size.

What are your OS, Python and Pillow versions?

  • OS: Linux
  • Python: 3.6
  • Pillow: 8.1.1
import numpy as np

from PIL import Image, ImageDraw, ImageFont

image_height = 500
image_width = 700

grayscale_image_array = np.ones([image_height, image_width]).astype(np.uint16)
grayscale_image_array[0:500, 0:700] = 12000
grayscale_image = Image.fromarray(grayscale_image_array)

rgb_image_array = np.ones([image_height, image_width]).astype(np.uint8)
rgb_image_array[0:500, 0:700] = 47  # roughly same color as on `grayscale_image`
rgb_image = Image.fromarray(rgb_image_array)

font_data = ImageFont.truetype('assets/ProductSans-Regular-prehint.ttf', 50)

grayscale_draw = ImageDraw.Draw(grayscale_image)
grayscale_draw.text((300, 300), "Expected normal-width characters", fill='white', font=font_data)

rgb_draw = ImageDraw.Draw(rgb_image)
rgb_draw.text((300, 300), "Expected normal-width characters", fill='white', font=font_data)

Grayscale image:
grayscale text rendering

RGB image:
rgb text rendering

ProductSans-Regular-prehint.ttf
(to test locally, change ".gif" extension of this file to ".ttf" as GitHub doesn't allow to upload those directly)

@radarhere
Copy link
Member

This is a bug with I;16 images, like #3747

@radarhere
Copy link
Member

I've created PR #5598 to resolve this.

@iprotsyuk
Copy link
Author

btw when looking for a workaround for this issue, I tried to pre-render the text as a PNG and use Image.paste() later on to effectively get the same output. However, Image.paste() also squeezes the overlay image when the parent is I;16. I wonder if more fundamental solution exists for these cases, instead of patching every method to make it aware of I;16 pixels?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants