Optimizing PNG for the web

GIF and I have been through a lot together. Over the years, we’ve argued over dithering algorithms, we’ve cried over Photoshop’s lossy compression and we’ve drunk the night away comparing palette reduction techniques. Then one day about four years ago, I built a site that required alpha-channel (semi transparent) images. I called up GIF: “Can you do this?”. GIF shuffled about, looked at his feet and dithered his palettes. “Um… no. Sorry.”

I spurned GIF and turned to PNG. PNG was gorgeous. She smiled at me and her IDATs twinkled. “I can do everything GIF does–and MORE!” She laughed, and teased me with her data chunks. She’d got me. I gave her images with alpha channels. She took them in her stride and returned highly compressed, lossless files. I gave her images for dithering; she returned beautiful optimized 8 bit palettes that put GIF to shame. She gave me everything I wanted and I loved her for it.

Everything with PNG was great–for a while. Then one day I discovered the truth. On an idle afternoon I had decided to compare the filesizes of an 8-bit PNG and an 8-bit GIF, compressed with exactly the same settings. The GIF was smaller! What!? My love affair with PNG was being rocked to it’s foundations. PNG had lied! How could she do this to me?

Well, the truth is that PNG didn’t lie at all and our love is as strong as ever. When I had compared those two files all those years ago, I was unaware of all the extra information that can be stored in PNG files. Useful data such as gamma settings, ICCP profiles, the date and time of the file creation and other text info can all squirreled away in its data chunks. Often this information is larger than the actual image data and can make the file unacceptably large for use on a website. So how do we get rid of this data and optimize our PNGs?

Use the correct colour depth

I create all my images in Photoshop and when I export images to PNG for web use, I use the Save for Web feature. This tool gives you lots of ways of saving your images by applying optimized palettes, dithering colours, etc.

Many web developers create optimized 8-bit PNGs for all solid colour imagery, unless it requires an alpha channel, in which case the 24 bit option is used. This is under the belief that an 8-bit optimized palette is always smaller than a 24-bit file with the same number of colours. Not true!

For images that only have a few colours, like a subtle gradient background, the 24-bit version will usually be smaller than the 8-bit version. This is because the 8-bit version has to store the palette information in a separate data chunk and this chunk is often larger than the image data itself. In a 24 bit PNG, the palette information is stored as part of the image data and often results in a smaller file:

24-bit versus 8-bit PNG

So when you’re exporting your image in Photoshop, or whatever package you use, experiment with 8-bit and 24-bit images to see which gives you the smallest file. Once you’ve got your PNGs exported, it’s time to optimize them.

Optimizing image data

Photoshop’s Save for Web feature does a reasonable optimization, but it’s far from perfect. We can improve on it.

If you’ve been in web development for any length of time, you’ll probably have heard of command line tools to optimize PNG image data. The two most popular are PNGout and PNGcrush. PNGout can produce slightly smaller files than PNGcrush but at the expense of speed: it’s far, far slower. As I opt for speed rather than the absolute best compression, I use PNGcrush. (Note that neither tool will change the original format of the file, so you can’t use them to create an 8-bit image from a 24-bit source. Make sure your PNGs are in the correct format before you start to play with these tools.)

Download PNGcrush and copy the executable into your Windows XP directory (sorry to non-Windows or Vista users, XP is all I use). I also recommend that you install the Command prompt here powertoy–or you can create the hack manually. This allows you to open a command prompt at any folder, by right clicking its name in Windows Explorer.

Once you’ve done this, open a command line at the folder where your PNG image resides and type:

pngcrush infile.png outfile.png

This will create a new optimised file, but only if the output is smaller than the input. Note that the new file might not be the smallest it could be as by default PNGcrush only tries a few compression methods. If you want to get the absolute best compression, you can ask PNGcrush to try all its methods, but this can take a very long time and doesn’t always yield much of a benefit. To do so, add the -brute option:

pngcrush -brute infile.png outfile.png

If you want to optimize all your images, you can do it in batch by creating a new file for every input file:

pngcrush -e -crushed *.png

This will create new, optimized files with the original filename plus the extra suffix “-crushed”. Alternatively, you can put the crushed images into a sub folder instead which will leave them with their original filename and won’t overwrite the original files:

pngcrush -d crushed-files *.png

Using any of these methods should have given you some smaller files.

Remove data chunks

