python-pillow / python-pillow/Pillow

Color and quality loss with similar colors or from RGBA

Open
#6,832 23 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

GIF
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:
GIF before import

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:
GIF after export

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:
GIF before import
After saving, there is an extreme quality loss:
GIF after export

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:

GIF before import 44

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.