Lose The Wait: Optimizing GIF Images

Posted: February 17, 2012 at 8:46 pm

Our Lose the Wait series is all about improving the performance of your web applications. As we have mentioned, a great way to lose the wait is to lose the weight, as in the weight of your page content. In our last post, we talked about using HTTP compression to reduce the size of the data that needs to be sent to the client, as well as the challenges that are involved. Now let’s shift our attention from text content to images.

Images make of the majority of content on the web. According to the HTTP Archive, the total size of an average web page and its supporting content is 968kB. Of that, 601kB, or 62% of the total amount, is image content. Understand images and how to optimize them are skills for any frontend performance advocate. To do this, we start by exploring the GIF image format and how to optimize it.

GIF is a lossless image format created by CompuServe in the late 1987. This makes GIF the oldest image format in common use on the web today. GIF is a palette based image format, allowing an image to contain up to 256 distinct colors defined from a possible 16,000,0000 colors (2^24). GIF images also support binary transparency. This means a pixel of the image can be completely transparency, showing the background behind the image, or completely opaque, showing the color value for that pixel. GIFs feature the ability to contain multiple graphic images inside of a single file

Due to their age, simple nature, and a widespread support, GIFs are widely present on the Internet. According to the HTTP Archive, 33% of all images on the web use the GIF format. Due to their prevalence, understanding how to structure optimize GIF images is an important part of understanding.

The Structure of a GIF Image

To understand how to optimize GIF images, we need to first explore the structure of the image format to identify which areas can be streamlined or optimized.

GIF File Format Structure

GIF are composed of a six byte header, identifying the file format and version. A six byte Logic Screen Descriptor follows, specifying the dimensions of the image, number of colors used, and other flags. The next data structure in a GIF file is the Global Color Table. This defines the color values for each of the up to 256 distinct colors which can referenced by the graphics data.

Now we get to how the content of an image is saved inside the GIF format. This happens in the Graphic Image Data sections. If the GIF is an animated GIF it will contain multiple Graphic Image Data sections for the different frames of animation. If it is a static, non-animated GIF, there is only one Graphic Image Data section. Each Graphic Image Data section is composed of a few other pieces of data. Obviously, it contains the graphics data that represent the image or a frame of animation. It can also optionally contain a local color palette that is specific to that piece of image data. This means that frame 1 of an animation can be composed of colors from a palette of 256 colors, and frame 2 can be composed of a different palette of colors. Local color palette data override the palette in the Global Color Table. In fact, the Global Color Table is actually optional, and each Graphic Image Data section can define it own palette. When you are dealing with a static image this is not really necessary, as it doesn’t matter whether the palette information is stored in the Global Image Data of the single Graphic Image Data section. As we will see later, this can be used to optimize animation.

The graphics data inside of a Graphic Image data section is a bitmap of pixel where each pixel value is a reference to the color palette which defines the actual red, green and blue values which represents the color. This pixel data can be sorted and stored in different ways to enable features like interlacing. All of this pixel data is compressed using the Lempel-Ziv-Welch (LZW) lossless data compression algorithm.

GIFs also have a number of other, optional data sections that can be present. Comments are common section, as are so-called "Application Extension" sections. These sections can be used to a variety of application specific information. The commonly implemented Netscape 2.0 Application Extension which enabled the looping of GIF animations. Adobe products store XMP image metadata inside of The Application Extensions. Embedded thumbnails can be stored in Application Extensions. There are also lesser used GIF features which use additional data sections. For example, the Graphic Image Data section can contain other data sections such as a Plain Text Data section, which allows for text to be rendered on top of an image similar to a closed captioning or subtitling system for video files.

GIF Optimization opportunities

Now that I’ve told you way more than you ever wanted to know about the internals of a GIF image, we can think about optimizing. There are several aspects of the GIF image format that create opportunities to reduce file size while retaining image quality:

  • The LZW compression algorithm has its roots in the 1970s. While impressive for its time, its performance and compression ratios have been eclipsed by more modern lossless compression algorithms. Using an image format with a better compression.
  • Palettes can contain more color definitions than actually used by the image
  • The size of palette entries can be inefficient when the image contains less than 128 colors.
  • GIF comments, metadata, and (most) Application Extension sections don’t contribution to the rendering of the graphic data. This data can be removed.

Funny enough, the GIF specification even suggests avoiding Application Extensions saying:

[Not using Application Extensions] is recommended in favor of using Application Extensions, which become overhead for all other applications that do not process them.