Depending what application you’ve used to save your PNGs, there will be extra chunks you don’t need for web delivery. TweakPNG is a very useful tool that allows you to open a PNG file and view, add or delete the chunks in your PNG.

TweakPNG screenshot

For the web, there are only a few chunks you need in your files:

8-bit: IHDR, PLTE, IDAT, IEND
8-bit with 1 bit transparency: IHDR, PLTE, tRNS, IDAT, IEND
24-bit (with or without alpha): IHDR, IDAT, IEND

You can use TweakPNG to delete any other chunks. In particular, if you have a gAMA (gamma) chunk, ensure you remove that — it’s not large, but its removal will also fix colour discrepancy problems in Internet Explorer. (Note that if you’re creating PNGs for uses other than the web and you want them to look the same across PCs and macs, it’s best to leave the gAMA chunk intact and play with the gamma settings.)

TweakPNG is good for working on single files, but if you want to remove ancillary chunks from PNGs in batch, you can do that using PNGcrush. There are a number of command switches for doing this, but to remove all chunks I use:

pngcrush -e -crushed -rem allb -rem gAMA *.png

Combining optimisations in batch

Both of the above techniques should yield filesize reductions, but the best reductions come from both together. I use the following PNGCrush command which applies the optimisations we’ve seen so far and also some extra little tweaks:

pngcrush -fix -rem allb -rem gAMA -e .new *.png

This creates a “.new” file for every PNG in the folder. I then delete all the original PNGs and rename the .NEW files to PNG (this is slightly more dangerous than using the new folder option as you’re deleting your source file, but I’ve never had any problems yet):

del *.png
ren *.new *.png

Because this method creates a new file for every PNG (whether or not it was optimized), you can be sure you’ll not lose any files and it’s handy because you don’t have to manually change file names or move images form other folders.

These commands can be thrown into your Registry so that you get a “Crush” option displayed whenever you right-click a folder. It’s then a no-brainer to optimize a folder full of PNGs. If you’ve not played in your registry before, I don’t recommend you start now as mistakes on the Registry key we’ll be using can render Explorer inoperable. But if you’re confident, this is what you need to do:

  1. If you haven’t already done so, download PNGcrush and copy the executable to your Windows XP directory
  2. Click Start, then Run, type Regedit and press Enter
  3. Once Regedit has loaded, navigate to the following key: HKEY_CLASSES_ROOT\Directory\shell
  4. Right click “shell” and select “New -> Key” and name the new key “crush”
  5. With “crush” selected, double click the Default icon in the right hand window pane and enter a new value in the popup–this will be the name of the function as it appears on the context-sensitive menu in Windows explorer when you right click a folder. Mine is called “Crush all PNGs”
  6. Click OK, then right click select the “crush” entry again in the left hand pane
  7. Select “New -> Key” again and name the new key “command”
  8. With “command” selected, double click the Default icon and enter this command into the popup box:
    cmd.exe /k "cd %L && pngcrush.exe -fix -rem allb -rem gAMA -e .new *.png && del *.png && ren *.new *.png && exit"
  9. Click OK and you’re done. You can close Regedit
  10. Open Windows Explorer and navigate to any folder and right click its icon. You’ll see the Crush option you added. If you select it and there are any PNGs in that folder, they will be optimized

I’ve also made available a REG file with the above hack in it. I’ve tested it but it’s unsupported so use at your own risk!

PNGcrush Registry hack for folders in Windows XP

Summary

Optimizing PNGs for the web by removing unsued data is quick and easy with the right tools. The initial learning curve is small and once you’re set up, it’s a breeze. I hope some of this will help you be more productive in your PNG creation. If you have any feedback or other tips, please share them in the comments.

17 thoughts on “Optimizing PNG for the web

  1. Great article in and on itself, but for Heaven’s sake, learn the difference between “its” and “it’s”.

  2. Thank you so much for sharing this info. Smaller files are always good of course, but especially because it led me to discover and understand the cause of the color (gamma chunk!) problem I was coincidentally having just yesterday on a alpha-transparent gradient text overlay png in ie7…

  3. Pingback: Optimizing Your Website – Curve those hips into shape | Weales.com: Version 4Edit

  4. Can you recommend any tools for achieving similar on a Mac? Can we command lines in Terminal?

  5. HI, sorry, I don’t use Macs, so can’t recommend a solution there. But I’m pretty sure you’ll be able to find a solution via Google ;-)