提高图像性能时,调整大小的动画gif


Improve imagick performance when resizing animated gifs

我正在调整动画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的大小时,需要相当长的时间。

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

我在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%!)所以,对于那些说,我应该对性能感到满意而不是抱怨的人来说,这证明你应该调查和改进你之前满意的东西,否则你将永远是一个平庸的开发人员。

当然,我正在尝试进一步减少转换时间,并将做一些分析以确定哪些调用是最昂贵的,然后针对它们。

在花了一段时间尝试优化之后,我最终得到了大约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的设置和玩颜色深度等,使它更好,一旦我找到一些空闲时间当然:)

我知道这可能有点晚了,但是对于那些像我一样在这里寻找一种方法来调整。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();

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