LinuxでのPNGからJPGへのバッチ変換


163

LinuxでたくさんのPNGをJPGにバッチ変換する良い方法を知っている人はいますか?(Ubuntuを使用しています)。

シェルスクリプトにドロップするだけのpng2jpgバイナリが理想的です。

回答:


237

あなたの最善の策は、Imagemagickを使用することです

私は実際の使用法の専門家ではありませんが、これに関連する画像はほとんど何でもできることを知っています!

例は次のとおりです。

convert image.png image.jpg

変換された画像を作成するだけでなく、元の画像も保持します。バッチは。Mogrifyツールを使用する必要があると思います(imagemagickの場合は同じコマンドラインから)。これにより、古いイメージが上書きされることに注意してください。

コマンドは次のとおりです。

mogrify -format jpg *.png  

7
素晴らしい、それはまさに私が望んでいたものであり、再び使用します。ちなみに、私がこれを理解していないことを明確にするために、これはあなたが意図したものです:convertは別の出力ファイルを生成するために使用され、mogrifyは元の画像を変更するために使用されます。
09年

1
背景が透明なpng画像は、jpgに正しく変換されません。
ヴィシュヌ

4
背景が透明なPNGを変換するには、次のコマンドを使用しますmogrify -format jpg -background black -flatten *.png
。– hyperknot

3
mogrify -format jpeg img.png2つのファイルがあり、file img.*1つのpng、元の未処理、および新しいjpeg ファイルを報告した後、Linuxボックスで@KevinCox 。だから、mogrifyないではない。この場合には、元のファイルを上書きします。
ニューリノ

4
mogrifyドキュメントから:「このツールはconvert、元のイメージファイルが(-formatオプションでファイルサフィックスを変更しない限り)必要な変更で上書きされることを除いて似ています。
janko-m

82

さらにいくつかの解決策があります。

最も簡単なソリューションは、すでに投稿されているほとんどのソリューションと同じです。単純なbash forループ。

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

なんらかの理由でbashのループを避ける傾向があるので、ここでは名前のマングリングにbashを使用する、よりユニキシなxargsアプローチを示します。

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'

いくつかの統計情報(ETA、完了したジョブ、ジョブごとの平均時間など)が必要な場合

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

GNU Parallelを使用している場合の代替構文もあります。

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

他のバージョン(debianを含む)の同様の構文。

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

2
forでの正しいbash文字列展開のために+1。ただし、タイプミスが1つあります-for doneループの最後に必要です。また、並列処理については、次のlsような構造でパイプとパイプを使用することを避けることができますparallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.pngここを参照)
-evilsoup

タイプミスを修正。それは私が知らないクールな構文です。おそらくbashでループを使用しない方が好きなのと同じ理由で、どちらが好きなのかわかりません。おそらくより「適切な」方法であるため、私はそれを解決策に入れましたが、私lsにとってはより理にかなっているので、おそらく私は自分自身の方法に固執するでしょう。
ケビンコックス

1
...ただし、構文はGNUパラレルでのみ機能することに注意してください。一部のLinuxディストリビューション(DebianやUbuntuなど)にパッケージ化されているパラレルは、実際にはわずかに異なる構文を持つ異なるバージョンです(使用するの--ではなく使用します:::)。
evilsoup

(GNUパラレルをパッケージ化していないディストリビューションの場合は、こちらの手順を使用して、ソースから簡単にインストールできます
-evilsoup

できる限り多くのバージョンで動作するように、当時の設定を変更する必要があると思います。
ケビンコックス

26

convert多くのLinuxディストリビューションで見つかったコマンドはImageMagickのスイートの一部としてインストールされます。convertディレクトリ内のすべてのPNGファイルで実行し、その二重拡張子の問題を回避するためのbashコードは次のとおりです。

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

8
convertのmanページによると:「convertプログラムはImageMagick(1)ツールスイートのメンバーです。」
09年

1
あなたは正しいです。何らかの理由で、私はそれが別の図書館の一部だと思った。いずれにしても、上記のコードは、ディレクトリ内でバッチ変換を自動化する正しい方法です。
マーチン

2
bash拡張を使用して、次のようなコマンドを改善できますfor f in *.png; do convert "$f" "${f/%png/jpg}"; done
。– evilsoup

大文字と小文字が区別されることを覚えておいてください。私のカメラは* .JPGという名前を付けていますが、最初はこれに気付きませんでした。
tsenapathy

10

tl; dr

最も単純なコマンドだけが必要な場合:

元のファイルを変換して保持する:

mogrify -format jpg *.png

元のファイルの変換削除

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

バッチ変換の説明

ちょっとパーティーに遅れましたが、cliにあまり慣れていない人のために混乱をすべて解消するために、ここでは非常に簡潔なリファレンスと説明を示します。

サンプルディレクトリ

bar.png
foo.png
foobar.jpg

シンプルな変換

すべての元のpngファイルを保持し、jpgファイルを作成します。

mogrify -format jpg *.png

結果

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

説明

  • mogrifyは、画像処理のためのImageMagickツールスイートの一部です。
    • 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

@don_crissti、読んでいる間何が悪いの?
スティーブンジェフリーズ

エラーが発生しやすく(正常なファイル名を100%処理していると確信していない限り)、遅い(非常に、非常に、非常に遅いなど)です。
don_crissti

デフォルトのJPG品質とは何ですか?また、ファイルのタイムスタンプをどのように保持できますか?
ダンダスカレスク

@DanDascalescu上記のメソッド(最後のメソッドを除く)はファイル名を保持しますが、拡張子を置き換えます。そのため、タイムスタンプ付きのファイルは大丈夫です(常にコピーを作成して最初にテストします)。ImageMagickによれば、「デフォルトでは、決定できる場合は入力画像の推定品質を使用し、それ以外の場合は92」を使用します(imagemagick.org/script/command-line-options.php#quality)-qualityで品質を指定できます<番号>ここで、<番号>は1〜100である
スティーブン・ジェフリーズ

8

実際にpng2jpg探している「」コマンドは、実際にはpngtopnmandと呼ばれる2つのコマンドに分割され、それぞれとパッケージのcjpeg一部です。netpbmlibjpeg-progs

png2pnm foo.png | cjpeg > foo.jpeg

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

1
結果の*.jpgファイルを元のファイルの隣に残し、*.pngディレクトリのサイズや品質を下げる方法を示し、ディレクトリまたはファイル名に奇妙な文字が含まれているために壊れない、深い/再帰的なディレクトリ1行ソリューションのおかげです。
ジョエルプラ14

5

私の迅速な解決策 for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done


2
これは、私が今まで見た中で最も
gliく

1
@evilsoup正直なところ、これはシェルスクリプトにとってエレガントです。複雑であると主張するのは公平ではありません。
マックスハウエル

8
@MaxHowell男。いいえfor f in ./*.png; do convert "$f" "${f%.*}.jpg"; done。これはエレガントなバージョンです。それは完全に不要な回避lsgrepおよびsed呼び出しを(そしてecho、しかし、組み込みbashのだとそう/いいえ非常に少ないパフォーマンスへの影響を持つことになりますIIRC)、および2本のパイプと2つのサブシェルを取り除く、およびより少ない入力を必要とします。のすべてのバージョンlsが安全に解析できるわけではないため、わずかにポータブルです。
evilsoup

@evilsoup修正済みです!よくやった。
マックスハウエル

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で動作します。他のシェルについては知りませんが、唯一の違いはループ構文です。


1

これは、ファイルが複数のディレクトリにまたがるときに変換するために使用するものです。私のオリジナルはTGAからPNGでした

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

コンセプトはあなたfindが必要なファイルであり、拡張子を取り除き、でそれを再び追加することxargsです。したがって、PNGからJPGの場合、拡張子を変更し、アルファチャネルに対処するためにもう1つ、つまり背景を設定し(この例では白ですが、変更できます)、画像を平坦化します。

find . -name "*.png" -type f | sed 's/\.png$//' | xargs -I% convert %.png -background white -flatten  %.jpg
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.