how can I resize an animated GIF file using ImageMagick?
first run:
convert do.gif -coalesce temporary.gif
then
convert -size <original size> temporary.gif -resize 24x24 smaller.gif
I was looking for imagemagick solution as I am familiar with it, but in the end I went with @sam's suggestion of gifsicle
. It did just what I wanted, no hassle.
Can optimize resulting file size in so many ways, but I went with just reducing the size and reducing number of colors. Worked like a charm:
gifsicle --resize 48x48 --colors 16 original.gif > smaller.gif
-coalesce
+ -deconstruct
After -coalesce
, you likely want to add a -deconstruct
:
convert in.gif -coalesce -resize 256x -deconstruct out-deconstruct.gif
The root cause of the problem is that your input GIF was properly minimized: GIF allows the next frame to be just the modified rectangle from the previous one at an offset.
-coalesce
then expands all the frames to the original size, which makes the resize work, but it does not re-compress the frames again as your input image: -deconstruct
is needed for that!
Using the test data from this answer: How do I create an animated gif from still images (preferably with the command line)? we can see this clearly with identify
:
$ identify out-convert.gif | head -n 3
out-convert.gif[0] GIF 1024x1024 1024x1024+0+0 8-bit sRGB 256c 16.7865MiB 0.020u 0:00.019
out-convert.gif[1] GIF 516x516 1024x1024+252+257 8-bit sRGB 256c 16.7865MiB 0.030u 0:00.019
out-convert.gif[2] GIF 515x520 1024x1024+248+257 8-bit sRGB 256c 16.7865MiB 0.030u 0:00.019
$ convert out-convert.gif -resize 256x out.gif
$ identify out.gif | head -n 3
out.gif[0] GIF 256x256 256x256+0+0 8-bit sRGB 256c 5.0479MiB 0.000u 0:00.009
out.gif[1] GIF 256x256 256x256+125+128 8-bit sRGB 256c 5.0479MiB 0.000u 0:00.009
out.gif[2] GIF 256x258 256x256+123+128 8-bit sRGB 256c 5.0479MiB 0.000u 0:00.009
$ convert out-convert.gif -coalesce -resize 256x out-coalesce.gif
$ identify out-coalesce.gif | head -n 3
out-coalesce.gif[0] GIF 256x256 256x256+0+0 8-bit sRGB 256c 1.97683MiB 0.010u 0:00.009
out-coalesce.gif[1] GIF 256x256 256x256+0+0 8-bit sRGB 256c 1.97683MiB 0.010u 0:00.009
out-coalesce.gif[2] GIF 256x256 256x256+0+0 8-bit sRGB 256c 1.97683MiB 0.010u 0:00.009
$ convert out-convert.gif -coalesce -resize 256x -deconstruct out-deconstruct.gif
$ identify out-deconstruct.gif | head -n 3
out-deconstruct.gif[0] GIF 256x256 256x256+0+0 8-bit sRGB 256c 1.87942MiB 0.010u 0:00.010
out-deconstruct.gif[1] GIF 135x135 256x256+60+61 8-bit sRGB 256c 1.87942MiB 0.010u 0:00.010
out-deconstruct.gif[2] GIF 135x136 256x256+59+61 8-bit sRGB 256c 1.87942MiB 0.010u 0:00.010
out.gif
out-coalesce.gif
out-deconstruct.gif
First, we see how to input file, out-convert.gif
, was in fact compressed, since frame 2 is only 516x516
at offset 252+257
, while the full sized frame 1 is 1024x1024
.
Then, if we compare the three conversions:
out.gif
: All frames are256x256
or larger, and huge at about 5MiB, TODO why?Visually incorrect, since those approximately
256x256
frames have a non-zero offset, e.g.125+128
for frame 2!out-coalesce.gif
: all frames are256x256
and have the correct offset0+0
.Output looks visually correct, but the output file size is 2.0 MiB, which is larger than
out-deconstruct.gif
out-deconstruct.gif
: compressed frames, final output size 1.9 MiB.Not considerably smaller than
out-coalesce.gif
, but I think this is just because the black ground compresses really well, and it could be very significant in general.
ffmpeg and gifsicle
I also tried out the following commands:
ffmpeg -i out-convert.gif -vf scale=256:-1 out-ffmpeg-small.gif
gifsicle --resize 256x256 out-convert.gif > out-gifsicle.gif
and both produced an even smaller correctly looking 1.5 MiB output.
See also: How do I create an animated gif from still images (preferably with the command line)?
TODO: why can they make it smaller than convert
? Are they just selecting better more minimal diff rectangles, or something else?
Tested in Ubuntu 18.10, ffpmeg 4.0.2-2, ImageMagick 6.9.10-8.