如何批量调整数百万张图片的大小以适应最大宽度和高度?

10

情况

我正在寻找一种批量调整约1500万个不同文件类型的图像大小的方法,以适应特定的边界框分辨率(在这种情况下,图像不能大于1024 * 1024),而不会扭曲图像,从而保留正确的长宽比。所有文件目前都位于我具有sudo访问权限的Linux服务器上,因此如果需要安装任何内容,我可以操作。

我尝试过的事情

在Windows下尝试了一些工具(Adobe Photoshop和其他工具)后,我不再愿意在自己的计算机上运行此操作,因为渲染时几乎无法使用。考虑到这项工作的规模,我真的很想寻找一些命令行魔法来直接在Linux上运行它,但是迄今为止,我的ImageMagick尝试没有给我任何可用的东西,因为我只得到了错误。 老实说,ImageMagick的文档可能需要改进...或者有人应该付出努力创建一个良好的Web界面,以创建这些神秘的图像转换一行代码。

所需输出格式

我需要将图像的大小调整为相同的文件名,并且格式适合于特定的最大尺寸,例如1024 * 1024,这意味着:

  • 2048 * 1024的JPG变为75%质量下的1024 * 512的JPG
  • 1024 * 2048的PNG变为512 * 1024的PNG

生成的图像不应包含任何其他透明像素来填充其余像素;我只是想找到一种将图像转换为有限分辨率的方法。

谢谢您的帮助!


我再好的时机都无法要求...我有这个脚本懒散在那里,我想自己为它写一个问答:D - Henry van Megen
1个回答

14

我发现将数百万张这样的图片转换为另一种格式的最佳方法是创建一个简单的bash脚本,开始转换它发现的所有图片,就像下面列出的那个:

要编辑此bash脚本,我使用nano。如果没有nano: "apt-get install nano" 适用于Ubuntu/Debian 或 "yum install nano"适用于CentOS/CloudLinux. 对于其他发行版:请使用Google搜索) 但您可以自由选择任何编辑器。

Bash脚本

首先,通过启动您喜欢的编辑器(我的是nano)来创建bash脚本:

nano -w ~/imgconv.sh

然后用这段内容填充它:

#!/bin/bash
find ./ -type f -iname "*.jpeg" -exec mogrify -verbose -format jpeg -layers Dispose -resize 1024\>x1024\> -quality 75% {} +
find ./ -type f -iname "*.jpg" -exec mogrify -verbose -format jpg -layers Dispose -resize 1024\>x1024\> -quality 75% {} +
find ./ -type f -iname "*.png" -exec mogrify -verbose -format png -alpha on -layers Dispose -resize 1024\>x1024\> {} +

然后您只需要使用 chmod +x ~/imgconv.sh 将其变为可执行文件,并从您想要调整大小的所有子目录中的主要图像目录运行它:

cd /var/www/webshop.example.com/public_html/media/
~/imgconv.sh

这应该会开始转换过程。

说明

脚本的工作原理是使用find查找任何大小写的扩展名为.jpeg的文件,然后运行一个命令:

find ./ -type f -iname "*.jpeg" -exec <COMMAND> {} +

然后使用"-exec {} +"参数执行适当的转换作业:

mogrify -verbose -format jpeg -layers Dispose -resize 1024\>x1024\> -quality 75% <### the filename goes here, in this case *.jpeg ###>

如果您正在处理比今天更早的文件,并且希望避免重新转换您已经在今天转换过的文件,甚至可以使用 -mtime +1 选项告诉“find”命令只转换早于今天的文件,示例如下:

#!/bin/bash
find ./ -type f -mtime +1 -iname "*.jpeg" -exec mogrify -verbose -format jpeg -layers Dispose -resize 1024\>x1024\> -quality 75% {} +
find ./ -type f -mtime +1 -iname "*.jpg" -exec mogrify -verbose -format jpg -layers Dispose -resize 1024\>x1024\> -quality 75% {} +
find ./ -type f -mtime +1 -iname "*.png" -exec mogrify -verbose -format png -alpha on -layers Dispose -resize 1024\>x1024\> {} +

性能

使用更多核心进行此过程的一个非常简单的方法是在每行后面添加&,将每个作业分叉到后台。另一种方式是使用GNU Parallel,特别是使用-X参数,它将使用所有CPU核心并快速完成作业。

但无论你使用什么类型的并行化技术,请确保只在你自己的系统上执行操作,而不要在共享磁盘系统上执行操作,因为追求最大性能会拖慢你的硬件或虚拟机性能。

这项工作需要一段时间,所以请务必提前设置一个没有超时/空包的屏幕或终端。在我的系统上,它每分钟处理约5000个文件,因此整个作业应该不到50-60小时...听起来像是在周末运行的好作业。

只需通过编写单独的命令将所有文件扩展名彼此分开即可。把所有选项堆叠在一起,并让'mogrify'对所有图像格式使用所有选项是行不通的。

ImageMagick是一个强大的工具,有了正确的使用方式。


1
刚刚在一组1500张图片上测试了一下,效果非常好!感谢您的解释和Bash脚本! - m.devrees
1
不用谢... 谢谢你的问题。我本来想分享它,但你帮我省去了自己提问的麻烦 :) - Henry van Megen
2
如果你使用 find . -name "*.JPEG" -o -name "*.jpeg",你将找不到以 Jpg 结尾的文件,所以最好使用 -iname "*.JPG"。如果你为 1500 万个文件中的每一个执行一个 mogrify 进程,你需要很多天时间,而 mogrify 可以接受多个输入文件,因此你应该在结尾处使用 + 而不是 \; 来减少创建的进程数量。 - Mark Setchell
1
此外,如果您使用 GNU Parallel 并使用 -X 参数,它将使用所有 CPU 核心并更快地完成作业,这样会好得多。如果您在 StackOverflow 上搜索最近使用并行处理的答案,那么它的语法非常简单。 - Mark Setchell
1
不,mogrify 不会崩溃,因为 find 知道命令行参数的最大长度。它将在退出之前处理所有传入的文件,但这可能是30-100+个文件,因此您只会创建1/30或1/100数量的 mogrify 进程,这将节省大量时间。 - Mark Setchell
显示剩余2条评论

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