All formats

Imagick

LanguagePHP (PECL extension)
LicensePHP License 3.01 (ImageMagick: ImageMagick License)
Repositorygithub.com/Imagick/imagick
Documentationphp.net/manual/en/book.imagick.php
Depends onImageMagick 6 or 7 (MagickWand)
Read / writeyes / 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#