Roame
Roame

Reputation: 71

(PHP) Imagick-created gif animation: setting the frame disposal?

I would like every frame to be drawn anew, without the frame before it drawn behind it. My current code is:

// $frames is an array of image blobs
$durations = array(50, 50, 50, 50)
$loops = 0;

$big = new Imagick();
$big->setFormat('gif');
for ($i = 0; $i < count($frames); $i++) {
    $frames[$i]->scaleImage(140, 140);
    $frames[$i]->setImagePage(140, 140, 0, 0);
    $frames[$i]->setImageDispose(1);
    $big->addImage($frames[$i]);
    $big->setImageDelay($durations[$i]);
}
$big = $big->deconstructImages();
$big->setImageIterations($loops);
$big->writeImages('test.gif');

None of the setImageDispose() settings achieve what I want:

  1. setImageDispose(1): example image
  2. setImageDispose(2-3): example image

Though (1) appears to work as intended, it is still drawing the previous frames underneath. How can I simply set it to Gimp's equivalent of "replace", where each frame is drawn independantly? Is there another function I have not found that would solve this?

Thank you.

Additional notes:

Upvotes: 2

Views: 645

Answers (1)

Roame
Roame

Reputation: 71

I have found the solution. deconstructImages() was optimizing the frames in the way we see in the setImageDispose(2-3) example above. My solution was to have a toggle for these tweo functions, so I can either output as:

  • setImageDispose(1) - larger filesize but no overlapping frames
  • setImageDispose(2); deconstructImages() - smaller filesize

Depending on the animation I am building, I can dispose or not. My final code is something like this:

// $frames is an array of image blobs
$durations = array(50, 50, 50, 50)
$loops = 0;
$dispose = false;

$dispose_mode = ($dispose) ? 2 : 1;

$big = new Imagick();
$big->setFormat('gif');
for ($i = 0; $i < count($frames); $i++) {
    $frames[$i]->setImageDispose($dispose_mode);
    $frames[$i]->scaleImage(140, 140);
    $big->addImage($frames[$i]);
    $big->setImageDelay($durations[$i]);
}
$big->setImageIterations($loops);
$big = ($dispose) ? $big : $big->deconstructImages();
$big->writeImages('output.gif', true);

Upvotes: 1

Related Questions