Content-aware resizing with PHP & ImageMagick
Use Imagick::liquidRescaleImage() to change an image’s proportions without uniformly stretching
every object. This walkthrough produces a 400 × 300 JPEG from a local image in PHP. Seam carving
can remove empty space around a subject, but it can also distort the subject itself.
What is content-aware resizing?
Content-aware resizing, or seam carving, removes or inserts connected paths of pixels called seams. It favors paths with less visual variation. A textured object against a plain background may retain its shape while the background shrinks; a smooth face against a busy background may be distorted instead. The algorithm does not recognize which object matters to you.
Prerequisites
The setup below targets Debian 13 with PHP 8.4, Imagick 3.8, and ImageMagick 7. Tested versions were PHP 8.4.26, Imagick 3.8.0, ImageMagick 7.1.1-43, and liblqr 0.4.2. Use the distribution’s maintained updates within these version lines; the patch numbers describe the tested setup, not an intrinsic minimum. PHP 8.4 is supported.
As root on Debian 13, install the CLI and extension packages:
apt-get update &&
apt-get install -y --no-install-recommends php8.4-cli php8.4-imagick imagemagick liblqr-1-0
Debian provides php8.4-imagick.
The examples use a trusted, intact, single-frame, RGB JPEG named input.jpg in a writable working
directory. Keep the original. Upload validation, animation, and color-profile conversion are
outside this local CLI example.
Additional prerequisites
Installing liblqr alone is insufficient: the ImageMagick library linked to PHP’s Imagick extension must have been built with it. Before saving the scripts, test the operation through PHP itself:
php -r '
$im = new Imagick();
$im->newImage(16, 16, "white");
$im->liquidRescaleImage(12, 16, 1, 0);
echo "Liquid rescale available\n";
'
Continue only if this exits successfully and prints Liquid rescale available. A missing extension
or delegate fails before that message. If installation or this check fails, fix the prerequisite
and repeat that step; no article output has been created yet.
How to use liquid rescale in PHP
Save this as resize.php beside input.jpg. The two target dimensions are pixels; change them to
match the output you need.
<?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);
}
Run it from that directory:
php resize.php
A successful run prints Saved output.jpg (400 x 300) and writes a 400 × 300 JPEG. Open it beside
the original: the dimensions confirm the target size, but they do not confirm subject preservation.
Successful runs replace output.jpg. On an ImagickException, the script exits with status 1 and
may leave an older output in place, so check the exit status before using the file.
Parameter fine-tuning
The liquid rescale operation is controlled by two key parameters:
- deltaX: Maximum sideways step of a seam. Zero produces straight seams; larger values give seams more freedom to move around image content.
- rigidity: A nonnegative penalty for bending seams. Zero adds no penalty; larger values favor straighter seams. This does not guarantee that a face or other important feature is preserved.
These meanings come from the Imagick parameter documentation. Inspect the result on representative images when choosing values.
Performance considerations
For a large original, you can reduce the number of pixels entering seam carving with a conventional
resize first. Save this separate version as resize-small.php. It fits oversized inputs within
800 × 600 while preserving their aspect ratio, then seam carves to 400 × 300. It skips the initial
resize for smaller inputs; without that guard, bestfit: true can enlarge them, as described in the
resizeImage documentation.
<?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
This prints Saved optimized-output.jpg (400 x 300) on success, with the same replacement and
failure behavior as the first script. The initial resize also shrinks the subject, so the two
outputs can look different. If the fitted image is narrower than 400 pixels or shorter than 300,
the final operation enlarges that dimension. Compare results before choosing this tradeoff; it is
not a guarantee of faster processing or better quality.
Common issues and solutions
Memory allocation errors
PHP’s memory_limit does not reliably bound ImageMagick’s native allocations. Configure
ImageMagick’s resource limits and security policy,
including memory, disk cache, dimensions, and processing time, for your workload. Surface resource
limit failures instead of retrying the same oversized image indefinitely.
Missing Liblqr support
Inspect the extension’s linked version with:
php --ri imagick
The standalone ImageMagick CLI can use a different build. A delegate listed by magick or
ImageMagick 6’s convert does not prove that PHP can use it. Repeat the PHP operation under
“Additional prerequisites” after installing a compatible build. Restart any long-running PHP
workers that use the old library. The saved scripts report Image resizing failed. and exit 1
when the liquid rescale call fails.
Quality preservation
JPEG decoding may recover part of a damaged file and still produce output. These scripts do not verify input integrity; use an intact original and inspect the whole result, including its bottom edge.
Inspect faces, lettering, straight edges, and repeated patterns. The ImageMagick seam carving examples explain why busy backgrounds can cause the algorithm to remove pixels from the foreground instead. Neither a higher rigidity nor sharpening protects a particular subject. For photos where shape matters, compare with proportional resizing or an explicit crop and choose the result that keeps the content you need.
Wrapping up
Try the script on a few images from your own workload before applying it to a batch. For hosted image resizing and format conversion, explore Transloadit’s Image Processing API.
