Dot Net Perls

PNG Compression - C# .NET

by Sam Allen

Problem

Optimize PNG images so that they consume fewer bytes. Go beyond a single piece of software and combine multiple aggressive optimization utilities. Benchmark the tool chain when used on popular websites. Present sample C# code.

Solution

I am not a PNG expert, but my research in the available options yielded some interesting projects. My goal was to chain many utilities together to get results better than any one utility alone. First I discuss the utilities and their options, and then I test them on popular websites.

Options used

I experimented with various options with the utilities. The following block shows the options I used. Note that I tested these repeatedly, but make no claim that they are the best. Note that I use /r with PNGOUT, which randomizes the starting table. This means it can keep improving things when you run it again.

// Option 1.
// Lossless compression.
optipng.exe file.png -o7
pngcrush.exe file.png -brute
advpng.exe -z -4 file.png

// Option 2.
// Lossless compression.
pngout.exe file.png /y /r

// Option 3.
// Lossy compression with PNGNQ.
// Uses neural network quantization.
pngnq.exe file.png

Read-world examples

How do popular websites do with their PNG compression? I don't have any information about what software they use, but it is clear they were compressed somehow. Here I examine two technology companies' websites, and then Wikipedia.

Microsoft's site. As a .NET developer, I pay a lot of attention to Microsoft, and I thought I would check out their compression on their homepage. I downloaded this image from Microsoft.com, which is the logo for Windows Media Player. I ran the PNG through the command-line compression utilities. Here are the results.

KeyBeforeAfter
Image
Size (bytes)22802001

Adobe's site. I am the last person who should tell Adobe how to compress images. However, I thought it would be interesting to see how their software performs in the "extreme compression" space. Can Fireworks compete with my tool chain of compression utilities? Here is what I found.

KeyBeforeAfter
Image
Size (bytes)47761661

Adobe's performance. I don't know the exact software Adobe compressed this image with, but it didn't do well. This indicates to me that the Adobe software doesn't come close to the several command-line programs I combined. Quantization was very effective here.

Wikipedia's site. Next I investigate Wikipedia's site, which is ranked as the 8th most popular in the world. How efficient is the Wikipedia icon, which we all know and love? Naturally it was stored as a PNG, so I attempted to compress it.

KeyBeforeAfter
Image
Size (bytes)1646212555

My website. This website (Dot Net Perls) has been using lossless compression for quite some time, but I decided to move to lossy compression with PNGNQ. Many website images do not require optimal quality, but simply good quality. I discarded compressed images with low (somewhat noticeable) quality loss.

KeyBeforeAfter PNGNQ
Zipped size in MB4.191.60

Example code

The following C# code shows some of the lines you will need to run the exes from a console or Windows Forms program. Keep the quantization, PNGOUT, and lossless parts separate. Using a thread would be excellent.

ProcessStartInfo info = new ProcessStartInfo();
//
// Lossy compression
//
{
    //
    // Quantize (change to 256 colors)
    //
    info.FileName = "pngnq.exe";
    info.Arguments = "\"" + fileName + "\"";
    info.WindowStyle = ProcessWindowStyle.Hidden;
    Process exe = Process.Start(info);
    exe.WaitForExit();
}
//
// Lossless compression
//
{
    //
    // Run OPTIPNG.
    //
    info.FileName = "optipng.exe";
    info.WindowStyle = ProcessWindowStyle.Hidden;
    info.Arguments = "\"" + fileName + "\" -o7";
    Process exe = Process.Start(info);
    exe.WaitForExit();
}
{
    //
    // Run PNGCRUSH brute.
    //
    info.FileName = "pngcrush.exe";
    info.WindowStyle = ProcessWindowStyle.Hidden;
    info.Arguments = "\"" + fileName + "\" -brute";
    Process exe = Process.Start(info);
    exe.WaitForExit();
}
{
    //
    // Run ADVPNG
    //
    info.FileName = "advpng.exe";
    info.WindowStyle = ProcessWindowStyle.Hidden;
    info.Arguments = "-z -4 \"" + fileName + "\"";
    Process exe = Process.Start(info);
    exe.WaitForExit();
}
//
// Run this code separately
//
{
    //
    // Run PNGOUT.
    //
    info.FileName = "pngout.exe";
    info.WindowStyle = ProcessWindowStyle.Hidden;
    info.Arguments = "\"" + fileName + "\" " + "/y /r";
    Process exe = Process.Start(info);
    exe.WaitForExit();
}

C# tips. Include "using System.Diagnostics;" to add the above code. Download the PNG compression utilities in their Windows 32-bit EXE form. Add them to your project, and select "Copy If Newer" to include them in the release version. Then execute the above code to run those executables.

Conclusion

Most websites today use very poor compression algorithms on their PNG images. Here I showed how Microsoft, Adobe, and Wikipedia could save money by reducing their bandwidth costs. These gains can be achieved with a couple mouse clicks using a program that implements the C# code I showed.

Industry standards. Here Microsoft and Adobe, each of which sells expensive graphics packages, neglected to apply optimal compression to their images. These images are likely viewed 100,000+ times per day. Popular software falls short when compared against PNGNQ, OPTIPNG, PNGCRUSH, PNGOUT, and ADVPNG combined together.

More on compression. Another article here deals with embedding 7-Zip and achieving excellent data compression. It uses the same approach here and has similar results.

Dot Net Perls
About
Sitemap
Source code
RSS
Compression
7-Zip Command-Line Examples
7-Zip Executable Tutorial
GZipStream Example Use
PNG Compression
7-Zip DEFLATE Compression Ratios
Recent
Pi
NGEN Installer Class
List Element Equality
DateTime Tips and Tricks
Remove HTML Tags From String
© 2008 Sam Allen. All rights reserved.