Cómo usar pngquant con PHP

Cómo usar pngquant con PHP

GIF, JPG y PNG son los 3 tipos de formatos principales para imágenes usados para la web, la diferencia entre ellos es la imágen resultante. Cada uno de ellos tiene su espacio para las páginas web (tanto para la interfaz de usuario como imágenes para mostrar). Las imágenes PNG fueron creadas precisamente con el proposito de ser mejores que los GIFs. Los diseñadores necesitan la habilidad de incorporar imágenes de baja resolución que cargan rápido en el explorador pero que tambien luzcan bien (no tan escalables como el SVG, pero bastante aceptables). Aquí es cuando entra el formato PNG en juego. Este tipo de imágenes son de baja disipación, esto significa que la compresión de esta no afecta mucho la calidad de la imágen. A diferencia de formatos como JPG, que crean desenfoque hasta cierto punto, una imágen con formato PNG comprimida siempre se verá al menos tan nítida como la imagen original.

Para ti, como desarrollador el formato de la imágen no debería ser importante (a menos que realmente necesites un formato en especifico como PNG para el uso de transparencia), lo que importa, es la manera en la que manejas las imágenes y si reduces el tamaño de estas, especialmente si quieres cuidad del tiempo de carga de tu sitio web, el espacio que estas ocupan en el disco duro del servidor etc. Para comprimir imágenes PNG puedes usar la conocida herramienta de compresión pngquant.

pngquant es una utilidad de linea de comandos y una librería para compresión de imágenes PNG. La conversión reduce el tamaño de las imágenes significativamente (en la mayoria de los casos hasta un 70% del tamaño del archivo y casi con la misma calidad) y preserva además su transparencia. Las imágenes generadas son compatibles con todos los navegadores modernos y tienen nejor fallback en IE6 que PNG de 24 bits. Lo mejor de todo, se puede utilizar con PHP.

En este articulo, aprenderas a usar pngquant con PHP usando una librería o PHP plano.

Requisitos

Necesitarás logicamente la utilidad de linea de comandos de pngquant en su versión más reciente en tu computadora y accesible además desdel el path (no tienes que, pero es recomendable). pngquant está disponible para casi todos los sistemas operativos y puede ser descargado desde el sitio oficial.

Windows

Puedes descargar un ejecutable de pngquant para windows desde este link.

Ubuntu

Para instalar pngquant en ubuntu, puedes hacerlo instalandolo desde un repositorio personalizado ejecutando los siguientes comandos en la terminal:

sudo add-apt-repository ppa:danmbox/ppa

sudo apt-get update

sudo apt-get install pngquant

MacOS

Puedes instalar pngquant usando brew:

brew install pngquant

Si la instalación de tu sistema operativo no está en esta lista, por favor visita la página de pngquant para ver otros métodos de instalación. Como mencionamos anteriormente, puedes usar pngquant con PHP usando una librería wrapper que hará el uso bastante sencillo o puedes ejecutar simplemente tu comando usando PHP y la función system.

A. Usando una librería

Puedes usar la librería php-pngquant library para trabajar con pngquant. php-pngquant es un simple wrapper para la popular herramienta de linea de comandos pngquant. Si usas composer, puedes instalarla ejecutando el siguiente comando en tu consola:

composer require ourcodeworld/php-pngquant

En caso de que no uses Composer, puedes descargar simplemente la clase PNGQuant.php desde el repositorio aquí y agregarla a tu código usando require_once.

La clase PNGQuant hará el trabajo por ti. En la misma manera que la linea de comandos, la clase agrega un método que agrega un nuevo argumento u opción al comando a ejecutar en pngquant, lo que hace su uso bastante intuitivo.

Para comprimir una imágen PNG necesitarás usar al menos 3 de los métodos en una instancia de PNGQuant:

<?php

use ourcodeworld\PNGQuant\PNGQuant;

$instancia = new PNGQuant();

// La instancia de PNGQuant es encadenable
$instancia
    // Proporciona el directorio y nombre de la imágen a comprimir
    ->setImage("/a-folder/image-original.png")
    // Directorio y nombre de archivo resultante de la compresion
    ->setOutputImage("/a-folder/image-compressed.png")
    // pngquant generará una excepcion si la imagen comprimida ya existe
    // Para ello permite la sobreescritura con este método
    ->overwriteExistingFile()
    // Define el rango de calidad de la imágen
    ->setQuality(50,80)
    // Ejecuta el comando (comprimir imagen)
    ->execute();

Solo necesitarás proporcionar el directorio de la imágen a comprimir, el directorio de salida y el rango de calidad que quieres usar para tu imágen PNG y eso es todo, ahora estás usando pngquant con PHP. Sin embargo en caso de error, no sabrás que paso si usas el código anterior, para saber que paso necesitas obtener el código de salida generado por pngquant y comparar el código con la tabla de errores:

<?php

use ourcodeworld\PNGQuant\PNGQuant;

$instancia = new PNGQuant();

// Obtener el código de salida de pngquant
$status_code = $instancia
    // Proporciona el directorio y nombre de la imágen a comprimir
    ->setImage("/a-folder/image-original.png")
    // Directorio y nombre de archivo resultante de la compresion
    ->setOutputImage("/a-folder/image-compressed.png")
    // pngquant generará una excepcion si la imagen comprimida ya existe
    // Para ello permite la sobreescritura con este método
    ->overwriteExistingFile()
    // Define el rango de calidad de la imágen
    ->setQuality(50,80)
    // Ejecuta el comando (comprimir imagen)
    ->execute();

// Si el código de salida es 0 entonces todo salio bien
if(!$exit_code){
    echo "Imagen satisfactoriamente comprimida";
}else{
    $description = $instance->getErrorTable()[(string) $exit_code];
    
    echo "Algo salio mal (código de salida $exit_code)  con descripción: ". $description;
}

El código de salida 0 significa que todo salio bien y la imágen ha sido comprimida, de otra manera por favor revisa los códigos de errores de pngquant aquí. Te recomendamos leer la documentación oficial de php-pngquant para ver todos los métodos disponibles y otros ejemplos.

En caso de que pngquant no esté disponible en el path, puedes cambiar el directorio donde se encuentra pngquant usando el método setBinaryPath:

<?php

use ourcodeworld\PNGQuant\PNGQuant;

$instance = new PNGQuant();

$instance
    // Propocirna donde se encuenta pngquant, por ejemplo en windows
    ->setBinaryPath("C:\\Users\\sdkca\\Desktop\\pngquant.exe")
    ->setImage("/a-folder/image-original.png")
    ->setOutputImage("/a-folder/image-compressed.png")
    ->overwriteExistingFile()
    ->setQuality(50,80)
    ->execute();

Nota

Hay otras librerias que te permiten usar pngquant, sin embargo estas no se especializan solo en pngquant, pues usan otras librerías tambien y no proveen soporte para errores. (Este wrapper ha sido creado por Our Code World )

B. PHP plano

Como pnquant es una utilidad de linea de comandos, podemos usar la función system para ejecutar una instrucción de linea de comandos. El comando a ejecutar depende completamente de ti, el punto principal es que necesitas usar el método system para obtener el código de salida de pngquant.

El siguiente ejemplo muestra como usar el método system para ejecutar un comando con una función llamada compress_png que espera como primer parametro el directorio de la imágen a comprimir y como segundo parametro el directorio donde la imágen comprimida debería ser creada:

<?php 

function compress_png($image_input,$image_output)
{
    // Directorio de ejecutable de pngquant
    $path_pngquant = "pngquant";

    $image_output_escaped = escapeshellarg($image_output);

    // Genera un comando como:
    // pngquant image-original.png --output "/a-folder/image-compressed.png" --force --quality 50-80
    $cmd = "$path_pngquant $image_input --output $image_output_escaped --force --quality 50-80";

    $status_code = null;

    // Ejecuta el comando
    system($cmd, $status_code);

    return $status_code;
}

$exit_code = compress_png("image.png", "image-compressed.png");
 
/* Compara con el código obtenido
"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"
*/

Que te diviertas !

Esto podría ser de tu interes

Conviertete en un programador más sociable