Imagick
| Language | PHP (PECL extension) |
|---|---|
| License | PHP License 3.01 (ImageMagick: ImageMagick License) |
| Repository | github.com/Imagick/imagick |
| Documentation | php.net/manual/en/book.imagick.php |
| Depends on | ImageMagick 6 or 7 (MagickWand) |
| Read / write | yes / yes; animation, delays, loop count, disposal, layer optimization |
An Imagick object holds a list of images; for an animated GIF each image is a frame. You iterate it with foreach (or setIteratorIndex), and per-frame settings like getImageDelay() (1/100 s), getImageDispose() and getImagePage() (frame position on the canvas) apply to the current frame.
Frames are stored as in the file, often as small rectangles. Call coalesceImages() to get full frames before resizing or drawing, then optimizeImageLayers() (or deconstructImages()) to make them small again, and write with writeImages($file, true).
Installation#
Shell
# Debian / Ubuntu
sudo apt install php-imagick
Basic usage: read frames of an animated GIF#
PHP
<?php
$gif = new Imagick('anim.gif');
printf("%d frames, loop %d (0 = forever)\n", $gif->getNumberImages(), $gif->getImageIterations());
foreach ($gif as $i => $frame) {
$page = $frame->getImagePage(); // ['width', 'height', 'x', 'y'] of the canvas and offset
printf("frame %d: %dx%d at (%d,%d), delay %d/100 s, dispose %d\n",
$i, $frame->getImageWidth(), $frame->getImageHeight(),
$page['x'], $page['y'], $frame->getImageDelay(), $frame->getImageDispose());
}
How to resize an animated GIF#
PHP
$gif = new Imagick('anim.gif');
$gif = $gif->coalesceImages(); // full frames
foreach ($gif as $frame) {
$frame->resizeImage(320, 0, Imagick::FILTER_LANCZOS, 1); // height 0 = keep aspect ratio
$frame->setImagePage(0, 0, 0, 0); // reset canvas size to the new frame size
}
$gif = $gif->optimizeImageLayers(); // back to small difference frames
$gif->writeImages('small.gif', true); // true = one file with all frames
How to create an animated GIF from images#
PHP
$anim = new Imagick();
foreach (['f1.png', 'f2.png', 'f3.png'] as $file) {
$frame = new Imagick($file);
$frame->setImageFormat('gif');
$frame->setImageDelay(20); // 0.2 s
$frame->setImageDispose(2); // restore to background
$anim->addImage($frame);
}
$anim->setImageIterations(0); // loop forever
$anim = $anim->optimizeImageLayers();
$anim->writeImages('anim.gif', true);
How to extract the first frame of a GIF#
PHP
$gif = new Imagick('anim.gif');
$gif->setIteratorIndex(0);
$first = $gif->getImage(); // a new Imagick with only this frame
$first->setImageFormat('png');
$first->writeImage('first.png');
How to make a GIF smaller#
PHP
$gif = (new Imagick('big.gif'))->coalesceImages();
foreach ($gif as $frame) {
$frame->quantizeImage(64, Imagick::COLORSPACE_RGB, 0, false, false); // 64 colors, no dither
}
$gif = $gif->optimizeImageLayers();
$gif->optimizeImageTransparency(); // unchanged pixels become transparent
$gif->writeImages('smaller.gif', true);
Tips#
writeImage(singular) writes only the current frame; usewriteImages($path, true)for animations.- Set limits in ImageMagick’s
policy.xmlor withImagick::setResourceLimiton servers: GIFs with thousands of frames can use gigabytes aftercoalesceImages. optimizeImageTransparency()needs ImageMagick 6.8.7+.