Keeping gif Animations Small

grid of lines of different thicknessesAnimated gifs can be big. A 300-frame animation at 500-by-500 pixels can easily run 25 megabytes (MB) or more.

25 MB doesn’t sound like much these days, but there are still a lot of services out there for whom that’s too big. For example, Tumblr has a 10 MB limit. In order to get my animations down to Tumblr size, I’ve relied on two blunt tools: making each frame smaller (and thus losing detail), and making fewer frames (causing shorter or choppier animation).

Recently, though, I discovered something that surprised me: gif compression depends very much on the directional qualities of your image (unlike, say, JPEG). After the break, some data I’ve collected and some advice.

I discovered this by accident after making an animation with lots of horizontal stripes: the resulting file was tiny, compared to the others I’ve been making.

I decided to investigate. Wikipedia tells us that the an individual gif is made with LZW encoding by running left-to-right, starting at the upper left, just like reading a book. That sure suggested that horizontal runs would compress better, but by how much? I decided to make some measurements. That is, Science!

To see how compression varied with the directionality of the image, I made a test program (in Processing, naturally). It draws a 500-by-500 window full of equally-spaced black and white stripes. I made images for stripes that are 2 pixels wide, 4, 6, and so on up to 20. For each width, I made images from 0 to 90 degrees of rotation in 1 degree increments. The picture at the top of this post shows the 2, 10, and 20 pixel wide stripes at 0, 30 and 90 degrees. The graph below shows the sizes of the gif files saved from these images. The horizontal axis runs from 0 degrees (horizontal stripes) at the left to 90 degrees (vertical stripes) at the right. The vertical axis shows the size of the resulting gif file. The colors correspond to the different stripe thicknesses, from 2 pixels (red) to 20 pixels (brown) in 2-pixel increments.

Compression of anti-aliased images of parallel lines.

Compression of anti-aliased images of parallel lines. Horizontal axis is rotation angle from 0 to 90 degrees, vertical axis is size of file. Colors indicate line width from 2 pixels (red) to 20 pixels (brown).

It’s pretty clear that the best results are at 0 and 90 degrees. And generally speaking, more horizontal stripes compress better than more vertical ones (values near the left are generally smaller than those on the right). That matches what we’d expect from the algorithm. There are some other, smaller local minima. There’s a big notch at 22.5 degrees, and a smaller one at 45 degrees. The asymmetry of the compression is reinforced by the lack of a corresponding notch at 67.5 degress.

I got to wondering how much the anti-aliasing was shaping these curves. So I ran the program again, but after drawing the image I clamped all pixels values less than 128 to black, and the others to white. Here are the results.

Compression of black-and-white-only images of parallel lines

Compression of black-and-white-only images of parallel lines. Horizontal axis is rotation angle from 0 to 90 degrees, vertical axis is size of file. Colors indicate line width from 2 pixels (red) to 20 pixels (brown).

Well that’s different. We still have much better compression for mostly horizontal lines than for mostly vertical, but the middle is a muddle because there are so many graphs overlapping. Here they are broken out one by one.

Graphs of compression for different line thicknesses.

Compression of black-and-white only images, broken out by line thickness from 2 (red) to 20 (brown).

So it’s really just the very thin lines that are responsible for most of the noise. The thicker lines all have a generally similar shape: fantastic compression at 0 (horizontal lines), which gets worse as the lines turn vertical. Then each compression curve’s wiggles get both taller and wider; I don’t have a good explanation for why that’s happening, particularly as the compression variation is even more extreme, relative to the rest of the curve, than the anti-aliased versions. And while the compression gets better as we get towards 90 degrees, it doesn’t become nearly as good as it was for the horizontal stripes. But once again, horizontal stuff compresses better than vertical.

Just for fun, here are the files sizes for the stripes in JPG format. The very thin stripes are noisy, as we’d expect, but as the stripes get thicker the compression becomes more predictable. This is because JPG works by compressing 8-by-8 tiles of the image. JPEG is responsive to structures aligned with its tiles, so we’d expect better compression as the stripes become horizontal or vertical, which the graphs show. But notice that JPG is not sensitive to directionality: the file sizes (even for the noisy, thin stripes) are symmetrical around 45 degrees. On the left are files sizes for the anti-aliased images, on the right are pure black and white.

Plots of JPG compression sizes.

Sizes of JPG compressed files. Left: anti-aliased. Right: pure black-and-white.

Here are the sizes of the different final anti-aliased animation files, running from the 2-pixel wide stripes at the left to the 20-pixel stripes at the right. These sizes do away with the directional nature, since they each contain the whole sequence from 0 to 90 degrees. Unsurprisingly, the big stripes resulted in smaller animation files than the thin stripes.

Plot of gif animation size by stripe width

Plot of gif animation size by stripe width

The moral of the story? The more your image contains dominantly horizontal elements, the better it will compress. I doubt I’d ever change any image just to make it compress better, but it’s nice to know that if you do happen to have a lot of horizontal stuff, you can create an animation with larger images or more frames, and still stay under the maximum allowed file size.

I’ve noticed that some social media platforms let you rotate a gif after you upload it. I don’t know what they’re doing to provide that feature, or even if they’re all doing the same thing. But if your platform offers that feature and you’ve produced an animation that’s just above their limit, you could try creating a new animated gif rotated 90 degrees, and seeing if that gives you a smaller file that’s under the limit. If so, you could upload that and then tell the platform to rotate it 90 degrees. I haven’t tried this myself yet.

1 thought on “Keeping gif Animations Small

  1. clipping path service

    That’s what i was really looking for. Because whenever gif file is large, it takes longer time to open on hard disk and longer time to load in case of a webpage. Looks like you have given a really great solution to my problem. Thanks a lot.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *