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



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

短版本:

convert占用了24GB的内存,尽管我使用了告诉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 RAM的机器上做这件事。然而,在最初的两分钟内,convert进程的内存使用率增长到约96%。它会在那里停留一段时间。CPU使用率达到最大值。再长一点,过程就结束了,只是说:

杀死

此时,尚未生成任何输出文件。我在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中存在错误,要么文档有问题,要么我没有正确阅读文档。

怎么了?如何在调整大量图像文件的大小的同时实现低内存使用率?

BTW:一个快速的解决方案是使用shell在文件上循环,并为每个文件独立调用convert。但我想了解如何使用纯ImageMagick实现同样的效果。

谢谢!

如果不能直接访问您的系统,很难帮助您调试它。

但你可以做三件事来帮助自己缩小这个问题:

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

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

  3. 暂时不要使用"*.ppm[1280x1280]"作为参数,而是使用"*.ppm[1280x1200]"。其目的是将通配符扩展(或其他适当的方式来实现)限制为仅少数匹配,而不是所有可能的匹配。

如果你做"2.",你也需要做"3.",否则你会被大量的输出淹没。(此外,您的系统似乎无法在不终止进程的情况下处理完整的通配符…)

如果你找不到解决方案,那么。。。

  1. 。。。在官方ImageMagick错误报告论坛注册用户名
  2. 。。。在那里报告你的问题,看看他们是否能帮助你(如果你礼貌地问,这些人相当友好,反应灵敏)

遇到同样的问题,似乎是因为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环境变量一起使用来执行相同的操作。

如果你有12个核心,我会选择GNU并行——类似这样的东西,效果很好。由于它一次只处理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个作业。

最新更新