Google ha creado un nuevo formato de imagen webp que ofrece imágenes de alta calidad con un tamaño mucho menor que los formatos gif, jpg y png. Es posible generar animaciones en archivos webp.
Aquí os muestro un ejemplo de una animación creada con 150 jpgs a un tamaño de 700 x 184 pixeles.


Para poder generar animaciones en archivos webp, necesitamos que la librería php GD para el manejo de imágenes este en nuestro servidor y que tenga activado el soporte para imágenes webp. Para ello hacemos una petición a la función gd_info:
$supportgd = gd_info();
$supoortwebp = false;
foreach($supportgd as $clave => $valor) {
if($clave."" === "WebP Support" && $valor."" === "1") { $supoortwebp = true; }
}
Una vez que sabemos que la librería puede trabajar con el formato webp podemos pasar a generar imágenes webp.
Voy a explicar como generar webp animados a partir de una secuencia de imágenes.
Para generar este código me he basado en la aportación de Alejandro Malbarez, en concreto su proyecto php-GD-Animated-webp.
En la generación de animaciones en archivos webp, lo primero creamos unas funciones recursivas para calcular datos convirtiendo un valor a en un entero de 32 , 24 o 16 bits sin signo, convertir array a string y convertir un binario a bytes.
function toUint32($n){
$ar = unpack("C*", pack("L", $n));
return $ar;
}
function toUint24($n){
$ar = unpack("C*", pack("L", $n));
array_pop($ar);
return $ar;
}
function toUint16($n){
$ar = unpack("C*", pack("S", $n));
return $ar;
}
function bytesToString($bytes){
return implode(array_map("chr", $bytes));
}
function binaryToBytes($bits){
$octets = explode(' ', $bits);
return array_map("bindec", $octets);
}
Creamos una función que crea la imagen webp pasandole:
function createWEbpAnim($srcframes, $gifW, $gifH, $loop) {
// create new WEBP
$fileWEBP = "";
$fileHeader = "";
$fileContents = "";
// Chunk HEADER VP8X
$fileContents .="VP8X";
$headChunkSize = bytesToString(toUint32(10));
// bit flags Rsv|I|L|E|X|A|R| Reserved
$oVP8XflagsBin = "00010010 00000000 00000000 00000000";
$oVP8Xflags = bytesToString(binaryToBytes($oVP8XflagsBin));
$oCanvasSize = bytesToString(toUint24($gifW-1)).bytesToString(toUint24($gifH-1));
$fileContents .= $headChunkSize. $oVP8Xflags. $oCanvasSize;
// Chunk HEADER ANIM
$fileContents .="ANIM";
$animChunkSize = bytesToString(toUint32(6));
$oLoopCount = bytesToString(toUint16($loop)); // loop count 16bits, 0 = infinito
$oBackGround = str_repeat(chr(0), 4); // 32bits BGRA, Blue Green Red Alpha (0,0,0,0)
$fileContents .= $animChunkSize . $oBackGround . $oLoopCount;
// los frames
for($i = 0; $i<count($srcframes); $i++) {
$imagetype = exif_imagetype($srcframes[$i][0]); // 1: gif, 2: jpg, 3: png
if($imagetype === IMAGETYPE_JPEG){ $img = imagecreatefromjpeg($srcframes[$i][0]); }
if($imagetype === IMAGETYPE_GIF){ $img = imagecreatefromgif($srcframes[$i][0]); }
if($imagetype === IMAGETYPE_PNG){ $img = imagecreatefrompng($srcframes[$i][0]); }
imagepalettetotruecolor($img);
imagealphablending($img, true);
imagesavealpha($img, true);
$w = imagesx($img);
$h = imagesy($img);
ob_start();
imagewebp($img);
if (ob_get_length() % 2 == 1) { echo "\0"; }
$image_data = ob_get_contents();
ob_end_clean();
$frameData = substr($image_data, strpos($image_data, "VP8 "));
$fileContents .="ANMF";
$frameDataChunkSize = bytesToString(toUint32(strlen($frameData)+16));
$fOrigin = str_repeat(chr(0), 6);
$fSize = bytesToString(toUint24($w - 1)).bytesToString(toUint24($h - 1));
$fDuration = bytesToString(toUint24($srcframes[$i][1]*10));
$fFlagsBin = "00000010";
$fFlags = bytesToString(binaryToBytes($fFlagsBin));
$fileContents .= $frameDataChunkSize.$fOrigin.$fSize.$fDuration.$fFlags.$frameData;
imagedestroy($img);
}
// calculate Size and build file header
$fileSize = bytesToString(toUint32(strlen($fileContents)+4));
$fileHeader = "RIFF".$fileSize."WEBP";
$fileWEBP = $fileHeader.$fileContents;
return $fileWEBP;
}
Para invocar la función rellenamos un array con las imágenes y el tiempo de permanencia de cada una y le pasamos los demás parámetros.
//crear en webp animado ejemplo
$losframes = Array(
Array("orig/horse/png/1.png",6),
Array("orig/horse/png/2.png",6),
Array("orig/horse/png/3.png",6),
Array("orig/horse/png/4.png",6),
Array("orig/horse/png/5.png",6),
Array("orig/horse/png/6.png",6),
Array("orig/horse/png/7.png",6),
Array("orig/horse/png/8.png",6)
);
// array de frames, ahcho de la imagen, alto de la imagen, veces que se repite (0 es infinito)
$resultado = createWEbpAnim($losframes, 307, 230, 0);
file_put_contents("img/ejemplo.webp",$resultado);
Os dejo en un zip los archivos del ejemplo de generación animaciones en archivos webp.