Run pngquant via a NativeProcess: C#, Unity & AS3/AIR

After our Unity runtime SpriteSheets generator, it is a good idea to optimize the generated pngs files.

pngquant is a command-line utility and a library for lossy compression of PNG images. The conversion reduces file sizes significantly (often as much as 70%) and preserves full alpha transparency. In other words this is a must have tool if you’re working with many pngs!

I used many times pngquant directly from the command line, but depending your project, you might need to run it directly inside your application! I didn’t find example for doing this, and it was way harder than I thought due to my lack of knowledge with batch and shell scripts! So here we go:

We use custom batch file (for Windows) and shell script (for Mac OS X) for launching pngquant. It will take the path to pngs to compress and overwrite them.

OS X:

#!/bin/sh
#!/usr/bin/env bash
#$ -N $2

DIR="$( cd "$( dirname "$0" )" && pwd )"

(cd "$DIR" && ./pngquant -f --ext .png "$1"/*.png)

Windows:

cd %~dp0
pngquant -f --ext .png "%~1"/*.png

Now a C# example for calling thoses scripts, note it works fine with Unity too:

System.Diagnostics.Process process = new  System.Diagnostics.Process();

string exec = "";
if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer)
	exec = "pngquant-windows.cmd";
else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer)
	exec = "pngquant-osx";
else
	throw new Exception("Platform not supported");

process.StartInfo.FileName = Application.dataPath + "/../../" + exec;
process.StartInfo.Arguments = Application.dataPath + "/../../png-to-compress";

// if your path have blank spaces use:
//process.StartInfo.Arguments = "\"" + Application.dataPath + "/../../png compress\"";

process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;

process.Start();

And finally an example with AS3 for AIR:

var process:NativeProcess = new NativeProcess();

var startupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
var file:File = File.applicationDirectory;

var exec:String = "";
if (Capabilities.os.indexOf("Windows") >= 0)
	exec = "pngquant-windows.cmd";
else if (Capabilities.os.indexOf("Mac") >= 0)
	exec = "pngquant-osx";
else
	throw new Error("doesn't work on " + Capabilities.os + " operating system");

file.nativePath = file.nativePath + "/../" + exec;
startupInfo.executable = file;

var processArgs:Vector.<String> = new Vector.<String>();
processArgs[0] = File.applicationDirectory.nativePath + "/../png-to-compress";
startupInfo.arguments = processArgs;

process.start(startupInfo);

Be sure to have a look to PngQuantNativeProcess’s git repository to be up to date!