PHP - imagecreatefromjpeg 为 <1M 图像使用 100M 内存

Posted

技术标签:

【中文标题】PHP - imagecreatefromjpeg 为 <1M 图像使用 100M 内存【英文标题】:PHP - imagecreatefromjpeg uses 100M memory for <1M image 【发布时间】:2013-07-20 07:41:48 【问题描述】:

图片小于 1MB,但大小约为 5500x3600。我正在尝试将图像缩小到小于 500x500 的大小。我的代码很简单。

    $image = imagecreatefromjpeg("upload/1.jpg");
    $width = imagesx($image);
    $height = imagesy($image);
    $pWidth = 500;
    $pHeight =  334;
    $image_p = imagecreatetruecolor($pWidth, $pHeight);
    setTransparency($image,$image_p,$ext);
    imagecopyresampled($image_p, $image, 0, 0, 0, 0, $pWidth, $pHeight, $width, $height);

我发现要处理这个图像,imagecreatefromjpeg 使用 memory_get_usage 使用 100M。

有没有更好的方法来做 imagecreatefromjpeg?是否有使用更少内存的解决方法或其他功能?

我确实要求我的服务器管理员增加内存,但我怀疑他们会将内存增加到 100M 或更多。我正在考虑限制用户可以上传的图片尺寸,但在用尽我的所有选项之前不会这样做,因为用户很可能会上传他们拍摄的图片。

顺便说一句,以下是我使用的使用100M内存的图像

【问题讨论】:

$_POST['imageSource'] 中有什么内容? 它是图像的来源。我将其更改为 upload/1.jpg 进行调试。我会删除它,因为那部分不相关。 使用5500x3600,您将需要至少 5500*3600*4 字节的内存 =~ 80MB。对于大图片,Imagick 扩展可能比 GD 有更好的性能 @dev-null-dweller 但是如何更好呢?此外,我从 php.net 上的讨论中发现 x * y * 3 * 1.7 更准确地计算出内存,它提供了 ~100M,我也在调试中发现了这一点。 【参考方案1】:

@dev-null-dweller 说的是正确答案:

对于 5500x3600,您至少需要 5500*3600*4 字节的内存 =~ 80MB。对于大图片,Imagick 扩展可能比 GD 有更好的性能

没有办法对此进行“改进”,因为这是处理图像所需的内存量。 JPEG 是一种压缩格式,因此它的文件大小无关紧要,重要的是实际尺寸。在 GD 中处理此类图像的唯一方法是增加内存限制。

如果您可以使用 ImageMagick 之类的库/命令行客户端,您可能会做得更好 - 当您 run ImageMagick from the command line 时,它的内存使用量不会计入内存限制。您是否可以这样做,您需要从您的网络主机或服务器管理员那里了解。

想到的另一个想法是使用您将图像发送到的图像大小调整 API。这将完全减轻服务器的负载。这个问题有一些指针:https://***.com/questions/5277571/is-there-a-cdn-which-provides-on-demand-image-resizing-cropping-sharpening-et

【讨论】:

有一些改进的方法。例如,可以在不解码的情况下将 JPEG 的大小减半(或四分之一等)。 @nwellnhof 也许,但不使用 GD,不是吗? (不过,无论使用什么工具,我都会对您所描述的资源感兴趣。) 有像 jpegtran 这样的工具可以直接处理 DCT 系数。但是为了节省内存,你只需要一种方法来逐个处理解码器的输出。不过,GD 和 ImageMagick 都不支持这种操作方式。 @nwellnhof 这很有趣。它本身可能是一个有价值的答案,为这个问题的未来读者提供选择 最终增加了内存然后转移到外部服务。【参考方案2】:

ImageMagick,至少在命令行上,能够使用libjpeg 的一个名为“加载时收缩”的功能,以避免在您只计划缩放时不必要地加载整个图像下来。

如果我将您上面的图像从当前的 3412x2275 调整到您实际处理的大小,则像这样 5500x2600

convert guys.jpg -resize 5500x2600 guys.jpg

我现在可以做一些测试...首先,简单的调整大小

/usr/bin/time -l convert guys.jpg -resize 500x334 small.jpg
        0.85 real         0.79 user         0.05 sys
 178245632  maximum resident set size                    <--- 178 MB
         0  average shared memory size
         0  average unshared data size
         0  average unshared stack size
     44048  page reclaims
         0  page faults
         0  swaps

你可以看到它在我的 Mac 上使用了 178 MB 的峰值。

如果我现在使用我提到的“加载时收缩” 功能:

/usr/bin/time -l convert -define jpeg:size=500x334 guys.jpg -resize 500x334 small.jpg
        0.06 real         0.04 user         0.00 sys
   8450048  maximum resident set size                 <--- Only 8 MB
         0  average shared memory size
         0  average unshared data size
         0  average unshared stack size
      2381  page reclaims
        33  page faults
         0  swaps

你可以看到它现在只需要 8MB。它也更快!

【讨论】:

以上是关于PHP - imagecreatefromjpeg 为 <1M 图像使用 100M 内存的主要内容,如果未能解决你的问题,请参考以下文章

调用未定义的函数 imagecreatefromjpeg() 并启用 GD

调用未定义的函数 imagecreatefromjpeg() GD 已安装但无法识别

已安装 Gd,但“调用未定义的函数 imagecreatefromjpeg()”

php图片水印

php 给图片加水印

PHP制作水印图