1

我已经设法在我的服务器上安装了 Imagemagick 7 并设置了适当的 PHP 模块,以便使用 Imagick 处理 HEIC 和 WebP 文件。

我可以轻松地将这些文件转换为其他格式,如 PNG 或 JPEG,没有任何问题。

现在,我尝试将 HEIC 序列(原始文件)转换为 GIF,但结果并不完美。

首先,Imagick 似乎无法确定每张图像之间的延迟。这会产生闪电般的动画。所以现在,我已经使用Imagick::setImageDelay硬编码了 40 个滴答声的延迟。我不确定,如果我遗漏了什么,或者 Imagick/Imagemagick 是否无法在 HEIC 序列上执行此操作。

我遇到的下一个问题是,Imagick 无法正确处理原始图像尺寸。为了解决这个问题,我必须获取原始图像的尺寸并在每一帧上执行Imagick::cropImageImagick::thumbnailImage ,然后使用Imagick::setImagePage完成它。

但是,我现在最大的问题是,结果有一个损坏的第一帧:

第一帧坏了

所以最终(损坏的)结果如下所示:

最终破碎的结果

虽然预期的结果(由heic2any生成)是:

heic2any 结果

我正在使用的(简化)代码:

<?php
if (!in_array('HEIC', \Imagick::queryFormats("HEI*"))) {
    throw new \Exception('Unsupported format');
}

$sourceFile = __DIR__ . '/3.heic';
$targetFile = __DIR__ . '/3.gif';

if (!file_exists($sourceFile)) {
    try {
        $content = file_get_contents('https://github.com/alexcorvi/heic2any/blob/master/demo/' . basename($sourceFile) . '?raw=true');

        if ($content === false) {
            throw new \Exception('Unable to download source file.');
        }

        file_put_contents($sourceFile, $content);
    } catch (\Exception $e) {
        throw new \Exception('Unable to download source file: ' . $e->getMessage());
    }

    if (!file_exists($sourceFile)) {
        throw new \Exception('Cannot find source file.');
    }
}

$im = new \Imagick($sourceFile);
$width = $im->getImageWidth();
$height = $im->getImageHeight();
$im = $im->coalesceImages();

foreach ($im as $frame) {
    $im->setImageDelay(40);

    $frame->cropImage($width, $height, 0, 0);
    $frame->thumbnailImage($width, $height);
    $frame->setImagePage($width, $height, 0, 0);
}

$im = $im->deconstructImages();
$im->writeImages($targetFile, true);

echo 'Size: ' . $width . 'x' . $height . '<br />Result:<br /><br /><img src="' . basename($targetFile) . '?v=' . time() . '" alt="" />';

所以我的问题是:

  • 第一帧从哪里来?
  • 我怎样才能避免它?
  • 有什么可以优化转换(代码)的吗?

更新:

还有另一个 .HEIC 序列可以使用(click),这个可以毫无问题地转换:

结果

更新:

即使是cloudconvert之类的转换服务也无法正确处理图像并生成如下 GIF 动画:

哎呀

4

0 回答 0