简体   繁体   中英

Merging animated Gif into background image

I'm trying to merge an animated gif into a static jpeg as a background, this is being generated by html canvas and a file upload that the user uploads. I had it working great with imagemagick command line

exec("convert ".$_paths['images_dir'].$fname.".gif  \( gif/cleared_dance".$dance.".gif -resize '80%' -repage 0x0-10+$imgHeight\! \) -coalesce -delete 0 -deconstruct -loop 0 ".$_paths['images_dir'].$fname.".gif");

this was taking about 15~ seconds to process which was acceptable, but then I found out I can't use the exec command and must use Imagick API, I was eventually able to recreate the process using the following code:

$data = $_POST["imgData"]; 
$dance = $_POST["dancer"]+1;
$spriteLeft = $_POST['left'];
$spriteTop = $_POST['top'];
$scale = $_POST['scale'];
$canvas = new Imagick();
$data = str_replace("data:image/png;base64,", "",$data); 
$data = base64_decode($data);
$canvas->readImageBlob($data);

$fname = 'tmp_'.uniqid();
$gif = new Imagick();
$gif->readImage('gif/cleared_dance'.$dance.'.gif');
do {
  $canvas->addImage($gif);
} while ($gif->nextImage());

foreach($canvas as $frame){
   if($frame->getIteratorIndex() != 0){
      $page = $frame->getImagePage();
      $frame->setImagePage(200,200,$page['x']+$spriteLeft,$page['y']+$spriteTop);
   }
}

This code takes about 5 seconds which is great but their is a blank frame in the gif when it loops that was super annoying so i added this after:

$canvas->setIteratorIndex(0);
$canvas->removeImage();
$canvas = $canvas->deconstructImages();
$canvas->writeImages('tmp/'.$fname.'.gif', true);

This takes out the blank frame, but adds about 20 - 30 seconds of processing. Am I doing something wrong, I've played around a good bit with the order of the code and trying different approaches. Is there a way to get the processing time back under 20 seconds like it was with the command line?

Your code is quite odd. Why are you setting the format of the Imagick object that is going to contain an animated gif to JPG? Why are you fiddling with the image page after you composited the image?

I'm pretty sure you want your code to look a lot more like

$static = new Imagick();
//$static->readImage("./testFile.png");
$inputGif->readImageBlob($data);

$inputGif = new Imagick();
//$inputGif->readImage('./testGif.gif');
$inputGif->readImage('gif/cleared_dance'.$dance.'.gif');

$gifFrames = $inputGif->coalesceImages();

$outputGif = new Imagick();
$outputGif->setFormat('gif');

foreach ($gifFrames as $gifFrame) {
    $frame = clone $static;
    $frame->compositeimage(
        $gifFrame,
        Imagick::COMPOSITE_OVER,  // or maybe \Imagick::COMPOSITE_ATOP,
        0, 0 // Set the offset here if you don't want the gif in the top left corner.
    );

    $outputGif->addImage($frame);
}

$outputGif->setImageIterations(0); //loop forever
$outputGif->deconstructImages();
$outputGif->writeImages("./outso.gif", true);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM