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

Copy Python palette to new image in quantize() #5696

Merged
merged 1 commit into from
Sep 6, 2021

Conversation

radarhere
Copy link
Member

Resolves #5695

quantize() accepts palette as an argument, but only applies the palette to the C layer.

Pillow/src/PIL/Image.py

Lines 1123 to 1133 in d50052a

if palette:
# use palette from reference image
palette.load()
if palette.mode != "P":
raise ValueError("bad mode for palette image")
if self.mode != "RGB" and self.mode != "L":
raise ValueError(
"only RGB or L mode images can be quantized to a palette"
)
im = self.im.convert("P", dither, palette.im)
return self._new(im)

This PR copies the palette into the Python layer as well.

@paulds8
Copy link

paulds8 commented Aug 30, 2021

Looking at the change, I don't quite understand how adding the 'GIF' format to the save worked though. My expectation was that the issue would be somewhere in save() but if this works I'm happy.

@radarhere
Copy link
Member Author

When writing the PNG PLTE chunk, the palette data is being retrieved from the C layer (.im), but limited to the number of colors

if im.mode == "P":
palette_byte_number = colors * 3
palette_bytes = im.im.getpalette("RGB")[:palette_byte_number]
while len(palette_bytes) < palette_byte_number:
palette_bytes += b"\0"
chunk(fp, b"PLTE", palette_bytes)

colors is set here (unless there is no palette or you're passing a "bits" argument, but those are not the case)

colors = max(min(len(im.palette.getdata()[1]) // 3, 256), 1)

This is determining the number of colors from the ImagePalette object in the Python layer

def getdata(self):
"""
Get palette contents in format suitable for the low-level
``im.putpalette`` primitive.
.. warning:: This method is experimental.
"""
if self.rawmode:
return self.rawmode, self.palette
return self.mode, self.tobytes()

So in this PR, I am making sure that ImagePalette is also correct, meaning that the number of colors is correct when saving to PNG.

@hugovk hugovk merged commit 869b786 into python-pillow:master Sep 6, 2021
@radarhere radarhere deleted the quantize_palette branch September 6, 2021 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PNG palette quantized save functionality different between 8.1.0 and 8.3.1
3 participants