【问题标题】:Image magick/PHP is falling over with large imagesImage magick/PHP 因大图像而崩溃
【发布时间】:2016-04-01 06:50:23
【问题描述】:

我有一个 PHP 脚本,用于调整用户 FTP 文件夹中的图像大小,以便在他的网站上使用。

虽然调整大小很慢,但脚本已正确完成过去所有图像。然而,最近,用户上传了一张 21 兆像素 JPEG 图像的相册,正如我所发现的,该脚本无法转换图像,但没有给出任何 PHP 错误。当我查阅各种日志时,我发现多个 Apache 进程因内存不足错误而被终止。

PHP 脚本的功能部分本质上是一个 for 循环,它遍历我在磁盘上的图像并调用一个方法来检查缩略图是否存在,然后执行以下操作:

$image = new Imagick();
$image->readImage($target);
$image->thumbnailImage(1000, 0);
$image->writeImage(realpath($basedir)."/".rescale."/".$filename);
$image->clear();
$image->destroy();  

服务器有 512MB 的 RAM,通常至少有 360MB 以上的空闲空间。

PHP 的内存限制目前设置为 96MB,但我之前已将其设置得更高,但对问题没有任何影响。
根据我的估计,一张 21 兆像素的图像在未压缩时应该占据 80MB+ 的区域,所以我很困惑为什么除非没有从内存中删除 Image Magick 对象,否则 RAM 会如此迅速地消失。

有什么方法可以优化我的脚本以更有效地使用更少的内存或垃圾收集?
我是不是没有内存来处理这么大的图像?

干杯

【问题讨论】:

  • 尝试只使用 'convert' 命令行工具,它应该会更快,并且不会计入 PHP 的内存限制。

标签: imagemagick


【解决方案1】:

查看this answer了解更详细的说明。

imagick 使用一个共享库,它的内存使用量超出了 PHP 的能力范围,因此调整 PHP 内存和垃圾收集将无济于事。

尝试在创建 new Imagick() 对象之前添加它:

// pixel cache max size
IMagick::setResourceLimit(imagick::RESOURCETYPE_MEMORY, 32);
// maximum amount of memory map to allocate for the pixel cache
IMagick::setResourceLimit(imagick::RESOURCETYPE_MAP, 32);

当它需要超过 32 MB 来处理图像时,它会导致 imagick 交换到磁盘(默认为 /tmp)。它会更慢,但不会耗尽 RAM(除非 /tmp 在 ramdisk 上,在这种情况下,您需要更改 imagick 写入其临时文件的位置)。

【讨论】:

  • 这是旧的,但这个评论是正确的,也是错误的。值以字节为单位,而不是 MB。 $magick->setResourceLimit(\imagick::RESOURCETYPE_MEMORY, 67108864); $magick->setResourceLimit(\imagick::RESOURCETYPE_MAP, 67108864); 用于 64 MB 限制;不要在新版本的 imagick 上使用静态调用
【解决方案2】:

MattBianco 几乎是正确的,唯一的变化是内存限制以字节为单位,因此 32MB 为 33554432:

// pixel cache max size
IMagick::setResourceLimit(imagick::RESOURCETYPE_MEMORY, 33554432);
// maximum amount of memory map to allocate for the pixel cache
IMagick::setResourceLimit(imagick::RESOURCETYPE_MAP, 33554432);

【讨论】:

  • 您应该在较新版本的 imagick 中使用调用的非静态变体; $img->setResourceLimit(\imagick::RESOURCETYPE_MEMORY, 33554432);
  • 这是不正确的,文档指出限制以兆字节为单位php.net/manual/en/imagick.setresourcelimit.php
  • 我收回,对不起。这是不正确的文档。这些值实际上以字节为单位。
【解决方案3】:

$image->readImage() 之前调用$image->setSize() 以让libjpeg 在加载时调整图像大小以减少内存使用。

(编辑),示例用法:Efficient JPEG Image Resizing in PHP

【讨论】:

  • 感谢 Steve-o,事实证明这对内存使用有很大帮助,我通过这样做完成了整个方法。然而,应该注意的是,对于我正在尝试做的更大的桌面壁纸(1920x1200+),它仍然在困扰着我。我想我要么必须非常积极地使用 setSize(),让我的用户使用较小的图像,要么完全使用另一种方法。感谢您的建议!
猜你喜欢
  • 2015-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-08
  • 2017-07-05
  • 1970-01-01
  • 2014-05-30
  • 1970-01-01
相关资源
最近更新 更多