Optimize 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?
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.
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 yield good file-size 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:
-
If you haven’t already done so, download PNGcrush and copy the executable to your Windows XP directory
-
Click Start, then Run, type Regedit and press Enter
-
Once Regedit has loaded, navigate to the following key: HKEY_CLASSES_ROOTDirectoryshell
-
Right click “shell” and select “New -> Key” and name the new key “crush”
-
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”
-
Click OK, then right click select the “crush” entry again in the left hand pane
-
Select “New -> Key” again and name the new key “command”
-
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"
-
Click OK and you’re done. You can close Regedit
-
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
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.