Imagick 扔在任何 png 文件上

问题描述 投票:0回答:1

我正在使用 Imagick 实现和格式 jpg 测试我的缩略图系统,webp 工作正常,但使用 png 时它总是抛出:

"improper image header `\/tmp\/magick-fj49nThGt9uvW0CFbLJj7XGsqT7x30OC' @ error\/png.c\/ReadPNGImage\/4107 => \/var\/www\/html\/Dullahan\/thumbnail\/Application\/Generator\/ImagickThumbnailGenerator.php => 89"
[
    {
        "file": "\/var\/www\/html\/Dullahan\/thumbnail\/Application\/Generator\/ImagickThumbnailGenerator.php",
        "line": 89,
        "function": "readImageFile",
        "class": "Imagick",
        "type": "->"
    },
    {
        "file": "\/var\/www\/html\/Dullahan\/thumbnail\/Application\/Generator\/ImagickThumbnailGenerator.php",
        "line": 54,
        "function": "generateThumbnailFile",
        "class": "Dullahan\\Thumbnail\\Application\\Generator\\ImagickThumbnailGenerator",
        "type": "->"
    },
 [...]

我尝试使用imei(https://github.com/SoftCreatR/imei/)在系统上重新安装imagick,但没有帮助。

我正在使用 PHP 8.3,这是我的 imagick 扩展信息:

/etc/php/8.3/cli/conf.d/20-imagick.ini,
imagick
imagick module => enabled
imagick module version => 3.7.0
imagick classes => Imagick, ImagickDraw, ImagickPixel, ImagickPixelIterator, ImagickKernel
imagick.allow_zero_dimension_images => 0 => 0
imagick.locale_fix => 0 => 0
imagick.progress_monitor => 0 => 0
imagick.set_single_thread => 1 => 1
imagick.shutdown_sleep_count => 10 => 10
imagick.skip_version_check => 1 => 1

Imagick 版本:

版本:ImageMagick 7.1.1-36 Q16-HDRI x86_64 58ddb87ca:20240726 https://imagemagick.org 版权所有:(C) 1999 ImageMagick Studio LLC 许可证:https://imagemagick.org/script/license.php 功能:密码 DPC HDRI 模块 OpenMP(4.5) 代表(内置):bzlib cairo djvu fftw fontconfig freetype gslib gvc heic jbig jng jp2 jpeg jxl lcms lqr ltdl lzma openexr pangocairo png ps raqm 原始 rsvg tiff webp wmf x xml zip zlib zstd 编译器:gcc (11.4)

我已经使用在线检查器测试了我的文件,他们认为它们合适并且没有损坏(使用https://onlinepngtools.com/verify-if-image-is-png)。

我正在使用此代码加载文件并调整文件大小(所有扩展名的代码相同):

        $resource = $structure->getResource();
        $imagick = new \Imagick();
        $imagick->readImageFile($resource); // Throw is coming from here

        $imagick->resizeImage(
            $width ?? $imagick->getImageWidth(),
            $height ?? $imagick->getImageHeight(),
            \Imagick::FILTER_CATROM,
            0,
            $config->autoResize,
        );

更新

此外,我有时会在调整 jpg 大小时遇到错误:

"insufficient image data in file `\/tmp\/magick-80xEWLOtzkO2kqgFNI5LGEVZ2iBToQlR' @ error\/jpeg.c\/ReadJPEGImage_\/1166 => \/var\/www\/html\/Dullahan\/thumbnail\/Application\/Generator\/ImagickThumbnailGenerator.php => 89"
[
    {
        "file": "\/var\/www\/html\/Dullahan\/thumbnail\/Application\/Generator\/ImagickThumbnailGenerator.php",
        "line": 89,
        "function": "readImageFile",
        "class": "Imagick",
        "type": "->"
    },
    {
        "file": "\/var\/www\/html\/Dullahan\/thumbnail\/Application\/Generator\/ImagickThumbnailGenerator.php",
        "line": 54,
        "function": "generateThumbnailFile",
        "class": "Dullahan\\Thumbnail\\Application\\Generator\\ImagickThumbnailGenerator",
        "type": "->"
    },

此外,使用 cli 命令

magick
调整图像大小时一切正常。

magick check.png -resize 100x100 new.png

更新2

仅在使用文件句柄时才出现问题 - 将文件加载到内存并作为字符串传递似乎工作正常:

$resource = $structure->getResource();
$imagick = new \Imagick();
$imagick->readImageBlob(stream_get_contents($resource));

更新3

好吧,我已经成功地让它工作了(一点点):

$resource = $structure->getResource();
$imagick = new \Imagick();
$file = fopen('/tmp/test', 'w');
stream_copy_to_stream($resource, $file);
fclose($file);
// I have to close a handle and open it again otherwise it doesn't see a thing even with clearstatcache
$file = fopen('/tmp/test', 'r');
$imagick->readImageFile($file);

有人可以向我解释为什么一个文件句柄比另一个更好吗?也许有更好的方法来做到这一点?我的主要重点是不将文件加载到内存中,而是将其传递给 Imagick。

php imagick
1个回答
0
投票

发布我现在要使用的解决方案。

感谢@AlexHowansky,我发现我得到的流有些损坏(例如stream_get_meta_data返回空数组)。对此我真的无能为力。

稍后,我将创建一个临时文件句柄,在其中保存缩略图,因此我的解决方案是将 tmp 的创建提前一点,并将文件的内容复制到其中,然后将 tmp 传递给 Imagick:

$imagick = new \Imagick();
$tmp = tmpfile();
stream_copy_to_stream($resource, $tmp);
rewind($tmp);
$imagick->readImageFile($tmp);
$imagick->resizeImage(
    $width ?? $imagick->getImageWidth(),
    $height ?? $imagick->getImageHeight(),
    \Imagick::FILTER_CATROM,
    0,
    $config->autoResize,
);
$imagick->writeImageFile($tmp);
$imagick->destroy();

有了这个,我可以确定传递的句柄没有损坏(我省略了数据验证,如:tmpfile() 没有返回 false)。

© www.soinside.com 2019 - 2024. All rights reserved.