PngOut is a command-line tool that can losslessly reduce the file size of your PNGs. In many cases, it can reduce the size of a PNG by 10-15%. I’ve even seen some cases where it was able to reduce the file size by over 50%.
There are several other PNG compression utilties out there, such as pngcrush and AdvanceCOMP, but I’ve found PngOut to be the best optimizer most of the time.
There’s an excellent tutorial on PngOut for first-timers. Running PngOut is pretty easy, simply run it once agaist your PNG:
PngOut.exe [image.png]
However, to get the best optimization of your images, you can run PngOut multiple times with different block sizes (eg, /b1024
) and randomized initial tables (/r
).
There’s a commercial program, PngOutWin that can run through all of the block sizes using multiple CPU cores, but I wanted something free that I could run from the command line.
To aid in this, I created a simple DOS batch script that runs PngOut through 9 different block sizes (from 0 to 8192), with each block size run multiple times with random initial tables.
While the first iteration of PngOut does all of the heavy lifting, I’ve sometimes found that using the different block sizes can eek out a few extra bytes (sometimes 100-bytes or more than the initial pass). You may not care about optimizing your PNG to the absolute last byte possible, but I try to run any new PNGs ready for production in my websites and mobile apps through this batch script before they’re committed to the wild.
Running PngOutBatch is as easy as running PngOut:
PngOutBatch.cmd [image.png] [number of iterations per block size - defaults to 5]
PngOutBatch will show progress as it reduces the file size. Here’s a sample compressing the PNG logo from libpng.org:
Blocksize: 0 Iteration #1: Saved 2529 bytes Iteration #2: No savings Iteration #3: No savings Iteration #4: No savings Iteration #5: No savings Blocksize: 128 Iteration #1: Saved 606 bytes Iteration #2: Saved 10 bytes Iteration #3: No savings Iteration #4: Saved 2 bytes Iteration #5: No savings Blocksize: 192 Iteration #1: No savings Iteration #2: No savings Iteration #3: No savings Iteration #4: No savings Iteration #5: No savings Blocksize: 256 Iteration #1: Saved 1 bytes Iteration #2: No savings Iteration #3: Saved 5 bytes Iteration #4: Saved 11 bytes Iteration #5: No savings Blocksize: 512 Iteration #1: No savings Iteration #2: No savings Iteration #3: No savings Iteration #4: No savings Iteration #5: No savings Blocksize: 1024 Iteration #1: No savings Iteration #2: No savings Iteration #3: No savings Iteration #4: No savings Iteration #5: No savings Blocksize: 2048 Iteration #1: No savings Iteration #2: No savings Iteration #3: No savings Iteration #4: No savings Iteration #5: No savings Blocksize: 4096 Iteration #1: No savings Iteration #2: No savings Iteration #3: No savings Iteration #4: No savings Iteration #5: No savings Blocksize: 8192 Iteration #1: No savings Iteration #2: No savings Iteration #3: No savings Iteration #4: No savings Iteration #5: No savings D:\temp\test.png: SUCCESS: 17260 bytes originally, 14096 bytes final: 3164 bytes saved
The first block size (0) reduced the file by 2529 bytes, then the 128-byte block size further reduced it by 606, 10 then 2 bytes. The 192-byte block size didn’t help, but a 256-byte block size reduced the file size by 1, 5 then 11 more bytes. Larger block sizes didn’t help, but at the end of the day we reduced the PNG by 3164 bytes (18%), and 635 bytes (25% more) than if we had only run it once.
The PngOutBatch.cmd script is hosted at Gist.Github if you want to use it or contribute changes.