First frame of transparent GIF is read wrong
What did you do?
I have a four-frame transparent GIF I want to do some manipulation with (i.e. comparing frames, cropping).

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:

What are your OS, Python and Pillow versions?
- OS: Mac OS 12.5.1 (21G83)
- Python: 3.10.6
- Pillow: 9.2.0
Additional information: I have tried using LoadingStrategy.RGB_ALWAYS, but it produces results with no transparency:

Is this different treatment of the first frame intended behaviour?
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.
I've created PR #6592 to fix the LoadingStrategy.RGB_ALWAYS bug, resolving this.
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.