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

First frame of transparent GIF is read incorrectly #6590

Closed
jerrutledge opened this issue Sep 16, 2022 · 4 comments · Fixed by #6592
Closed

First frame of transparent GIF is read incorrectly #6590

jerrutledge opened this issue Sep 16, 2022 · 4 comments · Fixed by #6592
Labels

Comments

@jerrutledge
Copy link

What did you do?

I have a four-frame transparent GIF I want to do some manipulation with (i.e. comparing frames, cropping).
squidcat

I ran this code to turn each frame into an array, and saved each array as a png for visualization purposes.

from PIL import Image
import numpy

inputFileName = "squidcat.gif"
outputFileName = "pngcat"

frames = []
with Image.open(inputFileName, formats=["GIF"]) as imageObject:
    # save each frame to a numpy array
    for frame_num in range(0, imageObject.n_frames):
        imageObject.seek(frame_num)
        frames.append(numpy.array(imageObject))

# do something with the numpy frames

for i in range(len(frames)):
    # save each frame as a png to visualize
    fileName = outputFileName + "_" + str(i) + ".png"
    Image.fromarray(frames[i]).save(fileName)

What did you expect to happen?

I expected the program to generate four png files containing the four transparent frames.

What actually happened?

The first frame was completely black, with the subsequent three turning out normally. I've included my results below:
pngcat_0
pngcat_1
pngcat_2
pngcat_3

What are your OS, Python and Pillow versions?

  • OS: Mac OS 12.5.1 (21G83)
  • Python: 3.10.6
  • Pillow: 9.2.0
@jerrutledge
Copy link
Author

Additional information: I have tried using LoadingStrategy.RGB_ALWAYS, but it produces results with no transparency:

pngcat_0

Is this different treatment of the first frame intended behaviour?

@radarhere radarhere added the GIF label Sep 17, 2022
@radarhere
Copy link
Member

If you run the following code, you will see that the GIF is in P mode for the first frame, and then RGBA mode for the subsequent frames that. However, when it is converted to NumPy and then back, the first frame becomes L. You have lost the palette. This is understandable, because a P mode image consists of each pixel as an index in a palette, and the palette itself. When converting to a NumPy array, it would only be copying the indexes of the pixels.

from PIL import Image
import numpy

inputFileName = "squidcat.gif"
outputFileName = "pngcat"

frames = []
with Image.open(inputFileName, formats=["GIF"]) as imageObject:
    # save each frame to a numpy array
    for frame_num in range(0, imageObject.n_frames):
        imageObject.seek(frame_num)
        print("before", imageObject.mode)
        frames.append(numpy.array(imageObject))

# do something with the numpy frames

for i in range(len(frames)):
    # save each frame as a png to visualize
    fileName = outputFileName + "_" + str(i) + ".png"
    im = Image.fromarray(frames[i])
    print("after", im.mode)
    im.save(fileName)

As for LoadingStrategy.RGB_ALWAYS, yes, that it does appear to be a Pillow bug that the first frame is not using the transparency.

@radarhere
Copy link
Member

radarhere commented Sep 17, 2022

I've created PR #6592 to fix the LoadingStrategy.RGB_ALWAYS bug, resolving this.

@jerrutledge
Copy link
Author

This was immensely helpful. Thank you especially for the PR. I've tested the #6592 version of GifImagePlugin.py with my project locally using LoadingStrategy.RGB_ALWAYS and it has solved my issue. Much appreciated.

@radarhere radarhere changed the title First frame of transparent GIF is read wrong First frame of transparent GIF is read incorrectly Sep 24, 2022
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 a pull request may close this issue.

2 participants