将动画 GIF 合并到背景图像中


Merging animated Gif into background image

我正在尝试将动画 gif 合并到静态 jpeg 作为背景中,这是由 html 画布和用户上传的文件上传生成的。我让它在图像魔术命令行上运行得很好

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");

这大约需要 15~ 秒来处理,这是可以接受的,但后来我发现我不能使用 exec 命令,必须使用 Imagick API,我最终能够使用以下代码重新创建进程:

$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);
   }
}

这段代码大约需要 5 秒,这很棒,但是当它循环时 gif 中有一个空白帧,这非常烦人,所以我在之后添加了这个:

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

这会去除空白帧,但会增加大约 20 - 30 秒的处理时间。我做错了什么吗,我已经在代码的顺序上玩了很多,并尝试了不同的方法。有没有办法像使用命令行一样将处理时间恢复到 20 秒以下?

你的代码很奇怪。为什么要将包含动画 gif 的 Imagick 对象的格式设置为 JPG?合成图像为什么要摆弄图像页面?

我很确定你希望你的代码看起来更像

$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);