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

Weird getcolors() output after some alpha/transparency processing #6797

Closed
MvGulik opened this issue Dec 10, 2022 · 4 comments
Closed

Weird getcolors() output after some alpha/transparency processing #6797

MvGulik opened this issue Dec 10, 2022 · 4 comments

Comments

@MvGulik
Copy link

MvGulik commented Dec 10, 2022

What did you do?

Trying to eradicate ... Erm, mask-out some image parts to get color-data on the remaining image data (pixel != 0).

What did you expect to happen?

To not get the same/identical color-data for both the source and the masked image.

What actually happened?

The source and the masked image actually returned the same/identical color-data.

What are your OS, Python and Pillow versions?

  • OS: Linux Mint 20.3
  • Python: Python 3.8.10 (default, Nov 14 2022, 12:59:47) // [GCC 9.4.0]
  • Pillow: 9.3.0
from PIL import Image

size = 16
band_size = 32

## Creating some source image
img1 = Image.frombytes('L', (size, size), bytes([int(v/band_size)*band_size for v in range(size**2)]))
print('getcolors:1 =', img1.getcolors())

## Creating some mask image.
img2 = Image.frombytes('1', (size, size), bytes(int(v%band_size<size)*255 for v in range(size**2))) ## (!?! ... Not using *255 gives odd result)
img2 = img2.transpose(method=Image.Transpose.ROTATE_90)

## Doing some magic with both.
img3 = img1.copy() ## just to not disturb test-case img1.
## not sure about the finer details off the next two processes.
img3.putalpha(img2)
img3.apply_transparency() ## totally mystified by this one.
print('img3.mode:1 =', img3.mode) ## "LA" ???. Kinda expected an "L" output image here.
#print('getcolors:2 =', img3.getcolors()) ## output as expected ... for a LA image. -- double nr of colors with halved count-values.

## Ok ... Lets try something else.
img3 = img3.convert('L')
print('img3.mode:2 =', img3.mode)
print('getcolors:3 =', img3.getcolors()) ## Come again ??? This data is the same as for img1. That can't be right ... considering it shows() a different image than img1.

if (00):
	img1.show()
	img2.show()
	img3.show()
Local output:
getcolors:1 = [(32, 0), (32, 32), (32, 64), (32, 96), (32, 128), (32, 160), (32, 192), (32, 224)]
img3.mode:1 = LA
getcolors:2 = [(16, (32, 0)), (16, (64, 0)), (16, (96, 0)), (16, (128, 0)), (16, (160, 0)), (16, (192, 0)), (16, (224, 0)), (16, (224, 255)), (16, (192, 255)), (16, (160, 255)), (16, (128, 255)), (16, (96, 255)), (16, (64, 255)), (16, (32, 255)), (16, (0, 0)), (16, (0, 255))]
img3.mode:2 = L
getcolors:3 = [(32, 0), (32, 32), (32, 64), (32, 96), (32, 128), (32, 160), (32, 192), (32, 224)]

... Guess I just have to try some other route(s).


Local picked alternative. (simpler and probably faster too)

## after "img2 = ..."
img0 = Image.new('L', (size, size), 0)
img3 = img1.copy() ## just to not disturb test-case img1.
img3.paste(img0, mask=img2)
print('getcolors =', img3.getcolors())
## getcolors = [(144, 0), (16, 32), (16, 64), (16, 96), (16, 128), (16, 160), (16, 192), (16, 224)]
@radarhere radarhere changed the title Weird getcolors() output after some alpha/transparency processing. Weird getcolors() output after some alpha/transparency processing Dec 11, 2022
@radarhere
Copy link
Member

"LA" ???. Kinda expected an "L" output image here.

https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.putalpha

Adds or replaces the alpha layer in this image. If the image does not have an alpha layer, it’s converted to “LA” or “RGBA”.

So it makes sense to me that putalpha converts your L mode image to LA. The "L" in "LA" should be the original img1, and the "A" should be img2.

img3.apply_transparency() ## totally mystified by this one.

https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.apply_transparency

If a P mode image has a “transparency” key in the info dictionary, remove the key and apply the transparency to the palette instead.

You shouldn't need to run apply_transparency on your image, because it's not a P mode image.

Come again ??? This data is the same as for img1. That can't be right ... considering it shows() a different image than img1.

When I run this code, it show()s the same image for both.

tmpu2hmx3rm

It makes sense to me that it would be the same - by convert()ing to "L", you're removing the alpha channel that was just added.

I think you're saying that using paste() with mask is working for you, so you're not looking for a solution here, you're just trying to point out a bug or gain understanding.

@MvGulik
Copy link
Author

MvGulik commented Dec 11, 2022

You shouldn't need to run apply_transparency on your image, because it's not a P mode image.

Mmmm. I see.
In that case it might be helpful to add something to that effect to the doc.
The "instead" part kinda made me think it would do something else to non P images.

When I run this code, it show()s the same image for both.

... Aha, yea. I probably should have gone for a img4 case, instead of using img3 as output again, at the "## Ok ... Lets try something else." part.

Closing: Invalid bug / local misunderstanding resolved.

@radarhere
Copy link
Member

I've created PR #6798 to update the docstring.

@MvGulik
Copy link
Author

MvGulik commented Dec 11, 2022

That adjustment would have definitely worked in my case.

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