« Smerity.com

The Mystery of the Spotty Animated GIF

Have you ever posted an animated GIF to an application or website that didn't like the idea of motion? You likely ended up with a horrible, strange looking freeze frame.

I know. You've pondered this question for the longest time. It has haunted your dreams. Why such a strange screenshot? What madness is happening? Is my computer cursed? Did I accidentally poke holes in my RAM again?

GIF, if you didn't know, is a most marvelously strange image format. It was introduced in 1987 and only supports 256 colours in an image. It has been plagued by lawsuits, poor algorithms, poor defaults, and lolcats. Actually, to be fair, I shouldn't be dissing the lolcats. The lolcats are probably what made it so resilient to change. Other formats have come and gone, but nothing has replaced the vehicle of the lolcats, our beloved GIF.

So why the spots, Doc?

GIF didn't have fancy techniques like spatial image compression or temporal motion compensation like these fancy new video formats. GIF's old. It predates the CD. It predates me! Instead, GIF uses an interesting little hack called Transparency Optimisation to optimise animations.

Uncompressed GIF animations store the full frame for each and every image. As you might guess, that gets pretty large pretty quickly. Wouldn't it be nice if you could just paint the difference between this frame and the last? That's exactly what GIF does.

One of the colours you can select is transparent. GIF doesn't support semi-transparency (like that fancy young PNG), but it does support binary transparency. Binary transparency is simple: either you see the colour or you don't.

How does that make it smaller?

One of the other advantages of GIF is that the images are compressed using the lossless Lempel-Ziv-Welch (LZW) technique. LZW compresses by creating a dictionary of commonly occurring sequences and replacing them with a shorter symbol. These symbols are placed whereever you meet repetitive data. Annoyingly enough, LZW compression was also one of the major issues with GIF in the olden days: the patent for it expired in 2003.

If we didn't include LZW, the transparency optimisation trick alluded to above wouldn't make anything smaller. Each of those transparent pixels has to be recorded in the GIF. With LZW, however, those transparent pixels become hugely advantageous over just storing the full frame.

GIFs store their pixel data in rows. If the majority of the frame is transparent, the majority of these rows will just be the transparent pixel repeated over and over again. This compresses tremendously well.

LZW compression is very happy to turn that into a succint representation. Bam. A smaller, thinner, sexier GIF.

And it's that transparency that results in your spotty GIF preview

When the GIF software decides to take a snapshot of the animation instead of playing it, it grabs an individual frame from somewhere past the start (i.e. movie trailers always start with a "boring" black frame).

This would generally be fine except that, as we've seen, GIFs use partial frames to aid in compression. What we end up with is a partial frame that appears "spotty" as it only contains the difference between the past frame and the current one.

Long story, I know, but now you understand why when you see an animated GIF preview it can end up looking spotty. Your friends will be amazed, your colleagues stunned, and it's now inevitable you'll become tremendously rich.

Or, at the very least, you've discovered something interesting and new. I'm happy to settle for that.

Random Thought

GIF isn't suitable for photographs or other high detailed images as you're limited to only 256 different colours in an image. There's one slight point of interest however - with each frame you can use a new block of 256 colours. Therefore, an animated GIF could reproduce a high detailed photograph outside of the normal restricted colour range even though the file format technically doesn't allow it.

  1. Given the C different colours used in the picture P, break C up into groups of 256 colours (i.e. C => C1, C2, C3, ..., Cn)
  2. For each frame of the animation, dot the image with the new selection of 256 colours.
  3. Stand back and marvel at your full 24 bit colour masterpiece that has the bit weight of a large elephant.

Bonus points if you progressively enhance the appearance of the image as more and more "colour layers" are loaded! If you do it properly, with a delay here and there, it should be a painting in the same style as A Sunday Afternoon on the Island of La Grande Jatte.

Update: Turns out this has been done: see the True-Color GIF example! Thanks to rcxdude from the Hacker News discussion thread for pointing it out.