Redimensionamiento según el contenido con PHP e ImageMagick
Usa Imagick::liquidRescaleImage() para cambiar las proporciones de una imagen sin estirar
uniformemente todos los objetos. Este tutorial genera un JPEG de 400 × 300 a partir de una imagen
local en PHP. El redimensionamiento por costuras puede eliminar el espacio vacío alrededor de un
sujeto, pero también puede distorsionar al propio sujeto.
¿Qué es el redimensionamiento según el contenido?
El redimensionamiento según el contenido, o redimensionamiento por costuras, elimina o inserta trayectorias conectadas de píxeles llamadas costuras. Favorece las trayectorias con menor variación visual. Un objeto con textura sobre un fondo liso puede conservar su forma mientras el fondo se reduce; en cambio, un rostro liso sobre un fondo complejo puede distorsionarse. El algoritmo no reconoce qué objeto te importa.
Requisitos previos
La configuración siguiente está pensada para Debian 13 con PHP 8.4, Imagick 3.8 e ImageMagick 7. Las versiones probadas fueron PHP 8.4.26, Imagick 3.8.0, ImageMagick 7.1.1-43 y liblqr 0.4.2. Usa las actualizaciones que mantiene la distribución dentro de estas líneas de versiones; los números de parche describen la configuración probada, no un mínimo intrínseco. PHP 8.4 cuenta con soporte.
Como root en Debian 13, instala los paquetes de la CLI y de la extensión:
apt-get update &&
apt-get install -y --no-install-recommends php8.4-cli php8.4-imagick imagemagick liblqr-1-0
Debian proporciona php8.4-imagick.
Los ejemplos usan un JPEG RGB confiable, intacto y de un solo fotograma llamado
input.jpg, en un directorio de trabajo con permisos de escritura.
Conserva el original. La validación de subidas, la animación y la conversión de perfiles de color
quedan fuera de este ejemplo local de CLI.
Requisitos previos adicionales
Instalar liblqr no es suficiente: la biblioteca ImageMagick enlazada a la extensión Imagick de PHP debe haberse compilado con ella. Antes de guardar los scripts, prueba la operación desde PHP:
php -r '
$im = new Imagick();
$im->newImage(16, 16, "white");
$im->liquidRescaleImage(12, 16, 1, 0);
echo "Liquid rescale available\n";
'
Continúa solo si la prueba termina correctamente e imprime Liquid rescale available.
Si falta una extensión o un delegado, la prueba falla antes de mostrar ese mensaje. Si la
instalación o esta comprobación falla, resuelve el requisito previo y repite ese paso; todavía no
se ha generado ningún archivo de salida del artículo.
Cómo usar el reescalado líquido en PHP
Guarda este código como resize.php junto a input.jpg.
Las dos dimensiones de destino están en píxeles; cámbialas para obtener la salida que necesitas.
<?php
$image = new Imagick();
try {
$image->readImage('input.jpg');
$targetWidth = 400;
$targetHeight = 300;
$deltaX = 1; // Maximum sideways step of a seam
$rigidity = 0; // Penalty for bending a seam
$image->liquidRescaleImage($targetWidth, $targetHeight, $deltaX, $rigidity);
$image->writeImage('output.jpg');
printf("Saved output.jpg (%d x %d)\n", $image->getImageWidth(), $image->getImageHeight());
} catch (ImagickException $e) {
fwrite(STDERR, "Image resizing failed.\n");
$failed = true;
} finally {
$image->clear();
}
if (isset($failed)) {
exit(1);
}
Ejecútalo desde ese directorio:
php resize.php
Una ejecución correcta imprime Saved output.jpg (400 x 300) y escribe un JPEG de 400 × 300.
Ábrelo junto al original: las dimensiones confirman el tamaño de destino, pero no que el sujeto
se haya conservado. Las ejecuciones correctas reemplazan output.jpg.
Ante una ImagickException, el script termina con el código de salida 1 y puede dejar
una salida anterior en su lugar, así que comprueba el código de salida antes de usar el archivo.
Ajuste preciso de los parámetros
La operación de reescalado líquido se controla mediante dos parámetros clave:
- deltaX: Desplazamiento lateral máximo de una costura. Cero produce costuras rectas; los valores mayores les dan más libertad para desplazarse alrededor del contenido de la imagen.
- rigidity: Penalización no negativa por curvar las costuras. Cero no añade ninguna penalización; los valores mayores favorecen costuras más rectas. Esto no garantiza que se conserve un rostro u otro rasgo importante.
Estos significados proceden de la documentación de parámetros de Imagick. Inspecciona el resultado en imágenes representativas al elegir los valores.
Consideraciones de rendimiento
Si el original es grande, puedes reducir la cantidad de píxeles que entran en el redimensionamiento
por costuras mediante un redimensionamiento convencional previo. Guarda esta versión independiente
como resize-small.php. Ajusta las imágenes de entrada demasiado grandes a un máximo de
800 × 600 conservando su relación de aspecto y luego aplica el redimensionamiento por costuras a
400 × 300. Omite el redimensionamiento inicial para las imágenes de entrada más pequeñas; sin esa
comprobación, bestfit: true puede ampliarlas, como se describe en la
documentación de resizeImage.
<?php
$image = new Imagick();
try {
$image->readImage('input.jpg');
if ($image->getImageWidth() > 800 || $image->getImageHeight() > 600) {
$image->resizeImage(800, 600, Imagick::FILTER_LANCZOS, 1, true);
}
$image->liquidRescaleImage(400, 300, 1, 0);
$image->writeImage('optimized-output.jpg');
printf("Saved optimized-output.jpg (%d x %d)\n", $image->getImageWidth(), $image->getImageHeight());
} catch (ImagickException $e) {
fwrite(STDERR, "Image resizing failed.\n");
$failed = true;
} finally {
$image->clear();
}
if (isset($failed)) {
exit(1);
}
php resize-small.php
Si la ejecución termina correctamente, imprime Saved optimized-output.jpg (400 x 300), con el mismo
comportamiento de reemplazo y de fallo que el primer script. El redimensionamiento inicial también
reduce el tamaño del sujeto, por lo que las dos salidas pueden verse diferentes. Si la imagen
ajustada tiene menos de 400 píxeles de ancho o menos de 300 de alto, la operación final amplía esa
dimensión. Compara los resultados antes de elegir esta opción con sus ventajas y limitaciones;
no garantiza un procesamiento más rápido ni una mejor calidad.
Problemas comunes y soluciones
Errores de asignación de memoria
El parámetro memory_limit de PHP no limita de forma confiable las asignaciones de
memoria nativas de ImageMagick. Configura los
límites de recursos y la política de seguridad de ImageMagick,
incluidos la memoria, la caché en disco, las dimensiones y el tiempo de procesamiento, según tu
carga de trabajo. Haz visibles los fallos por límites de recursos en lugar de reintentar
indefinidamente el procesamiento de la misma imagen demasiado grande.
Falta de soporte para Liblqr
Inspecciona la versión enlazada a la extensión con:
php --ri imagick
La CLI independiente de ImageMagick puede usar una compilación diferente. Que un delegado aparezca
en magick o en convert de ImageMagick 6 no demuestra
que PHP pueda usarlo. Repite la operación de PHP de «Requisitos previos adicionales» después de
instalar una compilación compatible. Reinicia los procesos de trabajo de PHP de larga duración
que usen la biblioteca anterior. Los scripts guardados muestran Image resizing failed.
y terminan con el código de salida 1 cuando falla la llamada al reescalado líquido.
Conservación de la calidad
La decodificación de JPEG puede recuperar parte de un archivo dañado y aun así generar una salida. Estos scripts no verifican la integridad de la entrada; usa un original intacto e inspecciona todo el resultado, incluido su borde inferior.
Inspecciona los rostros, las letras, los bordes rectos y los patrones repetidos. Los ejemplos de redimensionamiento por costuras de ImageMagick explican por qué los fondos complejos pueden hacer que el algoritmo elimine píxeles del primer plano. Ni una mayor rigidez ni el aumento de nitidez protegen a un sujeto específico. Para las fotos en las que importa la forma, compara con un redimensionamiento proporcional o un recorte explícito y elige el resultado que conserve el contenido que necesitas.
Para terminar
Prueba el script con algunas imágenes de tu propia carga de trabajo antes de aplicarlo a un lote. Para redimensionar imágenes y convertir formatos mediante un servicio alojado, explora la API de procesamiento de imágenes de Transloadit.