“Overhead” is just a fancy way of saying wasted bytes!

GIF vs. PNG

PNG images are also a lossless image format that very closely mirrors GIF images. The PNG format was defined 10 years after the GIF format allowing PNG images address many of the shortcomings of GIF images, such as:

  • PNG’s DEFLATE algorithm achieves better compression than GIF’s LZW algorithm
  • PNG images supports a precompression filter step, which rearranges graphic data before compression to maximize redundancy and thus improve the efficiency of DEFLATE compression. GIF does not have this feature.
  • The size of PNG palette entries can be smaller than the corresponding GIF palette entries on images with less than 256 colors.
  • PNG’s ancillary data sections support compression allowing their overall size to be reduced.

Additionally, programs that convert from a GIF image to a PNG image, such as gif2png, focus only on converting graphical data. Comments, metadata, embedded thumbnails, Application Extensions, and other non-graphical information present in a GIF are not transferred over into the resulting PNG. In other words, converting from a GIF to a PNG sheds all this "excess baggage" in addition to better compressing the graphical data. All of these factors mean that converting a GIF image to a PNG almost always results in a smaller image.

Bigger as PNG?

PNG images can sometimes be larger than the source GIF image. There are a few reasons for this, some of which can be fixed. Ensure the PNG you convert has an 8bit color depth. PNG supports millions of distinct colors in an image, whereas GIF only supports 256 distinct colors. Since you are converting from a source with a maximum of 256 colors, there is no need to support a larger color depth. If you do, it can needlessly result in a larger file.

It is still possible for GIF images to be smaller than PNG images. This usually only occurs for extremely small images, where the actual graphical data is quite small. For these images, the overhead of various headers and sections inside of the GIF or PNG image contribute to the overall size more so than the graphics data. In this case, very simple GIFs can be smaller than PNGs. In my experience, these extremely small GIF images are used by websites as spacer images or as the response for web services beacons. You shouldn’t be using spacer GIFs at all, and you should be returning HTTP 204 No Content responses instead of using tiny images. In short, if you find any GIFs on your website that are smaller as GIFs than PNGs, you are probably doing something else that is wrong.

The Savings of Converting to PNG

To determine the average savings of converting to PNG, I extract the 2547 GIF images that were recently downloaded by Zoompf’s scanner by users of our free performance scanning service. I then converted these from a GIF to a PNG using Optipng, which conveniently converts to a PNG image and then attempts to losslessly optimize the PNG image in a single step. The median size of the GIF images was 6900 bytes. The median size of the result PNG images was 5546 bytes. This means the median savings of converting all GIFs to PNGs is 21.07%. That’s a pretty awesome result and this aligns nicely with Stoyan’s analysis from 2009. You can download my test results here.

Animated GIFs

So far we have been talking about static GIFs, but what about animated GIFs? Luckily, the use of annoying, eye bleeding under construction GIFs has past us by (a fact for which I, and all of you, should thank whatever God or gods you pray to, every single day). However animated GIFs are still with us, thanks to the ever present status thumper!

While converting to PNG images provides a simple, easy way to bulk optimize GIFs, what can be done for animated GIFs? PNG does not support animation, so that is not an option.

Before you can optimize a GIF you need to know whether it’s animated or not. Ideally we want an easy way to do this from the command line so we can sort and optimize our GIF images and animations in bulk automatically as part of a script. Luckily the identify command of ImageMagick can help us out. The following:

identify [file] | head -n 1 | grep "\] GIF"

This will run identify on the command, and look for the text which indicates this GIF image contains multiple Graphic Image Data sections and thus is part of an animation. Now that we can sort the wheat from the chaff, we can start optimizing animated GIFs.

The list of optimizations that can be applies to animated GIFs is, in many ways, a superset of the optimizations for a static GIF. While you can’t gain the advantage of PNG’s DEFLATE compression algorithm you can:

  • Remove metadata, or unused palette entries from a GIF and write a better optimized GIF.
  • Combine or generalize local palette information in individual Graphic Image Data sections into the Global Color Table.
  • Reuse existing animation frames.
  • Minimize what is changing between animation frames, reducing the size different Graphic Image Data sections.

Gifsicle is a great command line tool which can, among other things, perform several of these optimizations automatically. Its free, open source, and easy to use. Because its a command line tool, this Gifsicle can be scripted for bulk optimization operations or bundled into build scripts. To optimize a GIF, this is all:

gifsicle -O2 orig-animation.gif -o new-animation.gif

While Gifsicle can automatically optimize GIFs, it can only do some of the optimizations discussed above with varying degrees of success. For example, Gifsicle does a great job detecting and combining duplicate local palette information into the Global Color Table. It does a good job removing GIF comment sections, but does a poor job detecting and removing Application Extensions, embedded thumbnails, and XMP metadata. It does a reasonable job trying to optimize differences between animation frames. Better optimization can be achieved by manually reviewing the animation to detect frames which can be reused as well as reduce the total changes applied to an image between animation frames.

I am want to sound like I’m criticizing Gifsicle. Detecting and applying the optimizations discussed above is not easy to do, let alone automate. Gifsicle is an awesome tool and everyone should use it. I just want to be clear that optimizing Animated GIFs is not as easy or straight forward as stripping meta data from a static GIF. Manual examination or optimization may be required to get the results you expect.

Conclusions

There are numerous aspects of the GIF image format which allow for lossless optimizations to reduce file size while maintaining image quality. Converting to PNG is a nice, universal way to do this. Animated GIFs however, cannot be converted. Instead you can use Gifsicle to automate some optimization and use hand optimization techniques.

Want to see what performance problems your website has? Unoptimzied GIF Image and Unoptimized Animated GIF Image are just 2 of the nearly 400 performance issues Zoompf detects when testing your web applications. You can get a free performance scan of you website now and take a look at our Zoompf WPO product at Zoompf.com today!

Choosing PNG8 Candidate Images

Posted: February 4, 2010 at 5:48 pm

Have you heard about PNG8 yet? No? Well, PNG8 is a PNG image that is used an indexed palette of 256 colors instead of a true color PNG which can support several million different colors. There has already been a number of excellent articles and blog posts written about PNG8. These articles have discussed things about PNG8 such as its benefits, how to create PNG8, and using them across different browsers.

But this article isn’t about any of that.

This article is about how to choose PNG images that are good candidates for converting to PNG8. Historically this has not been an easy or a straight forward decision.

We already know that PNG images can be optimized. Crunching PNGs (using pngcrush, or optipng, etc) to reduce their size is a lossless operation. This process removes unnecessary data chucks like comments and recompresses the DEFLATE streams using tweaked settings. When optimizing images by crunching them none of the image data changes. The number of colors in the image does not change and their color values and hues are exactly the same.

But converting a true color PNG to a PNG8 image is a lossly operation. You lose data. PNG8 images can have at most 256 distinct colors while true color PNGs can have several million. Because of this not all PNG images should be converted to PNG8. Some images look absolutely horrible when converted. Working with our clients we have created two guidelines to evaluate whether a PNG image can be converted to PNG8 without any noticeable loss in quality. This is a easier and scalable solution than converting all of the PNG images on your website and then manually verifying the resulting PNG8 images are acceptable.

Guideline #1: Number of Colors

To understand the impact of limiting a PNG image to only 256 distinct colors we must understand how many colors PNG images typically have. Converting to PNG8 can quite significantly reduce the number of colors in the image. A PNG8 version of a true color PNG image with 1,000 distinct colors has 25% as many colors of the original image. A PNG8 version of a true color PNG image with 10,000 colors has only 2.5% as many colors of the original image! So the number of distinct colors in the image (and thus the number of distinct colors you are destroying when converting to PNG8) has a huge impact on how acceptable the resulting PNG8 will be. In plain terms the PNG8 version of a 10,000 color PNG image will look worse than the PNG8 version of a 1,000 color PNG image.

While true color PNGs can have several million distinct colors they rarely do. (If you have a PNG image that has even a few tens of thousands of colors it should probably be saved as a JPEG instead). Examining a sample set of PNG images we found that PNGs tend to have several thousand distinct colors. We also have found that images containing only a few thousand colors will easily convert to a PNG8 image without any noticeable loss in quality. Consider the Zoompf logo:

The Zoompf logo is a true color PNG image consisting of 1999 distinct colors. That sounds like a lot. Let’s convert this to a PNG8 image using pngquant. Here is the original logo and the PNG8 version of the logo side by side for comparison. The original logo is on the top and new PNG8 version is on the bottom.

Wow, They look virtually identical even though the PNG8 version’s file size is over 50% smaller and uses 87% less colors than the original. Only if you zoom in very close do you start to see some differences. The greens are slightly lighter and the gray in the swoosh lines are a little different.

We have found that images will less than 2500-3000 distinct colors tend to provide the best trade off in terms of maximum reduction in file size without any noticeable difference to quality. This is purely subjective. There are some true color PNG images with 6,000 colors or more that look just fine when converted to PNG8. You should experiment and see what works best for you.

Guideline #2: Image Dimensions

Another factor is the dimensions of the image. Small images, even if they have more than 7,500 distinct colors, convert to PNG8 with not visible loss of quality. This is because your brain has trouble detecting some many similar colors in such a small area. Consider this true color PNG image of a cat.

This picture consists of 8,853 distinct colors. That’s an enormous amount when you realize this image has only 9900 pixels total! Almost every pixel is a completely unique color. That’s tons of distinct colors given the area they are displayed in. Again we use pngquant to convert this cat image into a PNG8 image and compare it to the original. The original image is on the top and PNG8 version is on the bottom.

Again, they look virtually identical even though the PNG8 version’s file size is over 50% smaller and uses 97.2% less colors than the original. As if the logo, only if you zoom in very close you can start to see the differences between the original image and the PNG8 version.

We have found that images less than 100 pixels by 100 pixels, or an image whose area is less than 10,000 pixels can easily be converted into a PNG8 without any noticeable difference in quality. This is a purely subjective guideline. Some larger true color PNG images look just fine when converted to PNG8.

Using the Guidelines

These guidelines can be used separately. A PNG image does not have to be both small and not using many colors to be a good candidate for converting to PNG8. As as example, Graphviz, a program that generates node-and-edge style graphs, regularly produces images that are thousands of pixels wide by thousands of pixels tall. This would violate our image area guideline. However these images usually contain a few hundred colors. This satisfies our color count guideline. Sure enough, converting the output of Graphviz to PNG8 saves a lot of space with no perceivable loss of quality.

PNG8 and CSS Sprites

A lot of times people want to combine PNG8′s advantage of a very small file size with CSS Sprite’s’ advantage of reducing the number of HTTP requests. At first glance this makes a lot of sense. Individual CSS background images inside of the sprite are often small images, fitting our image dimensions guideline. Also CSS background images are often icon-style images used on buttons, toolbars, etc. This means each individual image tends to have only several dozen distinct colors fitting our image colors guideline.

Unfortunately this is looking at the trees instead of the forest. That’s because a CSS Sprite saved as a PNG8 image has to use only 256 distinct colors for all the sub-images inside the sprite. So while each sub-image that makes up the CSS Sprite might look fine as an individual PNG8 image (each with its own 256 color palette) all the sub-images together in a single PNG8 CSS Sprite using a single common 256 color palette could not. This is especially true with gradients and othe graphics that use different shades for color transitions. In fact, Stoyan pointed out a recent article talked about how converting a CSS Sprite to PNG8 caused a very noticeable loss in quality. The solution was the hand edit the PNG8′s 256 color palette to preserve as many shades of the gradient as possible to improve quality.

Zoompf Color Counter

Since so much savings can occur from converting from PNG24 to PNG8 where appropriate, developers are left with the challenge of trying to quickly find candidate images. While Zoompf’s free web performance scanning service will detect candidate images developers will also want to test images that are not yet uploaded or test images on a website that is not yet in production. To help developers, Zoompf has released the Zoompf Color Counter.

Screen shot of Zoompf's Color Counter program

Zoompf Color Counter is a Windows program that will analyze an image and tell the user how many distinct colors it has. Simply open an image inside Zoompf Color Counter or drag and drop an image on top of Zoompf Color Counter to learn the number of distinct colors. Download Zoompf Color.

Summary

There are a lot of blog posts and articles on the Internet about how converting true color PNG images into PNG8 images is an excellent optimization technique. However knowing how to choose true color PNG images that are good candidates to convert to PNG8 can be difficult and time consuming. In this post we provide 2 guidelines to help:

  1. Images with less than 2500 to 3000 distinct colors can usually be converted to PNG8 without any noticeable differences
  2. Image less than 100 pixels by 100 pixels (or an image whose area is less than 10,000 pixels) can usually be converted to PNG8 without any noticeable differences.

In addition we have release Zoompf Color Counter to help developers find candidate images. Remember that converting to PNG8 is a lossly process. How much loss is tolerable will vary from person to person. You should use our guidelines but also experiment to see if you will tolerate more. Finally, be careful converting your CSS Sprites image into PNG8, especially if you use images with gradients.

Want to see what performance problems your website has? Finding Candidate PNG8 Images based on color count or image dimensions are just two of the 300+ performance issues Zoompf detects when checking your web applications. You can sign up for a free mini web performance assessment at Zoompf.com today!