1

我正在调整动画 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 的大小。对于非动画图像,大约需要半秒钟。

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

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

更新:

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

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

4

3 回答 3

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 的设置并使用颜色深度等以使其更好:)

于 2013-06-16T04:21:42.067 回答
1

我知道这可能有点晚了,但是对于像我这样最终在这里寻找调整 .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();
于 2013-08-27T09:37:24.960 回答
-3

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

于 2013-06-15T09:53:33.863 回答