python-pillow / python-pillow/Pillow
Color and quality loss with similar colors or from RGBA
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 13.8k
- Forks
- 2.5k
- Avg merge
- 2d 8h
- Merged PRs (30d)
- 89
Description
Hello,
I have found 2 cases where PIL reduces color quality, when I import a gif animation as PIL images, and then save it again as a gif animation.
Case 1: Importing a gif animation with similar background colors removes differentiated background:
This is the gif animation with a checkered background:

After importing it as PIL format images, and then exporting it again as a gif, the colors get reduced, and you cannot see the checkered pattern of the background anymore:

The code used is this:
from PIL import Image as Img
#Convert Gif Frames into PIL images:
tempimage = Img.open("GIF before import.gif")
ExportFrames = []
durationFrame=None
for i in range(0, tempimage.n_frames):
tempimage.seek(i)
ExportFrames.append(tempimage.copy())
if durationFrame == None:
durationFrame = tempimage.info['duration']
ExportFrames[0].save("GIF after export.gif", disposal=2, save_all=True,
append_images=ExportFrames[1:], loop=0,
duration=durationFrame, optimize=False, lossless=True)
Case 2: Adding Alpha Channel to PIL images, before saving as gif:
I added this additional step of pasting each frame unto a transparent alpha PIL image, because for some GIFs, when I imported them and then saved them, the first main frame of the GIF would not have a transparent background. This would be fixed by adding this step.
However with it this quality loss occurs:
The original GIF image that I import as PIL formatted images:

After saving, there is an extreme quality loss:

This quality loss does only occur when adding the step.
However, even with the step added, there is no quality loss when exporting the frames as single png images instead as a gif animation:

This suggests that error happens during GIF export.
The code used for this is the following:
from PIL import Image as Img
#Correct the first frame of gif animations:
def CreateFrameWithAlphaValue(CurrentImage,size):
width,height=size
edited_frame = Img.new('RGBA', (width, height))
edited_frame.putalpha(0)
edited_frame.paste(CurrentImage, (0, 0))
return edited_frame
#Convert Gif Frames into PIL images:
tempimage = Img.open("GIF before import.gif")
ExportFrames = []
durationFrame=None
for i in range(0, tempimage.n_frames):
tempimage.seek(i)
ExportFrames.append(tempimage.copy())
if durationFrame == None:
durationFrame = tempimage.info['duration']
#Add Alpha Channel to all gifs in order to avoid erroneous first frames:
for x in range(0,len(ExportFrames)):
ExportFrames[x]=CreateFrameWithAlphaValue(ExportFrames[x],ExportFrames[0].size).copy()
ExportFrames[0].save("GIF after export.gif", disposal=2, save_all=True,
append_images=ExportFrames[1:], loop=0,
duration=durationFrame, optimize=False, lossless=True)
I also attach the sample images and python scripts above here so anyone can recreate the issue:
Sample files.zip
Running convert('P') on every PIL frame image did not solve the issue.
How can I stop and control the quality loss in both of these cases? Why is this happening? Is this a potential bug?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the two Python scripts against the supplied Sample files.zip and compare the GIF and PNG outputs, focusing on the GIF export path for similar colors and RGBA frames. Reproduce both cases, then trace the relevant Pillow GIF-saving entry point and add regression coverage; done means the reported color loss is explained and the affected export behavior is corrected or clearly documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- computer-graphics
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100