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

getlength output varies for prebuilt vs "build_ext" wheels #6871

Closed
kdumontnu opened this issue Jan 8, 2023 · 9 comments
Closed

getlength output varies for prebuilt vs "build_ext" wheels #6871

kdumontnu opened this issue Jan 8, 2023 · 9 comments

Comments

@kdumontnu
Copy link

kdumontnu commented Jan 8, 2023

What did you do?

I had been using a pip option to build pillow because there previously weren't prebuilt wheels for some of my (unix) OSes I needed:

pillow; \
       --global-option="build_ext" \
       --global-option="--enable-freetype" \
       --global-option="--disable-zlib" \
       --global-option="--disable-jpeg" \
       --global-option="--disable-tiff" \
       --global-option="--disable-lcms" \
       --global-option="--disable-webp" \
       --global-option="--disable-webpmux" \
       --global-option="--disable-jpeg2000"

This worked well, and I had consistent behavior between operating systems (alpine, windows, MacOS, ubuntu).

However, I've tried moving to the prebuilt wheel, and now I'm seeing slightly different behavior from my text-wrapping built using getlength on ubuntu (tested 22.04 and 20.04)

I assume it's related to a dependency I need to lock, but I'm not sure where to start looking.

What did you expect to happen?

I expected the wrapping to be the same between operating systems and previous builds.

What actually happened?

I'm seeing different length results from getlength, causing differences in behavior between ubuntu vs other OSes and also vs previous "build_ext" versions.

What are your OS, Python and Pillow versions?

  • OS: Ubuntu (22.04 and 20.04)
  • Python: 3.10
  • Pillow: 9.4.0
        # Decode from base64 to binary
        binary = b64decode(MY_FONT_TTF)
        # Load my ttf font by wrapping in BytesIO to make file-like object
        with BytesIO(binary) as myttffontfile:
            self.myfont = ImageFont.truetype(myttffontfile, size=50000)

       self.myfont.getlength(test_softline)  # This has different results on Ubuntu now
@radarhere
Copy link
Member

I would be looking at raqm.

>>> from PIL import features
>>> features.check_feature("raqm")
True

https://pillow.readthedocs.io/en/stable/installation.html#basic-installation

We provide binaries for Linux for each of the supported Python versions in the manylinux wheel format. These include support for all optional libraries except libimagequant. Raqm support requires FriBiDi to be installed separately

@radarhere radarhere changed the title getlength out varies for prebuilt vs "build_ext" wheels getlength output varies for prebuilt vs "build_ext" wheels Jan 9, 2023
@nulano
Copy link
Contributor

nulano commented Jan 9, 2023

https://pillow.readthedocs.io/en/latest/installation.html#build-options

You probably want one of the Raqm flags, --disable-raqm or --enable-raqm. I noticed they were missing from the documentation so I opened #6876 to add them.

Alternatively you can try --vendor-raqm and --vendor-fribidi if you want to match the official wheels.

I'd guess you have libfribidi.so on your system, but no matching Raqm header files, so Raqm is automatically disabled for your builds. You can either install Raqm, or use the vendor flags to use the version included with Pillow.

@radarhere
Copy link
Member

#6876 has been merged, so you will find those options in the documentation now.

@radarhere
Copy link
Member

@kdumontnu did that answer your question?

@kdumontnu
Copy link
Author

kdumontnu commented Jan 13, 2023

I don't think so, unless I'm missing something. The discrepancy I'm seeing is that my outputs matched correctly when I was building from source (using the flags I posted above). However, now that I'm using the prebuilt wheels my outputs no longer match.

Are the prebuilt pillow wheels referencing any external dependencies?

@radarhere
Copy link
Member

radarhere commented Jan 14, 2023

So, to rewind a bit, raqm is an optional dependency that handles complex text layout. The previous comments were about enabling or disabling raqm in your prebuilt wheels. If you aren't worried about non-English languages though, you can choose to not use it, regardless of whether or not it is enabled.

If you switch to

ImageFont.truetype(myttffontfile, size=50000, layout_engine=ImageFont.Layout.BASIC)

you should find your results to be consistent, regardless of whether you're using the wheels or building Pillow from source.

@radarhere
Copy link
Member

radarhere commented Jan 16, 2023

Are the prebuilt pillow wheels referencing any external dependencies?

As I said,
https://pillow.readthedocs.io/en/stable/installation.html#basic-installation

We provide binaries for Linux for each of the supported Python versions in the manylinux wheel format. These include support for all optional libraries except libimagequant. Raqm support requires FriBiDi to be installed separately

@radarhere
Copy link
Member

What is your reason for wanting consistency across operating systems? If it is because you are developing a library, and have little control over how Pillow is installed, then using BASIC layout would be your best bet.

If you do have control over how Pillow is installed, and would like to consider complex text layout, then this comes down to a need to get raqm working on different operating systems. Which operating systems do not have raqm installed correctly?

>>> from PIL import features
>>> features.check_feature("raqm")
True

@github-actions
Copy link

Closing this issue as no feedback has been received.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Jan 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants