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

Added "exact" option when saving WebP #6747

Merged
merged 15 commits into from Nov 21, 2022
Merged

Conversation

ashafaei
Copy link
Contributor

When encoding a transparent image with WebP, even if specified to be lossless, it'll drop the information that is not visible. This is normally fine, except for applications where you need to undo the mask or make additional changes later.

There's an option in the WebPConfig data structure named exact:

     int exact;           // if non-zero, preserve the exact RGB values under
                          // transparent area. Otherwise, discard this invisible
                          // RGB information for better compression. The default
                          // value is 0.

This option is not exposed to the users. In this pull request, I make this option available.

The parameter exact is True/False at the python level but translated to 0 or 1 (int) to match that of WebPConfig.

Changes proposed in this pull request:

  • Updated the binding at src/_webp.c.
  • Updated the Python encoder at src/PIL/WebPImagePlugin.py.
  • Added documentation for the new flag docs/handbook/image-file-formats.rst.
  • Added the unit-test Tests/test_file_webp_alpha.py.

I tried to follow the guidelines as much as possible. Let me know if I'm missing anything.
Thanks.

@radarhere radarhere changed the title Added WebP encoding with exact config. Added WebP encoding with exact config Nov 17, 2022
@radarhere radarhere added the WebP label Nov 17, 2022
@radarhere
Copy link
Member

radarhere commented Nov 18, 2022

This is currently failing on CentOS 7, because it is using libwebp 0.3.0. exact was added in 0.5.0.

@ashafaei
Copy link
Contributor Author

@radarhere Thanks for reviewing the pull request.
I see three potential directions forward:

  1. Update the pythonpillow/centos-7-amd64:latest docker image to install libwebp outside of the package manager. The latest version of the CentOS package manager is 0.3.0. We could even build inside the container. I don't know how the PIL binaries are packaged and distrbuted -- if there's a way to ensure the latest WebP is pulled/embedded correctly on client machines, then this could be fine.
  2. Add an #IFDEF/#IFNDEF to the src/_webp.c code to skip that line if the WebP version is below 0.5.0. That would require updating the build scripts to include the correct DEFINE on CentOS7.
  3. Drop this pull request altogether in favour of maintaining complete backward compatibility.

Let me know if I'm missing a possibility here. I'd be happy to work on 1, or 2, or even drop this altogether.
Thanks.

@radarhere
Copy link
Member

Pillow does distribute Python wheels, but we're building from source in our CI presumably to support users who also build from source, and if you install libwebp-devel on CentOS 7, that's what you get.

If you want to suggest that we deprecate support for older versions of libwebp, that's perfectly reasonable. It's just we would probably want to include a deprecation period, and I imagine you'd prefer this feature sooner rather than later.

I think using #ifdef is the best solution to the immediate problem.

@ashafaei
Copy link
Contributor Author

Thanks @radarhere for the useful feedback.

Turns out LibWebP already has a definition for

#define WEBP_ENCODER_ABI_VERSION 0x020f    // MAJOR(8b) + MINOR(8b)

The fix is a simple

#if WEBP_ENCODER_ABI_VERSION >= 0x0209
    // the exact flag is only available in libwebp 0.5.0 and later
    config.exact = exact;
#endif

I verified that 0.5.0 is the earliest version with exact with a version 0x0209. The version before that is 4.4 with 0x0202.

Interestingly the unit test also passes. I think they started removing the transparent part at that exact version, so the tests pass.

Let me know if there's anything else I could do. Thanks!

@hugovk
Copy link
Member

hugovk commented Nov 18, 2022

Looking at https://github.com/webmproject/libwebp/blob/main/NEWS, version 0.5.0 was released in 2015, so I think we can also deprecate it (in another PR).

We normally deprecate for at least a year and then drop in a major version.

Re: https://github.com/python-pillow/Pillow/milestones

If we deprecate now, Pillow 10 in July 2023 is too soon for removal, so Pillow 11 in October 2024 is the next one that can drop it. That's a nice long deprecation period, and CentOS 7 is EOL in June 2024.

I verified that 0.5.0 is the earliest version with exact with a version 0x0209. The version before that is 4.4 with 0x0202.

Do you mean 0.4.4 with 0x0202?

@ashafaei
Copy link
Contributor Author

@hugovk , yeah, sorry, 0.4.4 is 0x0202-- so the condition I put on

#if WEBP_ENCODER_ABI_VERSION >= 0x0209
    // the exact flag is only available in libwebp 0.5.0 and later
    config.exact = exact;
#endif

should be correct.

I'm probably not part of the deprecation conversation, but I think if there's no cost in maintaining support, it may be worth keeping around. WebP > 0.5.0 to support a minor flag that may not be even useful to everyone seems to be too small of a reason to drop support for an entire OS. Unless, of course, you are also experiencing compatibility issues with the other features in Pillow and CentOS7.

src/_webp.c Outdated Show resolved Hide resolved
Copy link
Member

@hugovk hugovk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docs/handbook/image-file-formats.rst Show resolved Hide resolved
Copy link
Member

@hugovk hugovk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@hugovk
Copy link
Member

hugovk commented Nov 20, 2022

Oh one little change, I went ahead and committed it directly, hope that's okay: removed the code formatting from the title.

This follows the Google developer docs style guide and is similar to, for example,
https://pillow.readthedocs.io/en/stable/releasenotes/9.1.0.html#added-mct-and-no-jp2-options-for-saving-jpeg-2000

@Yay295
Copy link
Contributor

Yay295 commented Nov 20, 2022

I think you linked to the wrong part of Google's style guide, since the change you made isn't related to grammar. The part about headings and titles does say to "Avoid using code items in headings when possible.", but I think they mean you should not include code phrases at all, not that code phrases shouldn't be formatted, because the start of the next sentence is "If you must mention a code item in a heading, ..." implying that by following the first sentence you would not mention a code item in a heading.

I didn't find anything in their style guide specifically about code formatting in titles, but if you think of this as a list rather than just titles, then there is a reference on the lists page: "If the item is entirely in code font, don't add end punctuation.". So code formatting in list items is allowed.

In this case in particular I think "Added the exact encoding option for WebP" is really ambiguous without code formatting. If you don't know that the encoding option is actually called exact, you could be left wondering what encoding option was added. You would of course be able to figure that out by reading the paragraph below it, but the statement by itself is ambiguous.

@hugovk
Copy link
Member

hugovk commented Nov 20, 2022

Right you are, I've undone that change!

@hugovk hugovk added the automerge Automatically merge PRs that are ready label Nov 20, 2022
@hugovk hugovk removed the automerge Automatically merge PRs that are ready label Nov 20, 2022
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
@ashafaei
Copy link
Contributor Author

There's so much to learn from y'all. I committed the latest changes. Thanks for the suggestions.

@radarhere radarhere added the automerge Automatically merge PRs that are ready label Nov 21, 2022
@mergify mergify bot merged commit 4f68047 into python-pillow:main Nov 21, 2022
@radarhere radarhere changed the title Added WebP encoding with exact config Added "exact" option when saving WebP Nov 21, 2022
@hugovk
Copy link
Member

hugovk commented Nov 21, 2022

Thank you for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge Automatically merge PRs that are ready WebP
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants