我正在使用 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。
发布我现在要使用的解决方案。
感谢@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)。