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

GIF export PIL 9.2.0 palette bug #6675

Closed
keesh0 opened this issue Oct 22, 2022 · 3 comments
Closed

GIF export PIL 9.2.0 palette bug #6675

keesh0 opened this issue Oct 22, 2022 · 3 comments
Labels

Comments

@keesh0
Copy link

keesh0 commented Oct 22, 2022

Hello,
The following code correctly generates a GIF image with a custom color table under Pillow 9.0.1.
However, under Pillow 9.2.0 my first few entries for red, green, and blue are ignored.
Windows 11, Jupyter notebook, Python 3.8.13
image

import numpy as np
import PIL
from PIL import Image
import ctypes
PIL.__version__  # need 9.0.1, if we use 9.2.0 then the palette is **wrong!!!** 

pixels = np.zeros(shape=(256, 512), dtype=np.ubyte)  # rows x cols
for row in range(256):
    for col in range(512):
        if row < 24:
            pixels[row][col] = 1
        if row > 240:
            pixels[row][col] = 3
        if row > 100 and row < 125:
             pixels[row][col] = 2

colorMap = [0, 0, 0]   # PIL palettes must be an integer list or bytearray
for i in range(1, 256):
     colorMap.extend([i, i, i])
colorMap[3:6] = [255, 0, 0]
colorMap[6:9] = [0, 255, 0]
colorMap[9:12] = [0, 0, 255]
print(colorMap)

pilImage = Image.fromarray(pixels, mode="P")
comment = "test color GIF"
pilImage.save("D:\\data\\test.gif", include_color_table=True, palette=colorMap,
              interlace=False,  optimize=False, disposal=1, comment=comment)
@radarhere radarhere added the GIF label Oct 22, 2022
@radarhere
Copy link
Member

radarhere commented Oct 22, 2022

Testing, I find that this is due to #6283. That PR meant that Image.fromarray(pixels, mode="P") now has a populated palette, rather than an empty one. The palette that you are providing in palette=colorMap is being written as the global palette in the GIF, but the local palette is still coming from the image.

Possible solutions to your problem.

  1. Stop the image from having a palette. Change Image.fromarray(pixels, mode="P") to Image.fromarray(pixels, mode="L").
  2. Stop instructing GifImagePlugin to include the local palette. Remove include_color_table=True.

Let us know if either of those resolves the matter for you.

@radarhere
Copy link
Member

If neither of those solutions is satisfactory, then allow me to ask this question - why have you included include_color_table=True? The documentation states that this is "Whether or not to include local color table". I presume you don't want to increase the file size for no reason by including a global palette and a local palette that are the same.

@keesh0
Copy link
Author

keesh0 commented Oct 26, 2022

Thanks.
The following works fine under both PIL 9.0.1 and 9.2.0.

pilImage = Image.fromarray(pixels, mode="L")

Original motivation was to port legacy C++ code line by line (it used gif_lib.h).
Keep the exact same functionality for regression testing.
Also, there is a black box downstream system which may require a palette as opposed to direct RGB values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants