在Linux中将PNG批量转换为JPG


163

有谁知道在Linux中将一堆PNG批量转换为JPG的好方法吗?(我正在使用Ubuntu)。

我可以放入shell脚本中的png2jpg二进制文件是理想的。

Answers:


237

最好的选择是使用Imagemagick

我不是实际用法专家,但是我知道您几乎可以做任何与此有关的图像!

一个例子是:

convert image.png image.jpg

它将保留原始图像并创建转换后的图像。至于批次。我认为您需要使用Mogrify工具(在imagemagick中使用相同的命令行)。请记住,这会覆盖旧图像。

该命令是:

mogrify -format jpg *.png  

7
太棒了,这正是我的追求,并将再次使用。顺便说一句,只是澄清一下,我没有意识到这是您的意思:convert用于生成单独的输出文件,mogrify用于修改原始图像。
尼斯

1
具有透明背景的png图像无法正确转换为jpg。
vishnu

4
要转换具有透明背景的PNG,请使用以下命令:mogrify -format jpg -background black -flatten *.png
hyperknot 2012年

3
mogrify -format jpeg img.png我有2个文件并file img.*报告一个png(原始未修改)和一个新的jpeg 后,在我的Linux框上使用@KevinCox 。因此mogrify,在这种情况下,请勿覆盖原始文件。
neurino

4
mogrify文档中:“ 此工具类似于,convert除了原始图像文件(除非使用-format选项更改文件后缀)外,还可以根据您的要求进行任何更改。
janko-m

82

我还有几个解决方案。

最简单的解决方案就像大多数已经发布的解决方案一样。一个简单的bash for循环。

for i in *.png ; do convert "$i" "${i%.*}.jpg" ; done

由于某种原因,我倾向于避免bash中的循环,因此这是一种更加统一的xargs方法,使用bash进行名称处理。

ls -1 *.png | xargs -n 1 bash -c 'convert "$0" "${0%.*}.jpg"'

我用的那个。它使用GNU Parallel一次运行多个作业,从而提高了性能。默认情况下,它已安装在许多系统上,并且几乎肯定在您的存储库中(这是一个很好的程序)。

ls -1 *.png | parallel convert '{}' '{.}.jpg'

作业数默认为您拥有的进程数。我在双核系统上使用3个作业发现更好的CPU使用率。

ls -1 *.png | parallel -j 3 convert '{}' '{.}.jpg'

如果您需要一些统计信息(预计到达时间,完成的工作,每项工作的平均时间...)

ls -1 *.png | parallel --eta convert '{}' '{.}.jpg'

如果使用的是GNU Parallel,则还有另一种语法。

parallel convert '{}' '{.}.jpg' ::: *.png

某些其他版本(包括debian)的语法与此类似。

parallel convert '{}' '{.}.jpg' -- *.png

2
为for中的正确bash字符串扩展+1,如果我能再给您一个提起并行的支持,我会的。但是,有一个错别字-for done循环的末尾需要一个。另外,对于并行的东西,您可以避免将其ls与类似以下内容的管道一起使用:(parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png请参阅此处
evilsoup 2013年

固定错别字。我不知道这是一个很酷的语法。我不知道我更喜欢哪一个,可能是出于与我不希望在bash中使用循环相同的原因。我把它当作解决方案,因为它可能是更“正确”的方法,但我可能会坚持ls自己的方法,因为它对我来说更有意义。
Kevin Cox

1
...尽管应注意,语法仅适用于GNU并行。在某些Linux发行版(如Debian和Ubuntu)中打包的并行实际上是一个不同的版本,其语法略有不同(使用--而不是:::)-即便如此,它仍然令人沮丧地缺少GNU并行的某些功能。
evilsoup

(尽管发行版中未打包GNU parallel的发行版可以使用此处的说明从源代码非常容易地安装它)
evilsoup 2013年

我认为我应该在那时更改它,以便它可以与尽可能多的版本一起使用。
凯文·考克斯

26

convert在许多Linux发行版中找到的命令是作为ImageMagick套件的一部分安装的。以下是convert在目录中的所有PNG文件上运行的bash代码,可以避免这种双重扩展问题:

for img in *.png; do
    filename=${img%.*}
    convert "$filename.png" "$filename.jpg"
done

8
根据convert的手册页:“ convert程序是ImageMagick(1)工具套件的成员。”
2009年

1
你是对的。由于某种原因,我认为它是另一个库的一部分。无论哪种方式,我上面发布的代码都是在目录中自动进行批量转换的正确方法。
Marcin

2
您可以使用bash扩展来改进该命令,例如:for f in *.png; do convert "$f" "${f/%png/jpg}"; done
evilsoup 2013年

只要记住它是区分大小写的即可。我的相机将其命名为* .JPG,但一开始并没有意识到这一点。
tsenapathy

10

tl; dr

对于只需要最简单命令的用户:

转换保留原始文件:

mogrify -format jpg *.png

转换删除原始文件:

mogrify -format jpg *.png && rm *.png

批量转换说明

Kinda参加聚会很晚,但只是为了消除对可能不太熟悉cli的人的所有困惑,这里有个超级笨拙的参考和解释。

示例目录

bar.png
foo.png
foobar.jpg

简单转换

保留所有原始png文件以及创建jpg文件。

mogrify -format jpg *.png

结果

bar.png
bar.jpg
foo.png
foo.jpg
foobar.jpg

说明

  • mogrifyImageMagick图像处理工具套件的一部分。
    • mogrify 在适当的位置处理图像,这意味着原始文件会被覆盖,但该-format选项除外。(从网站This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option)
  • - format选项指定您将要更改格式,下一个参数必须是类型(在本例中为jpg)。
  • 最后*.png是输入文件(所有以.png结尾的文件)。

转换并删除

将所有png文件转换为jpg,删除原始文件。

mogrify -format jpg *.png && rm *.png

结果

bar.jpg
foo.jpg
foobar.jpg

说明

  • 第一部分与上述完全相同,它将创建新的jpg文件。
  • &&是一个布尔运算符。简而言之:
    • 程序终止时,它将返回退出状态。状态为“ 0无错误”。
    • 由于&&执行短路评估,因此只有在没有错误的情况下才执行正确的部分。这很有用,因为如果转换原始文件时出错,您可能不想删除所有原始文件。
  • rm命令删除文件。

花式的东西

现在,这里是对谁的人一些东西舒适的CLI。

如果在转换文件时需要一些输出:

for i in *.png; do mogrify -format jpg "$i" && rm "$i"; echo "$i converted to ${i%.*}.jpg"; done

转换所有子目录中的所有png文件,并为每个子目录提供输出:

find . -iname '*.png' | while read i; do mogrify -format jpg "$i" && rm "$i"; echo "Converted $i to ${i%.*}.jpg"; done

转换所有子目录中的所有png文件,将所有生成的jpg放入all目录中,对其编号,删除原始png文件,并在发生每个文件时显示输出:

n=0; find . -iname '*.png' | while read i; do mogrify -format jpg "$i" && rm "$i"; fn="all/$((n++)).jpg"; mv "${i%.*}.jpg" "$fn"; echo "Moved $i to $fn"; done

如果您while read
放弃

@don_crissti,阅读时出了什么问题?
史蒂芬·杰弗里斯

这很容易出错(除非您100%确定要处理的文件名是健全的)且速度很慢(例如非常非常慢)。
don_crissti 2015年

JPG的默认质量是什么?如何保存文件时间戳?
Dan Dascalescu

@DanDascalescu上面的方法(最后一个方法除外)将保留文件名,但替换其扩展名,因此带有时间戳的文件应该可以(总是先进行复制和测试)。根据ImageMagick的说法,“默认情况下,如果可以确定输入图像,则默认使用估计的图像质量,否则为92”(imagemagick.org/script/command-line-options.php#quality)可以使用-quality来指定质量<number>其中<number>是1〜100
史蒂芬杰弗里斯

8

实际上,png2jpg您要查找的实际“ ”命令分为两个称为pngtopnm和的命令cjpeg,它们分别是netpbmlibjpeg-progs包的一部分。

png2pnm foo.png | cjpeg > foo.jpeg

6
find . -name "*.png" -print0 | xargs -0 mogrify -format jpg -quality 50

1
感谢您提供深度/递归目录单行解决方案,该解决方案将生成的*.jpg文件保留在原始文件旁边*.png,展示了如何减小文件大小/质量并且不会由于目录或文件名中的任何奇数字符而中断。
乔尔·普拉

5

我的快速解决方案 for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done


2
这一定是我见过的最丑陋,最复杂的命令行之一
evilsoup 2013年

1
@evilsoup说实话,这对于shell脚本来说很优雅。声称它是令人费解的是不公平的。
Max Howell,

8
@MaxHowell男人。否。这将是一个优雅的版本:for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done。这避免了完全没有必要lsgrepsed调用(和echo,但IIRC这是Bash内建的,因此不会有任何/很小的性能影响),并摆脱两个管道和两个子shell的,涉及较少打字。由于不是所有版本ls都可以安全解析,因此它甚至更具可移植性。
evilsoup

@evilsoup我站纠正了!做得好。
Max Howell 2013年

4

很多年为时已晚,我专门编写了一个专门用于此目的的png2jpeg实用程序。

通过@Marcin修改代码:

#!/bin/sh

for img in *.png
do
    filename=${img%.*}
    png2jpeg -q 95 -o "$filename.jpg" "$filename.png"
done

3

对于批处理:

for img in *.png; do
  convert "$img" "$img.jpg"
done

不过,您最终会得到像image1.png.jpg这样的文件名。

这将适用于bash,甚至可能适用于bourne。我不了解其他shell,但是唯一的区别可能是循环语法。


1

当文件跨越多个目录时,这就是我用来转换的内容。我最初的是TGA到PNG

find . -name "*.tga" -type f | sed 's/\.tga$//' | xargs -I% convert %.tga %.png

概念是您find需要的文件,剥离扩展名,然后使用重新添加xargs。因此,对于从PNG到JPG的图片,您需要更改扩展名并做另一件事来处理Alpha通道,即设置背景(在此示例中为白色,但您可以更改它),然后使图像变平

find . -name "*.png" -type f | sed 's/\.png$//' | xargs -I% convert %.png -background white -flatten  %.jpg
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.