我已经设法在我的服务器上安装了 Imagemagick 7 并设置了适当的 PHP 模块,以便使用 Imagick 处理 HEIC 和 WebP 文件。
我可以轻松地将这些文件转换为其他格式,如 PNG 或 JPEG,没有任何问题。
现在,我尝试将 HEIC 序列(原始文件)转换为 GIF,但结果并不完美。
首先,Imagick 似乎无法确定每张图像之间的延迟。这会产生闪电般的动画。所以现在,我已经使用Imagick::setImageDelay硬编码了 40 个滴答声的延迟。我不确定,如果我遗漏了什么,或者 Imagick/Imagemagick 是否无法在 HEIC 序列上执行此操作。
我遇到的下一个问题是,Imagick 无法正确处理原始图像尺寸。为了解决这个问题,我必须获取原始图像的尺寸并在每一帧上执行Imagick::cropImage和Imagick::thumbnailImage ,然后使用Imagick::setImagePage完成它。
但是,我现在最大的问题是,结果有一个损坏的第一帧:
所以最终(损坏的)结果如下所示:
虽然预期的结果(由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 动画: