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

Incorrect vertical alignment of character when using fontmode = '1' #2293

Closed
jkrebs opened this issue Dec 19, 2016 · 13 comments
Closed

Incorrect vertical alignment of character when using fontmode = '1' #2293

jkrebs opened this issue Dec 19, 2016 · 13 comments
Labels
Bug Any unexpected behavior, until confirmed feature. Regression
Milestone

Comments

@jkrebs
Copy link

jkrebs commented Dec 19, 2016

What did you do?

I installed Pillow 3.4.2 for local development (Python 2.7.12 on Ubuntu 16.04). My deployment target is Google App Engine which unfortunately still uses PIL 1.1.7.

There appears to be a backwards incompatibility (regression?) with the vertical alignment of the zero (0) character between these libraries and versions. Pillow does not align the character correctly.

I noticed it in one particular font (Verdana 13pt) when using ImageDraw.fontmode = '1' to disable anti-aliasing. The same issue does not occur with the default fontmode value.

I have tested this across 3 different official versions of the font from various downloads on Microsoft's website and Windows. These are freely available core fonts.

What actually happened?

Please compare the alignment of the zero (0) character in the aliased lines of the following images. It is very slight but it is unfortunately a big problem in my use-case.

PIL 1.1.7

pil_1_1_7

Pillow 3.4.2

pillow_3_4_2

Script

from PIL import Image, ImageDraw, ImageFont

import os.path
import string

path = os.path.dirname(os.path.abspath(__file__))

text = (string.digits
        + string.ascii_lowercase
        + string.ascii_uppercase
        + string.punctuation)

font_names = ['verdanab_a.ttf', 'verdanab_b.ttf', 'verdanab_c.ttf']

image = Image.new('RGB', (1250, 250))

draw = ImageDraw.Draw(image)
draw.rectangle((0, 0, image.size[0], image.size[1]), fill=(255, 255, 255))

current_y = 10

for n, font_name in enumerate(font_names):
    font = ImageFont.truetype(os.path.join(path, font_name), 13)

    draw_alias = ImageDraw.Draw(image)
    draw_alias.fontmode = '1'
    draw_alias.text(
        (10, current_y),
        '%s (alias): %s' % (font_name, text),
        (0, 0, 0),
        font=font)

    current_y += 25

    draw = ImageDraw.Draw(image)
    draw.text(
        (10, current_y),
        '%s (anti-alias): %s' % (font_name, text),
        (0, 0, 0),
        font=font)

    current_y += 50

image.save(os.path.join(path, 'output.png'), 'PNG')

Fonts

fonts.zip

@aclark4life
Copy link
Member

@jkrebs So it's better in PIL 1.1.7?

@aclark4life aclark4life added the Bug Any unexpected behavior, until confirmed feature. label Jan 8, 2017
@aclark4life aclark4life added this to the Future milestone Jan 8, 2017
@jkrebs
Copy link
Author

jkrebs commented Jan 8, 2017

@aclark4life Yes, PIL 1.1.7 aligns the zero character correctly.

@aclark4life
Copy link
Member

aclark4life commented Jan 8, 2017

@jkrebs Thanks, added Regression label

@wiredfool
Copy link
Member

Are you building the recent Pillow, or are you installing from a wheel?

@jkrebs
Copy link
Author

jkrebs commented Jan 8, 2017

I installed Pillow 3.4.2 via pip install on Ubuntu 16.04.

As part of the setup, I installed external libraries using apt-get install libxml2-dev libxslt1-dev libz-dev python-dev libjpeg-dev zlib1g-dev libfreetype6 libfreetype6-dev

@wiredfool
Copy link
Member

I strongly suspect that this is a difference in rendering in freetype.

Pip will preferrentially install from binary wheels, and all the binary wheels that we have package their own dependencies. So that is one version of freetype.

PIL doesn't have binaries, so it's building using the freetype on your machine.

I've tested this with MASTER and Pillow 1.2 (which is the earliest that builds for me, and it's basically PIL at that point), and not seeing any difference in the rendering. Specifically, both of them have an elevated 0.

This is from Pillow 1.2:
output

@hugovk
Copy link
Member

hugovk commented Jan 8, 2017

@jkrebs What version of FreeType is on Google App Engine?

I can reproduce the problem with Pillow 4.0.0 / Python 2.7 and:

$ freetype-config --ftversion
2.7.0

@jkrebs
Copy link
Author

jkrebs commented Jan 8, 2017

@hugovk Is there a way to determine the version of FreeType being used by PIL or Pillow from within Python? Google App Engine is kind of a black box.

My test was carried out using PIL 1.1.7 and Pillow 3.4.2 within the same machine, both compiled from source by pip, as far as I know. Could they still be using different FreeType versions?

@hugovk
Copy link
Member

hugovk commented Jan 8, 2017

Is there a way to determine the version of FreeType being used by PIL or Pillow from within Python? Google App Engine is kind of a black box.

I don't know.

My test was carried out using PIL 1.1.7 and Pillow 3.4.2 within the same machine, both compiled from source by pip, as far as I know. Could they still be using different FreeType versions?

They could. It's likely when you pip installed Pillow 3.4.2 it used a binary wheel, packaging its own version of FreeType (probably FreeType 2.7 or thereabouts). I'd guess PIL was built from source and used whatever FreeType is on GAE, which could well be as ancient as PIL 1.1.7 (maybe 2.4.4 from 2010?).

@jkrebs
Copy link
Author

jkrebs commented Jan 8, 2017

I'd guess PIL was built from source and used whatever FreeType is on GAE, which could well be as ancient as PIL 1.1.7 (maybe 2.4.4 from 2010?).

I compiled PIL 1.1.7 from source (http://effbot.org/downloads/Imaging-1.1.7.tar.gz). Pip would only compile when the FreeType libraries were already installed on the system, so presumably it did not use a binary wheel. The result of freetype-config --ftversion is 2.6.1.

So we know that the test case was passing as of FreeType 2.6.1 via PIL 1.1.7.

Is there a way that I can install Pillow 3.4.2 and force it to use the system FreeType 2.6.1 as a test?

@wiredfool
Copy link
Member

You can clone this git repo, then run python setup.py install and it will build against system packages.

@hugovk
Copy link
Member

hugovk commented Feb 17, 2019

@jkrebs Did you ever narrow this down to the version of FreeType being used? Is this still an issue?

@jkrebs
Copy link
Author

jkrebs commented Feb 18, 2019

@hugovk I did not make more progress with the investigation.

For my situation, I decided to use PIL 1.1.7 for local development because it matches Google App Engine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Any unexpected behavior, until confirmed feature. Regression
Projects
None yet
Development

No branches or pull requests

4 participants