The PNGQuant is pretty easy to use and understand.
Creating an instance of the class
The PNGQuant class doesn't expect any value in the constructor, so it can be easily instantiated in a single line:
<?php
$instance = new PNGQuant();
Note that the instantiation in the previous example assumes that you have already imported the class either by using require_once
or if you use composer, the autoloader. If the class isn't included, please read the docs about the installation.
The generated instance will have all the following methods:
buildCommand
This method is normally used only internally by the class. However, if you want to use it for debug or testing purposes it's available publicly. It generates a string with the command that will be executed using system
:
<?php
$instance = new PNGQuant();
$instance
->setImage("/a-folder/image-original.png")
->setOutputImage("/a-folder/image-compressed.png")
->overwriteExistingFile()
->setQuality(50,80);
// The command to execute of the previous code will be:
// pngquant /a-folder/image-original.png --output "/a-folder/image-compressed.png" --force --quality 50-80
echo $instance->buildCommand();
The structure of the command is modified by all the methods of the class.
disableDithering
This method disables the usage of dithering. Dithering is used in computer graphics to create the illusion of "color depth" in images with a limited color palette, a technique also known as color quantization.
<?php
$instance = new PNGQuant();
$instance->disableDithering();
The equivalent command argument in the CLI is --nofs
.
execute
This method executes the built command with all the methods, compressing finally the image with pngquant. It returns the exit status code generated by pnquant (an integer). The success status code of pngquant is by default 0, other value is sign of an error (see getErrorTable
for more information about the status code):
<?php
$instance = new PNGQuant();
// Set the path to the image to compress
$exit_code = $instance->setImage("image-original.png")
// Set the output filepath
->setOutputImage("image-compressed.png")
// Overwrite output file if exists, otherwise pngquant will generate output ...
->overwriteExistingFile()
// As the quality in pngquant isn't fixed (it uses a range)
// set the quality between 50 and 80
->setQuality(50,80)
// Execute the command
->execute();
// if exit code is equal to 0 then everything went right !
if(!$exit_code){
echo "Image succesfully compressed";
}else{
echo "Something went wrong (status code $exit_code) with description: ". $instance->getErrorTable()[(string) $exit_code];
}
getRawOutput
This method allow you to execute the build command with the methods, however instead of creating directly the image in some path, you can retrieve the binary data of the generated image in a variable.
A known bug of PHP and PNGQUANT is that you can retrieve the raw data from an image with the providen snippet by the official pngquant website here, however to make it work, our wrapper will create a temporary file in the tmp directory of your operative system, then it will retrieve its content and you can do whatever you want with it:
<?php
$instance = new PNGQuant();
$result = $instance
->setImage("/image/to-compress.png")
->setQuality(50,80)
->getRawOutput();
// Result is an array with the following structure
// $result = array(
// 'statusCode' => 0,
// 'tempFile' => "/tmp/example-temporal.png",
// 'imageData' => [String] (use the imagecreatefromstring function to get the binary data)
//)
// Get the binary data of the image
$imageData = imagecreatefromstring($result["imageData"]);
// Save the PNG Image from the raw data into a file or do whatever you want.
imagepng($imageData , '/result_image.png');
getErrorTable
This method returns an array, the error table. The error table is an associative array (key[error code] => value[error identifier]) with the following structure:
array(
"0" => "SUCCESS",
"1" => "MISSING_ARGUMENT",
"2" => "READ_ERROR",
"4" => "INVALID_ARGUMENT",
"15" => "NOT_OVERWRITING_ERROR",
"16" => "CANT_WRITE_ERROR",
"17" => "OUT_OF_MEMORY_ERROR",
"18" => "WRONG_ARCHITECTURE", // Missing SSE
"24" => "PNG_OUT_OF_MEMORY_ERROR",
"25" => "LIBPNG_FATAL_ERROR",
"26" => "WRONG_INPUT_COLOR_TYPE",
"35" => "LIBPNG_INIT_ERROR",
"98" => "TOO_LARGE_FILE",
"99" => "TOO_LOW_QUALITY"
);
You can use the error table to identify if there was an error with the execution of the command using the execute method:
<?php
$instance = new PNGQuant();
// Set the path to the image to compress
$exit_code = $instance->setImage("/a-folder/image-original.png")
// Set the output filepath
->setOutputImage("/a-folder/image-compressed.png")
// Overwrite output file if exists, otherwise pngquant will generate output ...
->overwriteExistingFile()
// As the quality in pngquant isn't fixed (it uses a range)
// set the quality between 50 and 80
->setQuality(50,80)
// Execute the command
->execute();
// if exit code is equal to 0 then everything went right !
if(!$exit_code){
echo "Image succesfully compressed";
}else{
echo "Something went wrong (status code $exit_code) with description: ". $instance->getErrorTable()[(string) $exit_code];
}
Remember that the error table is an associate array with string keys (therefore you need to convert the exit code to a string).
overwriteExistingFile
This method allows you to overwrite the generated image (in case that it already exists) without throw errors (use with caution). If this option is not used, the command will generate output (interpreted as an error) because pngquant won't write on an existing file:
<?php
$instance = new PNGQuant();
$instance->overwriteExistingFile();
The equivalent command argument in the CLI is --force
.
posterize
Reduce precision of the palette by number of bits. Use when the image will be displayed on low-depth screens (e.g. 16-bit displays or compressed textures in ARGB444 format):
<?php
$instance = new PNGQuant();
$instance->setImage("image-original.png")
->setOutputImage("image-compress.png")
// For ARGB444
->posterize(4)
->execute();
removeMetadata
This methods allows you to remove the metadata of the png file. Don't copy optional PNG chunks (Metadata is always removed on Mac when using Cocoa reader).
<?php
$instance = new PNGQuant();
$instance->setImage("image-original.png")
->setOutputImage("image-compress.png")
->removeMetadata()
->execute();
The equivalent command argument in the CLI is --strip
.
setBinaryPath
This method specifies the path where the binary of pnquant (e.g the pngquant.exe file in windows) is located. The wrapper assumes that pngquant is accesible on the path to execute the command, therefore if it isn't, change the path:
<?php
$instance = new PNGQuant();
// Change the path to the binary of pngquant
// for example in windows would be (with an example path):
$instance->setBinaryPath("C:\\Users\\sdkca\\Desktop\\pngquant.exe");
setCustomExtension
This method allows you to set a custom extension (suffix) for the output filename in case that you don't set an output filename (setOutputImage). By default, if you don't provide the output filename pngquant uses the same filename and -or8.png or -fs8.png to save the compressed file:
<?php
$instance = new PNGQuant();
// Should generate the compressed file "image-original-or8.png" or "image-original-fs8.png"
$instance->setImage("image-original.png")
->overwriteExistingFile()
->setQuality(50,80)
->execute();
You can change this suffix with setCustomExtension
:
<?php
$instance = new PNGQuant();
// Should generate the compressed file "image-original-ourcodeworld.png"
$instance->setImage("image-original.png")
->setCustomExtension("-ourcodeworld.png")
->overwriteExistingFile()
->setQuality(50,80)
->execute();
setDitheringLevel
This method allows you to control the level of dithering used by pngquant. It needs to be a value from 0 (none) to 1 (full dithering) :
<?php
$instance = new PNGQuant();
$instance->setDitheringLevel(0.5);
setImage
This method specifies the path (recommendable to be absolute to prevent errors) to the image that will be compressed:
<?php
$instance = new PNGQuant();
$instance->setImage("/var/www/project/image-original.png");
setOutputImage
This method specifies the path (recommendable to be absolute to prevent errors) to the output image that will be generated:
<?php
$instance = new PNGQuant();
$instance->setOutputImage("/var/www/project/image-compressed.png");
The equivalent command argument in the CLI is --output
.
setOption
This method is normally used only internally by the library to build the command. It can be used to add options that may not be added in this library but that you need to add to the command.
It expects as first parameter the identifier of the option (string), as second parameter the value of the option, as third parameter a boolean that defines if the value should be set as argument or as value (--optionName=value
or --optionName value
) and as fourth parameter a boolean that defines if the given value should be escaped using escapeshellarg
.
Add option to command
To add an option without value use:
<?php
$instance = new PNGQuant();
$cmd = $instance
->setOption("--option")
->buildCommand();
// Outputs: pngquant --option
echo $cmd;
Add an option with value
<?php
$instance = new PNGQuant();
$cmd = $instance
->setOption("--option", 5)
->buildCommand();
// Outputs: pngquant --option=5
echo $cmd;
Add an option with value as an argument
<?php
$instance = new PNGQuant();
$cmd = $instance
->setOption("--option", 5, true)
->buildCommand();
// Outputs: pngquant --option 5
echo $cmd;
Escape a value of an option
This argument comes in handy if you use paths as value:
<?php
$instance = new PNGQuant();
// Escape and option as value
$cmd = $instance
->setOption("--option", "c:\\path\\to\\somewhere", true, true)
->buildCommand();
// Outputs: pngquant --option "c:\path\to\somewhere"
echo $cmd;
// Don't escape and option as argument
$cmd2 = $instance
->setOption("--option", "c:\\path\\to\\somewhere", false)
->buildCommand();
// Outputs: pngquant --option=c:\path\to\somewhere
echo $cmd2;
In short words, if an option of pngquant isn't supported by the library, then you can simply add it using this method. The following example shows how you can build the same command built with helper methods of the library with setOption:
<?php
$instance1 = new PNGQuant();
$instance2 = new PNGQuant();
$cmd = $instance1->setImage("image-original.png")
->posterize(4)
->setSpeed(0.5)
->overwriteExistingFile()
->buildCommand();
// Outputs :
// "pngquant image-original.png --posterize=4 --speed 0.5 --force"
echo $cmd;
// Build the previous command with setOption
$cmd2 = $instance2->setImage("image-original.png")
->setOption("--posterize", 4)
->setOption("--speed", 0.5, true)
->setOption("--force")
->buildCommand();
// Outputs too :
// "pngquant image-original.png --posterize=4 --speed 0.5 --force"
echo $cmd2;
setQuality
This method allows you to change the range of quality that should be used for the image in pngquant. The function expects 2 arguments in range 0 (worst) to 100 (perfect), similar to JPEG. pngquant will use the least amount of colors required to meet or exceed the max quality. If conversion results in quality below the min quality the image won't be saved (if outputting to stdin, 24-bit original will be output) and pngquant will exit with status code 99.
<?php
$instance = new PNGQuant();
$instance->setImage("image-original.png")
->setOutputImage("image-compress.png")
// Set the quality of the image from 50 to 80
->setQuality(50,80)
->execute();
If the arguments of method aren't set, the default values will be 60 and 80.
setSpeed
The speed quality trade-off from 1 (brute-force) to 11 (fastest). The default is 3. Speed 10 has 5% lower quality, but is 8 times faster than the default. Speed 11 disables dithering and lowers compression level:
<?php
$instance = new PNGQuant();
$instance->setImage("image-original.png")
->setOutputImage("image-compress.png")
->setQuality(50,80)
// Super fast = lower compression level
->setSpeed(11)
->execute();
skipIfLarger
This method will make that pngquant don't write converted files if the conversion isn't worth it:
<?php
$instance = new PNGQuant();
$instance->skipIfLarger();
Note
If the output image already exists, then pngquant will throw an error (generating output). It's recommendable to use always the setOutputImage together with the overwriteExistingFile
method.