【问题标题】:Merging animated Gif into background image将动画 Gif 合并到背景图像中
【发布时间】:2015-01-17 04:11:37
【问题描述】:

我正在尝试将动画 gif 合并为静态 jpeg 作为背景,这是由 html 画布和用户上传的文件上传生成的。我用 imagemagick 命令行很好地工作

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 秒以下?

【问题讨论】:

  • 给我们一个输入图像和“cleared_dance”图像以及一个输出图像怎么样,这样我们就可以看到我们在说什么并进行一些实验?如果做不到这一点,您可能会从将“cleared_dance”转换为 IM 的 MIF 格式中获得一些好处。多一点你的代码也可能有用。
  • 我更新了代码以反映所有内容,这是一个处理过的图像的示例,其中包含一个空白帧,生成大约需要 5 秒:s16.postimg.org/s0x2b17cl/tmp_54b971d00b8bf.gif,这需要 > 20 秒:s30.postimg.org/cfcw1uqkh/tmp_54b9725b99690.gif

标签: php imagemagick imagick


【解决方案1】:

你的代码很奇怪。为什么要将包含动画 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);

【讨论】:

  • 你的意思是写 $static->readImageBlob($data); 吗?好吧,最初我想获取正在发送的画布 dataURI 并将其转换为 JPEG,以便我可以压缩它,认为这会减小整个图像的文件大小,但实际上我把它拿出来了,它减少了 10 秒的额外时间的处理时间。我会试试这段代码,看看它是否更有效。就像我说的我是 imagemagick 的新手,试图在我使用的 exec 命令中重新创建事件顺序
  • 我试过这个方法,处理时间是40秒,而我的方法是15~
  • 你能提供一些示例图片供人们使用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-31
  • 2011-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-23
相关资源
最近更新 更多