在使用ImageMagick调整jpg大小时,似乎忽略了-limit
选项。
下面的命令使用docker
来模拟在有限的空闲内存(100MB)的机器上运行ImageMagick: ImageMagick命令通过-limit memory 5MiB
传递4958 × 6198 JPEG(原始文件大小:5.5MB)来调整大小。
结果是ImageMagick被容器的OOM Killer杀死,这意味着ImageMagick试图分配超过~100MB的内存,而不是保持在它被指示的~5MB的限制内。如果您增加(或删除)docker run
上的--memory 100m
标志,该命令将成功:
# Download a 5.5MB JPEG (4958 × 6198)
curl 'https://images.unsplash.com/photo-1534970028765-38ce47ef7d8d?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&dl=trail-5yOnGsKUNGw-unsplash.jpg'
-o 5500kb-image.jpg
docker run --memory 100m
-v $(pwd):/imgs
dpokidov/imagemagick
/imgs/5500kb-image.jpg
-debug All -limit memory 5MiB -limit map 10MiB -resize 400
/imgs/5500kb-image-resized.jpg
我怎么能内存绑定ImageMagick时调整jpeg大小?
我觉得你的参数顺序不对。
如果你在linux上,/usr/bin/time
是非常方便的测量峰值内存使用。你正在运行这个命令:
$ /usr/bin/time -f %M:%e
convert
5500kb-image.jpg
-limit memory 5MiB -limit map 10MiB
-resize 400 5500kb-image-resized.jpg
346060:2.37
ie。350mb内存,2.37s CPU时间
如果你把限制放在前面,你会看到:
$ /usr/bin/time -f %M:%e
convert
-limit memory 5MiB -limit map 10MiB
5500kb-image.jpg -resize 400 5500kb-image-resized.jpg
105468:2.64
现在峰值只有105mb,运行时间差不多。您需要在加载图像之前设置限制。
正如Mark所说,vipsthumbnail
相当快,内存消耗更少。我明白了:
$ /usr/bin/time -f %M:%e
vipsthumbnail 5500kb-image.jpg --size 400 -o 5500kb-image-resized.jpg
133676:0.28
130mb, 0.28s。
这仍然相当高。您的图像是渐进式JPG—在缩略开始之前,这些图像必须完全加载到内存中,并且不可能利用jpeg shrink-on-load之类的东西。
如果我你的图像转换为一个普通的jpeg,我明白了:
$ /usr/bin/time -f %M:%e
vipsthumbnail 5500kb-image-regular.jpg --size 400 -o 5500kb-image-resized.jpg
40200:0.09
40mb和0.1s的CPU。
vipsthumbnail可以用少量内存调整非常大的图像,例如:
$ vipsheader st-francis.jpg
st-francis.jpg: 30000x26319 uchar, 3 bands, srgb, jpegload
$ /usr/bin/time -f %M:%e
vipsthumbnail st-francis.jpg --size 400 -o 5500kb-image-resized.jpg
49692:2.52
50mb, 2.5s。
4958×6198图像有30,729,684像素。每个将有一个R, G和B通道制作92,189,052个样本。由于每个样本通常以16位(2字节)的分辨率存储,因此您需要180+MB的RAM来保存它。以及用于输出图像的空间。
你通常会发现libvips
更节省内存,如果这是你最关心的。这里的示例显示了相对内存需求以及如何度量它们。