【问题标题】:Improve imagick performance when resizing animated gifs调整动画 gif 大小时提高 imagick 性能
【发布时间】:2013-06-11 22:00:41
【问题描述】:

我正在调整动画 gif 的大小并使用 PHP 中的 imagick 扩展为其添加背景。

这是我正在使用的代码:

$image = new Imagick('myfile.gif');
$image = $image->coalesceimages();

$final = new \Imagick();

foreach ($image as $frame){

    $frame->thumbnailImage($width, $height, true);
    $geometry = $image->getImageGeometry();

    $x = ( $width - $geometry['width'] ) / 2;
    $y = ( $height - $geometry['height'] ) / 2;

    $canvas = new \Imagick();
    $canvas->newImage( $width, $height, $background);

    $canvas->compositeImage( $image, \Imagick::COMPOSITE_OVER, $x, $y );

    $final->addimage($canvas);
}

$final->desconstructimages();
$final->writeImages('resized.gif', true);

代码有效,调整大小的图像非常完美。但是,在调整动画 GIF 的大小时,需要相当长的时间。

使用上面的代码,调整一个 36kb 的 60 帧 gif 大约需要 10 秒。对于非动画图像,大约需要半秒。

我在Ubuntu 12.10 32-bit 上运行ImageMagick 6.8.1-0 2012-12-20。

有没有办法加快调整大小?

更新:

我发现 thumbnailImage 不需要在每一帧上都调用,所以现在我正在使用这个:

$image = new Imagick('myfile.gif');
$image = $image->coalesceimages();

$final = new \Imagick();

$image->thumbnailImage($width, $height, true);
$geometry = $image->getImageGeometry();

$x = ( $width - $geometry['width'] ) / 2;
$y = ( $height - $geometry['height'] ) / 2;

foreach ($image as $frame){

    $canvas = new \Imagick();
    $canvas->newImage( $width, $height, $background);

    $canvas->compositeImage( $image, \Imagick::COMPOSITE_OVER, $x, $y );

    $final->addimage($canvas);
}

$final->desconstructimages();
$final->writeImages('resized.gif', true);

通过只做一次缩略图,我现在平均节省了 1 秒(10%!)与以前相比!所以,对于那个说,我应该对性能感到满意而不是抱怨的人,这证明你应该调查和改进你以前满意的东西,否则你将永远是一个平庸的开发者。

当然,我正在尝试进一步减少转换时间,并将进行一些分析以确定哪些调用成本最高,然后针对这些调用。

【问题讨论】:

    标签: php imagemagick image-manipulation imagick


    【解决方案1】:

    在花了一段时间尝试优化之后,我最终得到了大约 6.5 秒的平均时间,这比最初的 10 秒要好得多。

    我现在正在调整循环外的动画大小并使用optimizeImageLayers,它比deconstructImages 更快,并且还减小了文件大小。

    $image = new Imagick('myfile.gif');
    $image = $image->coalesceimages();
    
    $final = new \Imagick();
    
    foreach ($image as $frame){
    
        $image->thumbnailImage($width, $height, true);
        $geometry = $image->getImageGeometry();
    
        $x = ( $width - $geometry['width'] ) / 2;
        $y = ( $height - $geometry['height'] ) / 2;
    
        $canvas = new \Imagick();
        $canvas->newImage( $width, $height, $background);
    
        $canvas->compositeImage( $image, \Imagick::COMPOSITE_OVER, $x, $y );
    
        $final->addimage($canvas);
    }
    
    $final = $final->optimizedImageLayers();
    $final->writeImages('resized.gif', true);
    

    这是我目前正在使用的,对此我非常满意。但是,一旦我找到一些空闲时间,我会考虑调整 imagemagick 的设置并调整颜色深度等以使其更好:)

    【讨论】:

      【解决方案2】:

      我知道这可能有点晚了,但对于像我这样最终在这里寻找调整 .gif 大小的方法的人来说,这是我编写的一个小代码,它也可以在图像中保留最多 25 帧(这个代码保持原来的动画速度)。

      $original = new \Imagick('/path/to/original/image');
      $new = new \Imagick();
      
      $i = 0; 
      $frameStep = ceil($original->getNumberImages() / 25);
      foreach ($original as $frame) {
          if ($i % $frameStep === 0) {
              $delay = $frame->getImageDelay();
      
              $frame->thumbnailImage($x, $y);
              $frame->setImagePage($x, $y, 0, 0);
              $frame->setImageDelay($delay * $frameStep);
      
              $new->addImage($frame->getImage());
          }
      
          $i++;
      }
      
      file_put_contents('/path/to/NEW/file', $new->getImagesBlob());
      
      $new->clear();
      $new->destroy();
      $original->clear();
      $original->destroy();
      

      【讨论】:

        【解决方案3】:

        如果 60 帧需要 10 秒来调整大小,那么每个帧实际上需要 1/6 秒,这更好,你的结果是 1 帧,不是吗?你不应该抱怨,因为 60 倍的工作需要更长的时间。

        【讨论】:

        • 嗯,是的,如果你这么想的话,还不错。但是,也许有更好的方法可以更有效地做到这一点。我目前正在自己​​循环处理每一帧,但也许有一种优化的方法可以做得更好,或者有人可能以前做过这个并发现了一种更有效的方法来做到这一点。至于对当前的性能是否满意,我不同意 ;) 开发人员应该始终不断地改进他们的应用程序,无论是性能、用户体验还是其他方面。满足于现状而不发展是失败的秘诀。
        • 然后编辑您的问题以删除与 1 帧调整大小的比较。
        • 我不明白为什么这是必要的。这是我在测试脚本时观察到的,将我的观察结果放在那里可以为每张图像的整体转换时间提供一些背景信息。
        猜你喜欢
        • 2015-06-16
        • 2015-04-19
        • 2018-04-18
        • 2011-03-02
        • 2012-06-28
        • 2012-08-30
        • 2011-11-01
        • 2012-09-07
        • 1970-01-01
        相关资源
        最近更新 更多