72

How to compress GIF animations? For example by reducing the color index.

The files are generated using Imagemagick but optimization seems complicated.

For example, the following animation is 864KB at 150x119:

example animation

To be used on a Linux machine.

Giacomo1968
  • 58,727
qubodup
  • 9,394

3 Answers3

92

Use gifsicle (available for Mac OS X, Windows, DOS, Debian, FreeBSD and NetBSD).

gifsicle -i anim.gif -O3 --colors 256 -o anim-opt.gif

This will optimize and reduce to 256 colors, if the animation uses more colors (the example image does).

You can reduce the size by reducing the number of colors:

example image with only 256 colors 512KB, 256 colors

example image with only 128 colors 412KB, 128 colors

example image with only 64 colors 340KB, 64 colors

example image with only 32 colors 240KB, 32 colors

example image with only 16 colors 140KB, 16 colors

Based on another Q&A.

qubodup
  • 9,394
16

Small addition to @qubodup's answer

Add --lossy flag. This flag varies from 30 to 200, where 30 is good enough.

gifsicle -O3 --colors 256 --lossy=30 -o output.gif input.gif
Levon
  • 596
3

A combination of ImageMagick and Gifsicle is what I do.

For testing, I create a gif from a video using FFmpeg. This is the exact command I used for that:

# The subtitle part will break the command unless the file has actual subtitles. Remove that part if you want to copy paste this command. It's there to convert the softsubs to hardsubs.
ffmpeg -y -i file.mkv -threads 8 -vf "subtitles=file.mkv:force_style=Fontsize=24,scale=-1:480:flags=spline-32,mpdecimate,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -vsync vfr -loop 0 file.gif

The base file is 12.5MB at 480p and 3.3MB at 240p.

High Quality:

mogrify -coalesce -layers optimize -fuzz 1% file.gif 
# Size is now 9.5MB at 480p
magick file.gif -append -unique-colors -dither None -colors 256 /tmp/colors.gif
magick file.gif -remap /tmp/colors.gif file.gif
rm /tmp/colors.gif 
# Size is now 9.4MB at 480p
gifsicle -o "file.gif" -i -O3 --lossy=10 -j8 "file.gif" 
# Size is now 8MB at 480p

Because Super User only supports 2MB files I had to tweak the values a little bit to get it to that exact size, the values in the (parentheses) are the sizes I got with the actual above settings.

240p(3.3MB) results:

  • Layer Optimization 1.2% fuzz -> 2.5MB (2.6MB)
  • 212 Color -> 2.1MB (2.6MB)
  • Lossy Compression -> 2MB (2.2MB)

240p HQ

Medium Quality:

mogrify -coalesce -layers optimize -fuzz 3% file.gif 
# Size is now 5.9MB at 480p
magick file.gif -append -unique-colors -dither None -colors 128 /tmp/colors.gif
magick file.gif -remap /tmp/colors.gif file.gif 
rm /tmp/colors.gif
# Size is now 4.7MB at 480p
gifsicle -o "file.gif" -i -O3 --lossy=30 -j8 "file.gif" 
# Size is now 4.2MB at 480p

240p(3.3MB) results:

  • Layer Optimization -> 1.6MB
  • 128 Color -> 1.3MB
  • Lossy Compression 30 -> 1.1MB

240p MQ

Low Quality:

mogrify -coalesce -layers optimize -fuzz 5% file.gif 
# Size is now 4.4MB
magick file.gif -append -unique-colors -dither None -colors 96 /tmp/colors.gif
magick file.gif -remap /tmp/colors.gif file.gif 
rm /tmp/colors.gif
# Size is now 3.4MB
gifsicle -o "file.gif" -i -O3 --lossy=50 -j8 "file.gif" 
# Size is now 2.9MB

240p(3.3MB) results:

  • Layer Optimization 1.2% fuzz -> 1.2MB
  • 96 Color -> 937KB
  • Lossy Compression -> 780KB

240p LQ

I uploaded other examples on imgur, but I got told off for them not being family friendly enough so keep that in mind before looking at them. It's a 7.2MB file at 240p which with the medium settings was reduced to 1.7MB.

Other notably common methods to reduce the filesize are to reduce the resolution and framerate. I usually do thesse things from ffmpeg when I create the GIF instead. (For instance with my example gif, I made it 240p resolution instead of 1080p, but kept framerate unchanged, this was how I got a managable 7MB file to start with.)

If planning to do this it should always be done before running the commands I suggested up top for the best results. It is better to do this when the GIF is originally created if possible.

ffmpeg -i input.gif -vf "fps=12,scale=-1:480:flags=spline-32,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" output.gif # Reduce fps to 12 and scale down to 480p using the spline-32 algorithm.

Important Update

I discovered after writing this that the split[s0][s1];[s0]palettegen=max_colors=128[p];[s1][p]paletteuse filter with FFmpeg to restrict the color palette of the gif (in this case to 128) before running ImageMagick layer optimization and gifsicle compression is superior to the approach I am taking above, the lower you set the colors the more FFmpeg's superiority in this area becomes apparent. You'll get marginally bigger files but the quality will be significantly greater relative to size if you use this method instead. So if you want to use that method, here's how to do it for medium quality:

ffmpeg -i input.gif -vf "split[s0][s1];[s0]palettegen=max_colors=128[p];[s1][p]paletteuse" file.gif
# Size is now 11MB at 480p
mogrify -coalesce -layers optimize -fuzz 3% file.gif
# Size is now 6MB at 480p
gifsicle -o "file.gif" -i -O3 --lossy=30 -j8 "file.gif" 
# Size is now 4.5MB at 480p

As you can see with that final number it's only a tiny bit bigger than the original Medium Quality method, but the quality is substantially better.

With this method you can also lower the color even further than you would with imagemagick while still maintaining a higher quality than imagemagick would give you, effectively allowing you to reduce the filesize further that way and still have it look better than the original method.

Mixing in the imagemagick and/or gifsicle color setting commands after ffmpeg's one will have no effect (they will just keep the ffmpeg generated palette).

For the high quality preset this doesn't matter though because it uses all 256 colors.


To explain what I'm doing.

ImageMagick:

  • -coalesce cleans all the frames which removes prior layer optimizations and can fix broken gifs, not using it can sometimes lead to broken results; by itself this option will usually make a gif bigger. My example gif becomes 3.8MB if I run only this option.

  • -layers optimize reduces the number of pixels per frame as much as possible and makes pixels that are of similar colors transparent.

  • -fuzz determines how 'similar' colors need to be to be rendered transparent instead with -layers optimize. Increasing this setting dramatically reduces filesize at the cost of creating ghosting artifacts which become more apparent the higher you set this. Increasing this to only 1.5% reduces my 2.5MB example file's size down to 1.3MB instead of 1.6MB; you should set this value as high as you can get away with. Usually a range of 1-3 is good.

    The artifacts created by -fuzz will be much more obvious on animated artwork than recorded videos; I recommend 1% for those.

Gifsicle:

  • -O3 sets the optimization level for gifsicle to 3, it works relatively similar to -layers optimize in imagemagick.
  • --lossy controls the amount of quality lost to jpeg-like artifacts and noise in order to reduce the filesize. You can set it as high as 200 I believe but I always tend to stick to the 10-50 range.
  • -j controls the number of threads. I use 8 because I have 8 physical cores on my cpu, the setting should be fine since even the cheapest pc these days is going to have at least a quad core multithreaded cpu which would mean that you can use 8 threads just fine even then.

This answer is a rewrite of another answer I made on Stack Overflow. The reason I use ImageMagick instead of Gifsicle to limit the colors of the GIF is because that question was about how to optimize a gif with only ImageMagick. I figured I'd leave it as is to make an answer that's equally good for that question and this one.

Cestarian
  • 1,997