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
GifImageFile and animated gif with mismatched color palettes #2893
Comments
To be clear -- is the image incorrect when reading it in, or when writing back out? |
The reading part is incorrect ( |
@tomaszhlawiczka thanks for the workaround! it saved my day! |
This workaround helps with some GIFs, but I found some GIFs which are still incorrectly opened or saved even after applying the workaround. I simply just open the gif and then save it, the code looks like this: # workaround initialization code
class AnimatedGifImageFile(GifImageFile):
def load_end(self):
ImageFile.ImageFile.load_end(self)
Image.register_open(AnimatedGifImageFile.format, AnimatedGifImageFile, _accept)
Image.register_save(AnimatedGifImageFile.format, _save)
Image.register_save_all(AnimatedGifImageFile.format, _save_all)
Image.register_extension(AnimatedGifImageFile.format, ".gif")
Image.register_mime(AnimatedGifImageFile.format, "image/gif")
# end of workaround initialization code
def get_frames(gif: Image.Image) -> List[Image.Image]:
"""
Extract all frames from gif.
This function is just slight adjustment of the for-cycle from the workaround.
"""
last_frame = None
all_frames = []
i = 0
try:
while True:
gif.seek(i)
new_frame = gif.convert('RGBA')
if last_frame is not None and gif.disposal_method == 1:
updated = new_frame.crop(gif.dispose_extent)
last_frame.paste(updated, gif.dispose_extent, updated)
new_frame = last_frame
else:
last_frame = new_frame
# do resizing on new_frame here...
all_frames.append(new_frame.copy())
i += 1
except EOFError:
gif.seek(0)
return all_frames
gif: Image.Image = Image.open('example.gif')
frames = get_frames(gif)
frames[0].save('example.saved.gif', save_all=True, append_images=frames[1:]) |
#5333 doesn't completely fix, but does significantly improve the car gif. |
We use this code to save AnimGifs (taken from https://github.com/akirbaes/giftools.git): import PIL.Image, numpy
# https://github.com/akirbaes/giftools.git
def create_gif_frame( frame, transparency=255):
# 'only RGB or L mode images can be quantized to a palette' says PIL
quantized = (frame.convert('RGB') if frame.mode != 'RGB' else frame).quantize(colors=255, method=2, kmeans=0, dither=0)
# Save the transparency areas beforehand because quantizing doesn't always respect it
mask = numpy.array( frame.convert('RGBA') if frame.mode != 'RGBA' else frame.copy() )[:,:,3].copy() // 255
# Puts back the transparency areas on the image after quantization
data = numpy.array( quantized )
data = data * mask # Nullifies transparent areas
mask = -(mask-1) * transparency
data = data + mask # Makes transparent area the transparency color
result = PIL.Image.fromarray( data,'P' )
result.putpalette( quantized.getpalette() )
result.info['transparency'] = transparency
return result
with PIL.Image.open('/tmp/example.gif', 'r') as image:
frames, durations = [], []
for frame in PIL.ImageSequence.Iterator(image):
frames.append( create_gif_frame(frame) )
# crucial to get duration+timestamp
image.copy()
duration = image.info.get( 'duration' )
assert duration is None or type(duration) is int # 'image/mpo' has no duration
if duration is None:
assert not durations
break
durations.append( duration )
frames[0].save( '/tmp/test.gif', format='GIF', version='GIF89a', save_all=True, optimize=False, disposal=2,
append_images=frames[1:], duration=durations, loop=0 ) |
I've created PR #5857, which fixes both images listed here, resolving this. |
I've just upload my solution on github. https://github.com/bongdang/gifraw |
I'm trying to resize an animated gif file with a different color palette for each frame.
Each frame should be composed with own colors, but because of buildin frames merge (see
GifImageFile.load_end
) colors are messed up.Python:
3.6
PIL:
4.4.0.dev0
I see following solutions here:
P
→RGBA
and then make a merge (losing an original data)So far I've made a workaround as follow (might be helpful for someone):
The text was updated successfully, but these errors were encountered: