ImageMagick:如何在调整大量图像文件大小时实现低内存使用?

10

我想调整大约5200个图像文件(PPM格式,每个文件大小为5 MB),并使用convert将它们保存为PNG格式。

简短版本:

convert会占用24 GB的内存,尽管我使用了指示convert按顺序处理图像文件的语法。

详细版本:

针对超过25 GB的图像数据,我认为不应同时处理所有文件。我搜索了ImageMagick文档,了解如何按顺序处理图像文件,并找到了以下内容:(链接)

逐个调整每个读取的图像速度更快、资源占用更少:

$ convert '*.jpg[120x120]' thumbnail%03d.png

此外,教程中还提到:

例如,不要使用...

montage '*.tiff' -geometry 100x100+5+5 -frame 4 index.jpg

该命令首先读取所有tiff文件,然后再调整它们的大小。相反,可以使用...

montage '*.tiff[100x100]' -geometry 100x100+5+5 -frame 4 index.jpg

该命令会在读取每个图像后调整其大小,然后再进行下一个图像的处理。这样可以大大减少内存使用量,并可能在达到内存限制时防止磁盘交换(抖动)。

因此,我正在执行以下操作:

$ convert '*.ppm[1280x1280]' pngs/%05d.png

根据文档,应该逐个处理每个图像文件:读取、调整大小、写入。我正在一台拥有12个真实核心和24GB内存的机器上进行操作。然而,在前两分钟内,convert进程的内存使用量增长到约96%。它会在那里停留一段时间,CPU使用率达到最大值。再过一段时间,该进程就会死亡,并显示以下信息:

Killed

此时,还未生成任何输出文件。我正在使用Ubuntu 10.04,convert --version显示如下:
Version: ImageMagick 6.5.7-8 2012-08-17 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2009 ImageMagick Studio LLC
Features: OpenMP 

看起来convert在开始转换之前尝试读取所有数据。因此,要么是convert存在问题,要么是文档存在问题,或者我没有正确阅读文档。
有什么问题?如何在调整此大量图像文件大小时实现低内存使用?
顺便说一句:一个快速的解决方案就是使用shell循环遍历文件,并单独为每个文件调用convert。但我想了解如何使用纯ImageMagick实现相同的效果。
谢谢!

1
如果你尝试像这样使用:find . -name "*.ppm" -exec convert '{}[1280x1280]' pngs/%05d.png \; 这能行吗? find -exec 将会列出所有的文件,并对每个文件执行给定的命令。 - Flinth
@epingle:原则上这样做是可以的(就像我在问题的最后部分所说的那样)。像这样做也是我的临时解决方案。不过,它还应该能够(应该)使用纯 ImageMagick 来完成。(请注意,你提出的特定解决方案行不通,因为文件计数器 %05d 总是为零)。 - Dr. Jan-Philip Gehrcke
好的,抱歉,我没有看到你消息的结尾,也没有意识到 %05d 是一个计数器。 - Flinth
我会使用netpbm和gnu make (-j12)。如果netpbm对您来说可以的话,我会复制/粘贴我的工作makefile作为示例。 - Ray
3个回答

6

没有直接访问您的系统,因此很难帮助您调试问题。

但是您可以采取三个措施来帮助自己缩小问题范围:

  1. -monitor添加为第一个命令行参数,以查看更多有关正在发生的情况的详细信息。

  2. (可选)添加-debug all -log "domain: %d +++ event: %e +++ function: %f +++ line: %l +++ module: %m +++ processID: %p +++ realCPUtime: %r +++ wallclocktime: %t +++ userCPUtime: %u \n\r"

  3. 临时不要使用“*.ppm [1280x1280]”作为参数,而应改用“a * .ppm [1280x1280]”。目的是将通配符扩展(或其他适当的方式)限制为仅几个匹配项,而不是所有可能的匹配项。

如果您执行了“2.”,那么您也需要执行“3.”,否则您将被输出的大量信息所淹没。(另外,您的系统似乎无法在不终止进程的情况下处理完整的通配符...)

如果您找不到解决方案,则...

  1. ...在官方ImageMagick错误报告论坛上注册用户名。
  2. ...将您的问题报告给他们,看看他们是否能够帮助您(如果您礼貌地询问,这些人非常友好和响应)。

3
我遇到了相同的问题,似乎是因为ImageMagick将临时文件创建在/tmp目录下,而该目录通常被挂载为tmpfs。只需将您的tmp移动到其他地方即可。
例如: - 在大型外部驱动器上创建一个名为“tmp”的文件夹 mkdir -m777 /media/huge_device/tmp - 确保权限设置为777 chmod 777 /media/huge_device/tmp - 作为root用户,将其挂载以取代您的/tmp mount -o bind /media/huge_device/tmp /tmp 注意:应该可以使用TMP环境变量来执行相同的操作。

2
如果你有12个核心,我会选择GNU Parallel,像这样的东西非常有效。它一次只处理12张图片,同时保留输出文件编号,只使用最小的RAM。
scene=0
for f in *.ppm; do
   echo "$f" $scene
   ((scene++))
done | parallel -j 12 --colsep ' ' --eta convert {1}[1280x1280] -scene {2} pngs/%05d.png

注释

-scene 命令可以设置场景计数器,该计数器在您的%05d 部分显示。

--eta 命令可以预测作业完成时间(预计到达时间)。

-j 12 命令可以同时并行运行12个作业。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接