I have a list of PIL images I want to turn into a GIF. I have a gray mouse moving around in a maze, following a cyan dot. However, the mouse renders as cyan in the saved GIF, and I don't know why.
Here's a link to the GIF (in mp4 format). Here's a link to what the mouse should look like.
Here's the code I used to generate the GIF:
import PIL
imgs = []
fig, ax = plt.subplots(1, 1, figsize=(4, 4))
# np_grids is a list of grids I used to render the maze frames; these details seem unimportant
for idx, grid in enumerate(np_grids):
# [Code which plots something interesting on ax]
# Get the axis as an image
fig.tight_layout()
fig.canvas.draw()
img = PIL.Image.frombytes('RGB', fig.canvas.get_width_height(),fig.canvas.tostring_rgb())
imgs.append(img)
target_file = 'example.gif'
start_step = 25 # Start the gif at this step
# Save the gif
imgs[start_step].save(target, format="GIF", save_all=True, append_images=imgs[start_step+1:], duration=100, loop=0)
imgs
appears to contain the correct images, as plotting with plt.imshow(imgs[0])
gives the desired result.
I've tried saving via a few different tools, using both imageio
and the save
function in the PIL.Image
class. I hoped one would use a different algorithm to save the GIF and therefore have better coloration, but both approaches produced similar results.
EDIT: I solved the problem thanks to the comments. I changed the img
generation code to:
img = PIL.Image.frombytes('RGB', fig.canvas.get_width_height(),fig.canvas.tostring_rgb())
if idx == 0: # Quantize the first frame and get the palette
img = img.quantize(colors=254, method=PIL.Image.Quantize.MAXCOVERAGE)
else: # Quantize all other frames to the same palette
img = img.quantize(colors=254, palette=imgs[0], method=PIL.Image.Quantize.MAXCOVERAGE)
imgs.append(img)