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

Bounding box calculation discrepancy between 7.0.0 and 8.4.0 for RGBA #5914

Closed
rabanks opened this issue Dec 29, 2021 · 3 comments
Closed

Bounding box calculation discrepancy between 7.0.0 and 8.4.0 for RGBA #5914

rabanks opened this issue Dec 29, 2021 · 3 comments

Comments

@rabanks
Copy link

rabanks commented Dec 29, 2021

What did you do?

I'm upgrading Pillow from 7.0.0 -> 8.4.0, and have noticed a discrepancy in what img.getbbox() returns for images that have the RGBA mode. It's worth mentioning that this is part of an upgrade in Python versions as well, from 3.7.9 -> 3.9.7 (although I'm not sure this is a cause).

The toy example that demonstrates the difference:

Pillow 7.0.0 (Python 3.7.9)

my_image = Image.open("/path/to/image.jpg").convert("RGBA")
my_image2 = my_image.point(lambda p: p if p < 220 else 0)
my_image2.getbbox()
# outputs e.g. (83, 10, 134, 152)

Pillow 8.4.0 (Python 3.9.7)

my_image = Image.open("/path/to/image.jpg").convert("RGBA")
my_image2 = my_image.point(lambda p: p if p < 220 else 0)
my_image2.getbbox()
# outputs None

If I remove the conversion to RGBA, however, then I get the same output as I did with 7.0.0.

It's also worth noting that my_image2 is the same image in both versions (i.e. I saved them both and then used ImageChops.difference()).

What did you expect to happen?

I expected the output of getbbox() to be the same as with 7.0.0.

What actually happened?

The output with 8.4.0 is None.

FWIW I noted some additions to the PIL.Image.load() logic between these two versions, which is unsurprising, but could be relevant. I believe load() is called within most functions, including getbbox().

Screenshot 2021-12-29 at 15 08 40

The line that caught my eye was 841 (the one that reads if "transparency" in self.info and mode in ("RGBA", "LA", "PA"):). Unless I'm reading this incorrectly, the addition of the check on mode means that this won't ever evaluate to True, because mode is set back to RGB a few lines above?

What are your OS, Python and Pillow versions?

OS: Mac OS
Python: 3.9.7
Pillow: 8.4

@radarhere
Copy link
Member

Hi. If I save the image from your code, using one of our test images,

from PIL import Image
my_image = Image.open("Tests/images/hopper.jpg").convert("RGBA")
my_image2 = my_image.point(lambda p: p if p < 220 else 0)
my_image2.save("out.png")

I get this completely transparent image
out

The purpose of getbbox() is to

Calculates the bounding box of the non-zero regions in the image.

So if there are no non-zero regions, returning None seems correct to me.
The change in behaviour is due to #4454. We've actually already had another user raising the same issue as you in #4849.
Here are the release notes we issued about this change.

https://pillow.readthedocs.io/en/stable/releasenotes/7.1.0.html#if-present-only-use-alpha-channel-for-bounding-box

When the getbbox() method calculates the bounding box, for an RGB image it trims black pixels. Similarly, for an RGBA image it would trim black transparent pixels. This is now changed so that if an image has an alpha channel (RGBA, RGBa, PA, LA, La), any transparent pixels are trimmed.

@radarhere
Copy link
Member

I've created #5915 to fix the the (unrelated) oddity you've found in load().

@rabanks
Copy link
Author

rabanks commented Dec 30, 2021

Hi Andrew,

Thanks for the useful context around the change and for the info; it has helped to solve the issue. I agree that it does indeed sound like the function is now behaving properly which is great!

@rabanks rabanks closed this as completed Dec 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants