Newer Older

The Tiniest GIF Ever

Yesterday I was base64-encoding an image so I could send it to CouchDB to test some code I'm working on for a client. It reminded me of something I did a while back to set cookies on a remote server.

Basically, a small PHP script was put on the remote server which took a couple of GET parameters and set some cookies based on their values. The script then output a 1x1 transparent GIF. A PHP script on the local server generated an IMG tag which linked to this image and set the parameters based on the COOKIES on the local server.

This process also had to happen in the reverse direction, so I had to send the script to developers on the other side. I wanted to keep it as simple as possible, so I put the actual image contents in the PHP file as a base64 encoded string. I used the GIMP to generate the smallest transparent GIF I could manage so there wouldn't be too huge of a nasty string in the file. I came up with something like the following:

    <?php
setcookie('foo', $_GET['foo']);
header('Content-Type: image/gif');
echo base64_decode('R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
?>

Remembering this got me to wondering, how small could you make a GIF? The file generated by the GIMP was only 43 bytes, but it seemed to be that you should be able to make a file which is representing a single pixel a bit smaller than that.

So, with equal parts of determination and derangement, I set about finding out.

Though of somewhat dubious usefulness, I managed to generate a perfectly valid GIF of only 26 bytes in length, which has the potential to display completely differently in various different software.

Read on to see how I found my way to this point.

Starting point: the GIF89a specification

The file generated by the GIMP, as I said, was 43 bytes long. You can find it here: tinytrans.gif

To understand what was taking up all those bytes, I read through the GIF89a Spec. The file tinytrans.gif above consists of the following sections:

Making a smaller GIF

Based on the required structures for a transparent GIF, it turns out that 43 bytes is pretty close to as small as you can get.

But, I managed to figure out one trick to make it a bit smaller. It's mentioned in the standard that it is optional to have a global color table. Of course, it's undefined as to what happens when you make a GIF without a color table at all (there are also optional local color tables per image block).

When you have a color table index defined as transparent, however, GIF decoders don't seem to care that there isn't actually a color table.

So I changed the logical screen descriptor to indicate there was no global color table and removed the table itself, saving a total of six bytes, bringing the file size down to a mere 37 bytes.

Here it is in all its glory: handtinytrans.gif

Interestingly enough, Wordpress gave me a lovely list of error messages of GD complaining that this isn't a valid GIF file, despite the fact that Firefox and the GIMP both open and display (is it "displayed" when it's transparent?) the file just fine.

So there you go, the tiniest transparent GIF possible (if you can make one smaller, let me know).

But of course, there's room still for the tiniest GIF ever.

Even smaller, no longer transparent

To make it even smaller, I looked to the biggest remaining "optional" block in the image, the graphic control extension. If you don't need transparency, this block is no longer needed, and that's another 8 bytes you can take away.

Sadly, I wanted a whilte image, and I couldn't get it to come out white without adding the global color table back in, so I only managed to trim 2 bytes off of the file.

Still, 35 bytes is indeed smaller: handtinywhite.gif

The tiniest possible GIF

If I remove the constraint of having the image be white (or any color I choose), I can make it even smaller, though admittedly this becomes much less useful.

I removed both the global image table and the graphic control extension, and then no matter what color the pixel originally was, it comes out black. From there, I took it a step further, because the standard never says you have to actually set any pixels in the image, I removed the LZW encoded image data. I left the required lzw code-size header and block terminator, because without those Firefox and the GIMP both complained it wasn't a valid GIF, and then I had it.

The tiniest GIF ever, 26 bytes: handtinyblack.gif

Despite the fact that this is called "handtinyblack.gif", black is just the color that the GIMP chooses to display when there's no global color table. It's stated in the spec "If no color table is available at all, the decoder is free to use a system color table or a table of its own."

This means that any GIF decoder is free to pick whatever color it wants for this image. Opening this image in Firefox at various different times, it has show up as shades of blue, green and brown, as well as transparent if set as a background image.

blog comments powered by Disqus