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 已安装但无法识别