-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Extra output from getpalette() and getcolors() in quantized image #6046
Comments
I think this probably deserves a PR, but if you would like an immediate solution, try this code out. from PIL import Image
RGB_flat = (2, 62, 255, 255, 124, 0, 26, 201, 56, 232, 0, 11, 139, 43, 226, 159, 72, 0, 241, 76, 193, 163, 163, 163, 255, 196, 0, 0, 215, 255, 0, 0, 0, 255, 255, 255)
img = Image.open('cherry.jpg')
pimg = Image.new('P', (16,16))
pimg.putpalette(RGB_flat+RGB_flat[-3:]*(255 - len(RGB_flat)//3))
imgq = img.quantize(palette=pimg)
print(imgq.getcolors())
print(imgq.palette.colors) |
Thanks that fix seems to work. I'm not terribly familiar with interfacing C with Python programs but after staring at the code a bit I think my specific issue might stem from the Pillow/src/libImaging/Palette.c Lines 43 to 47 in 95cff6e
Then in _putpalette() the call to unpack appears to only replace items up to the size of the palette:Line 1674 in 1646326
As a result you get your requested palette plus the remaining ramp items from the original palette initialization (or whatever the palette was before). There are a lot of places where the code assumes a 256 color palette so changing the size would probably break everything...so padding out the palette automatically might be the best fix. There does appear to be logic to skip duplicate colors in other sections of the code which is why the call to getcolors() seems to work with the padding.
I can try to come up with a PR for a fix, but you would prefer to fix this at the Python level or in the C code itself? |
I expect a C solution would be better than a Python one, as it would have a broader effect. |
I've created PR #6060 to resolve this, so that your original code works. |
Thanks I pulled in your changes from the PR and recompiled. This fixes the confusing outputs I was seeing and even better the quantization is now acting in a much more predictable fashion. I was always puzzled at some of the color choices it was making before. I appreciate your help in resolving this so quickly. Please feel free to close once that PR gets into a release. |
The next release will be on April 1. |
What did you do?
I am using
Image.quantize
to reduce an image down to a simple 12 color palette and count the prevalence of each color in quantized image.What did you expect to happen?
getpalette()
should return a 36 integer list reflecting the R,G,B values of the 12 color palettegetcolors()
should return a list of 12 tuples with the second index in the tuples ranging from 1-12 referencing the colors in the palette.What actually happened?
When I call
getpalette()
the first 36 items reflect my palette but the remaining items up to index 768 are a sequence of12, 12, 12, 13, 13, 13
etc. I'm guessing the code does this to avoid resizing the array and internally detects these additional items and discards them...so maybe not a big deal.The real issue is when I call
getcolors()
. Instead of receiving a list of 12 tuples (with second index in the tuples referencing a palette colors in the range 1-12) I receive a list of 208 tuples which reference palette colors as high as 252. I can't seem to make sense of the output. Am I supposed to just ignore anything that references an out of range palette index?What are your OS, Python and Pillow versions?
The text was updated successfully, but these errors were encountered: