Skip to content

Each frame of an animated GIF can have a different palette #4977

@MarkSetchell

Description

@MarkSetchell

This StackOverflow question refers https://stackoverflow.com/q/64334674/2836621

If you look at the animated GIF in that question and analyse it with ImageMagick, you will see that each frame has a different palette:

$ identify -verbose  anim.gif | grep -A5 "Colormap:"
  Colormap:
    0: (6,2,3,1) #060203FF srgba(6,2,3,1)
    1: (253,135,19,1) #FD8713FF srgba(253,135,19,1)
    2: (29,82,41,1) #1D5229FF srgba(29,82,41,1)
    3: (44,74,95,1) #2C4A5FFF srgba(44,74,95,1)
    4: (101,134,148,1) #658694FF srgba(101,134,148,1)
--
  Colormap:
    0: (5,5,6,1) #050506FF srgba(5,5,6,1)
    1: (206,130,24,1) #CE8218FF srgba(206,130,24,1)
    2: (112,67,11,1) #70430BFF srgba(112,67,11,1)
    3: (12,70,103,1) #0C4667FF srgba(12,70,103,1)
    4: (15,135,146,1) #0F8792FF srgba(15,135,146,1)
--
  Colormap:
    0: (5,5,8,1) #050508FF srgba(5,5,8,1)
    1: (28,132,103,1) #1C8467FF srgba(28,132,103,1)
    2: (15,71,38,1) #0F4726FF srgba(15,71,38,1)
    3: (11,74,99,1) #0B4A63FF srgba(11,74,99,1)
    4: (7,137,148,1) #078994FF srgba(7,137,148,1)
--
  Colormap:
    0: (5,5,8,1) #050508FF srgba(5,5,8,1)
    1: (33,135,106,1) #21876AFF srgba(33,135,106,1)
    2: (21,71,37,1) #154725FF srgba(21,71,37,1)
    3: (11,73,100,1) #0B4964FF srgba(11,73,100,1)
    4: (8,138,145,1) #088A91FF srgba(8,138,145,1)

If you append all the frames side-by-side with ImageMagick, you will get:

convert anim.gif -coalesce +append result.png

z

If you analyse the same image with PIL:

import numpy as np
from PIL import Image

gif = Image.open('anim.gif')

# Append all frames together into one wide image
for i in range(img.n_frames):
   img.seek(i)
   frame = img.copy()
   print(f'Frame: {i}, palette: {frame.getpalette()[:15]}')
   frame = frame.convert('RGB')
   if i==0:
      combined = np.array(frame)
   else:
      combined = np.hstack((combined,frame))

Image.fromarray(combined).save('result.png')

You get the same palette for all frames:

Frame: 0, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 1, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 2, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 3, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 4, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 5, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 6, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 7, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 8, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 9, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 10, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 11, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 12, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 13, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 14, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 15, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]
Frame: 16, palette: [6, 2, 3, 253, 135, 19, 29, 82, 41, 44, 74, 95, 101, 134, 148]

And a big mess :-)

result

Using Pillow v7.2.0 on macOS with Python 3.8.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions