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
Number of colors in palette should be maintained #3396
Comments
The supplied PNG image has 8 colours in it. Pillow is providing a palette of the maximum length for the bit depth. Since the nearest valid bit depth is 4, the output palette is 16 (2**4 = 16). You are suggesting that we trim it further, rather than just keeping it within the valid range. See also #2202 |
I am having a similar problem with gif files. The input gif file has 64 colors in the palette, when opening the file and checking the palette size I get 256 colors. There is data in the palette which I cannot make sense of...
I know my test data has 64 colors but I need to know this programmatically. What is the reason for expanding the palette size to the maximum? Is there a workaround? |
#5330 addresses the PNG part of this issue. |
I started putting together a change to fix the TIFF problem - Date: Fri Mar 26 23:43:16 2021 +1100
Limit COLORMAP to number of colors in palette when saving
diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py
index ba7f9a084..1de91fbba 100644
--- a/Tests/test_file_tiff.py
+++ b/Tests/test_file_tiff.py
@@ -616,6 +616,16 @@ class TestFileTiff:
im.load()
assert not fp.closed
+ def test_plte_length(self, tmp_path):
+ im = Image.new("P", (1, 1))
+ im.putpalette((1, 1, 1))
+
+ out = str(tmp_path / "temp.tif")
+ im.save(str(tmp_path / "temp.tif"))
+
+ with Image.open(out) as reloaded:
+ assert len(reloaded.palette.getdata()[1]) == 3
+
# Ignore this UserWarning which triggers for four tags:
# "Possibly corrupt EXIF data. Expecting to read 50404352 bytes but..."
@pytest.mark.filterwarnings("ignore:Possibly corrupt EXIF data")
diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py
index 19bcf4419..0dd5bd0e8 100644
--- a/src/PIL/TiffImagePlugin.py
+++ b/src/PIL/TiffImagePlugin.py
@@ -1520,7 +1520,8 @@ def _save(im, fp, filename):
ifd[PHOTOMETRIC_INTERPRETATION] = photo
if im.mode in ["P", "PA"]:
- lut = im.im.getpalette("RGB", "RGB;L")
+ palette_length = len(im.palette.getdata()[1])
+ lut = im.im.getpalette("RGB", "RGB;L")[:palette_length]
ifd[COLORMAP] = tuple(v * 256 for v in lut)
# data orientation
stride = len(bits) * ((im.size[0] * bits[0] + 7) // 8) But then I found that the TIFF documentation for COLORMAP states that https://www.awaresystems.be/imaging/tiff/tifftags/colormap.html
It doesn't specify the flexibility that the PNG format has (see #2202). So I would conclude that we shouldn't make this change for TIFF. |
Similarly, the GIF specification - https://www.w3.org/Graphics/GIF/spec-gif87.txt - states that
So, closing. If anyone disagrees with my reasoning, feel free to comment and this can be re-opened. |
What did you do?
Open an image (PNG or TIFF) with mode P and save it again in the same file format.
What did you expect to happen?
The saved file should have exactly the same colors in the palette.
What actually happened?
The number of colors in the saved palette is larger than in the source palette using more space than necessary.
What are your OS, Python and Pillow versions?
Please include code that reproduces the issue and whenever possible, an image that demonstrates the issue. Please upload images to GitHub, not to third-party file hosting sites. If necessary, add the image to a zip or tar archive.
The best reproductions are self-contained scripts with minimal dependencies. If you are using a framework such as plone, Django, or buildout, try to replicate the issue just using Pillow.
Test data
The text was updated successfully, but these errors were encountered: