Stapelkonvertierung von PNG in JPG unter Linux

163

Kennt jemand eine gute Möglichkeit, eine Reihe von PNGs in JPGs unter Linux zu konvertieren? (Ich benutze Ubuntu).

Eine png2jpg-Binärdatei, die ich einfach in ein Shell-Skript einfügen könnte, wäre ideal.

nedned
quelle

Antworten:

237

Am besten verwenden Sie Imagemagick

Ich bin kein Experte in der tatsächlichen Verwendung, aber ich weiß, dass Sie so ziemlich alles tun können, was mit diesem Bild zusammenhängt!

Ein Beispiel ist:

convert image.png image.jpg

Das Original bleibt erhalten und das konvertierte Bild wird erstellt. Wie für charge. Ich denke, Sie müssen das Mogrify-Tool verwenden (von der gleichen Befehlszeile aus, wenn Sie in imagemagick sind). Beachten Sie, dass dadurch die alten Bilder überschrieben werden.

Der Befehl lautet:

mogrify -format jpg *.png  
William Hilsum
quelle
7
Genial, genau das habe ich gesucht und werde es wieder verwenden. Übrigens, nur um zu verdeutlichen, dass ich nicht realisiert habe, was Sie damit gemeint haben: convert wird verwendet, um eine separate Ausgabedatei zu generieren, mogrify wird verwendet, um das Originalbild zu modifizieren.
16.
1
PNG-Bilder mit transparentem Hintergrund werden nicht ordnungsgemäß in JPG konvertiert.
Vishnu
4
Verwenden Sie den folgenden Befehl, um mogrify -format jpg -background black -flatten *.png
PNGs
3
@ KevinCox auf meiner Linux-Box, nachdem mogrify -format jpeg img.pngich 2 Dateien und file img.*einen PNG-Bericht, das Original unberührt und einen neuen JPEG-Bericht habe . So mogrifywird nicht überschrieben Originaldateien in diesem Fall.
Neurino
4
Aus der mogrifyDokumentation: „ Dieses Tool ist ähnlich zu , convertdass die Original - Bilddatei ist , außer überschrieben (es sei denn , Sie die Dateiendungen mit dem ändern -Format mit allen Änderungen fordern Sie Option).
janko-m
82

Ich habe noch ein paar Lösungen.

Die einfachste Lösung ist wie die meisten bereits gebucht. Ein einfacher Bash for Loop.

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

Aus irgendeinem Grund neige ich dazu, Schleifen in bash zu vermeiden, daher hier ein unixigerer xargs-Ansatz, bei dem bash für die Namensverknüpfung verwendet wird.

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

Den ich benutze. Es verwendet GNU Parallel, um mehrere Jobs gleichzeitig auszuführen und so die Leistung zu steigern. Es wird standardmäßig auf vielen Systemen installiert und ist fast definitiv in Ihrem Repo (es ist ein gutes Programm, um herum zu haben).

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

Die Anzahl der Jobs richtet sich standardmäßig nach der Anzahl der von Ihnen ausgeführten Prozesse. Ich habe mit 3 Jobs auf meinem Dual-Core-System eine bessere CPU-Auslastung gefunden.

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

Und wenn Sie eine Statistik wünschen (eine ETA, abgeschlossene Jobs, durchschnittliche Zeit pro Job ...)

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

Es gibt auch eine alternative Syntax, wenn Sie GNU Parallel verwenden.

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

Und eine ähnliche Syntax für einige andere Versionen (einschließlich Debian).

parallel convert '{}' '{.}.jpg' -- *.png
Kevin Cox
quelle
2
+1 für die korrekte Erweiterung der Bash-Zeichenfolge in der for, wenn ich Ihnen eine weitere Aufwertung für die Erwähnung von parallel geben könnte, würde ich. Es gibt jedoch einen Tippfehler - Sie benötigen doneam Ende eine for-Schleife. Auch für die parallelen Sachen könnten Sie vermeiden, das zu verwenden lsund mit einem Konstrukt wie Pipe parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png(siehe hier )
Evilsoup
Tippfehler behoben. Das ist eine coole Syntax, die ich nicht kannte. Ich weiß nicht, welches ich aus dem gleichen Grund besser mag, aus dem ich es bevorzuge, keine Loops in bash zu verwenden. Ich nehme die Lösung, weil es wahrscheinlich der "richtige" Weg ist, aber ich bleibe wahrscheinlich bei der lsMethode für mich, weil sie für mich sinnvoller ist.
Kevin Cox
1
... obwohl zu beachten ist, dass diese Syntax nur unter GNU parallel funktioniert. Die Parallele, die in einigen Linux-Distributionen (wie Debian & Ubuntu) enthalten ist, ist tatsächlich eine andere Version mit einer etwas anderen Syntax (verwenden --statt :::) - und selbst dann fehlen frustrierend einige der Funktionen von GNU parallel.
Übelsuppe
(obwohl diejenigen auf Distributionen, die GNU nicht parallel packen, es ganz einfach von der Quelle installieren können, indem sie die Anweisungen hier
befolgen
Ich denke, ich sollte es damals ändern, damit es mit so vielen Versionen wie möglich funktioniert.
Kevin Cox
26

Der convertBefehl, der auf vielen Linux-Distributionen zu finden ist, wird als Teil der ImageMagick-Suite installiert. Hier ist der Bash-Code, der convertfür alle PNG-Dateien in einem Verzeichnis ausgeführt wird und das Problem der doppelten Erweiterung vermeidet:

for img in *.png; do
    filename=${img%.*}
    convert "$filename.png" "$filename.jpg"
done
Marcin
quelle
8
Laut der Manpage für convert: "Das convert-Programm ist ein Mitglied der ImageMagick (1) -Toolsuite."
16.
1
Du hast Recht. Aus irgendeinem Grund dachte ich, es sei Teil einer anderen Bibliothek. In beiden Fällen ist der oben angegebene Code der richtige Weg, um die Stapelkonvertierung in einem Verzeichnis zu automatisieren.
Marcin
2
Sie können die Bash-Erweiterung verwenden, um diesen Befehl zu verbessern:for f in *.png; do convert "$f" "${f/%png/jpg}"; done
Evilsoup
Denken Sie daran, es ist case sensitive. Meine Kamera nannte es * .JPG und bemerkte dies zunächst nicht.
Tsenapathy
10

tl; dr

Für diejenigen, die nur die einfachsten Befehle wollen:

Konvertieren und behalten Sie Originaldateien:

mogrify -format jpg *.png

Ursprüngliche Dateien konvertieren und entfernen :

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

Batch-Konvertierung erklärt

Ein bisschen zu spät zur Party, aber nur, um die Verwirrung für jemanden zu beseitigen, der sich mit Cli nicht besonders wohl fühlt, hier ist eine super verworrene Referenz und Erklärung.

Beispielverzeichnis

bar.png
foo.png
foobar.jpg

Einfach umwandeln

Behält alle ursprünglichen PNG-Dateien bei und erstellt JPG-Dateien.

mogrify -format jpg *.png

Ergebnis

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

Erläuterung

  • mogrify ist Teil der ImageMagick- Tool- Suite für die Bildverarbeitung.
    • mogrify verarbeitet Bilder an Ort und Stelle , was bedeutet, dass die Originaldatei mit Ausnahme der -formatOption überschrieben wird . (Von der Website : This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option))
  • Die - formatOption gibt an, dass Sie das Format ändern, und das nächste Argument muss der Typ sein (in diesem Fall jpg).
  • Zuletzt *.pngdie Eingabedateien (alle Dateien, die mit .png enden).

Konvertieren und entfernen

Konvertiert alle PNG-Dateien in JPG, entfernt das Original.

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

Ergebnis

bar.jpg
foo.jpg
foobar.jpg

Erläuterung

  • Der erste Teil ist genau der gleiche wie oben, es werden neue JPG-Dateien erstellt.
  • Das &&ist ein Boolescher Operator. Zusamenfassend:
    • Wenn ein Programm beendet wird, gibt es einen Beendigungsstatus zurück. Ein Status von 0bedeutet keine Fehler.
    • Da &&die Kurzschlussbewertung durchgeführt wird , wird der richtige Teil nur ausgeführt, wenn keine Fehler aufgetreten sind . Dies ist nützlich, da Sie möglicherweise nicht alle Originaldateien löschen möchten, wenn beim Konvertieren ein Fehler aufgetreten ist.
  • Der rmBefehl löscht Dateien.

Schickes Zeug

Hier sind einige Goodies für die Leute, die sich mit dem Cli wohl fühlen.

Wenn Sie beim Konvertieren von Dateien eine Ausgabe wünschen:

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

Konvertieren Sie alle PNG-Dateien in alle Unterverzeichnisse und geben Sie für jedes eine Ausgabe aus:

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

Konvertieren Sie alle PNG-Dateien in allen Unterverzeichnissen, legen Sie alle resultierenden JPGs in das allVerzeichnis, nummerieren Sie sie, entfernen Sie die ursprünglichen PNG-Dateien und zeigen Sie die Ausgabe für jede Datei an, während sie stattfindet:

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
Steven Jeffries
quelle
Wahrscheinlich die beste Antwort, sofern Sie das while readTeil loswerden (ersetzen Sie es oder entfernen Sie alles zusammen) ...
don_crissti
@don_crissti, was stimmt nicht beim lesen?
Steven Jeffries
Es ist fehleranfällig (es sei denn, Sie sind sich zu 100% sicher, dass Sie es mit vernünftigen Dateinamen zu tun haben) und langsam (wie in sehr, sehr, sehr langsam).
don_crissti
Was ist die Standard-JPG-Qualität und wie können Dateizeitstempel beibehalten werden?
Dan Dascalescu
@DanDascalescu Bei den oben beschriebenen Methoden (mit Ausnahme der letzten) werden die Dateinamen beibehalten, aber die Dateierweiterungen werden ersetzt. Daher sollten Dateien mit Zeitstempel in Ordnung sein (immer eine Kopie erstellen und zuerst testen). Laut ImageMagick ist "Standardmäßig wird die geschätzte Qualität Ihres Eingabebildes verwendet, wenn sie ermittelt werden kann, andernfalls 92" ( imagemagick.org/script/command-line-options.php#quality ). Die Qualität kann mit -quality angegeben werden <number> wobei <number> 1 bis 100 ist.
Steven Jeffries
8

Die eigentliche „ png2jpg“ Befehl Sie suchen , ist in Wirklichkeit spaltete sich in zwei Befehle genannt pngtopnmund cjpeg, und sie sind ein Teil der netpbmund libjpeg-progsPakete sind.

png2pnm foo.png | cjpeg > foo.jpeg
Teddy
quelle
6
find . -name "*.png" -print0 | xargs -0 mogrify -format jpg -quality 50
emdog4
quelle
1
Vielen Dank für eine einzeilige Lösung mit tiefem / rekursivem Verzeichnis, die die resultierenden *.jpgDateien neben den Originaldateien belässt *.png, zeigt, wie die Dateigröße / -qualität verringert werden kann und nicht aufgrund von ungeraden Zeichen im Verzeichnis oder Dateinamen unterbrochen wird.
Joel Purra
5

meine schnelle lösung for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done

max
quelle
2
Dies muss eine der hässlichsten und
kompliziertesten
1
@evilsoup ehrlich, das ist elegant für Shell-Skripte. Zu behaupten, es sei verwickelt, ist nicht fair.
Max Howell
8
@ MaxHowell Mann. Nein . Hier wäre eine elegante Version dieses: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done. Das vermeidet die völlig unnötig ls, grepund sedAnrufe (und echo, aber IIRC , dass ein heftiger Schlag ist gebautet und haben so keine / sehr wenig Auswirkungen auf die Leistung) und wird von zwei Leitungen und zwei Subshells los zu werden , und beinhaltet weniger tippen. Es ist sogar etwas portabler, da nicht alle Versionen von lssicher zu analysieren sind.
Übelsuppe
@evilsoup Ich stehe korrigiert! Gut gemacht.
Max Howell
4

Viele Jahre zu spät gibt es ein speziell für diesen Zweck entwickeltes Hilfsprogramm png2jpeg , das ich verfasst habe.

Anpassung des Codes durch @Marcin:

#!/bin/sh

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

Für die Stapelverarbeitung:

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

Sie erhalten jedoch Dateinamen wie image1.png.jpg.

Dies funktioniert in bash und vielleicht bourne. Ich kenne keine anderen Shells, aber der einzige Unterschied wäre wahrscheinlich die Schleifensyntax.

Jeffrey Aylesworth
quelle
1

Dies ist, was ich verwende, um zu konvertieren, wenn die Dateien mehr als ein Verzeichnis umfassen. Mein ursprüngliches war TGA zu PNG

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

Das Konzept ist, dass Sie finddie Dateien haben, die Sie benötigen. Entfernen Sie die Erweiterung und fügen Sie sie dann wieder hinzu xargs. Für PNG zu JPG ändern Sie also die Erweiterungen und tun eine zusätzliche Sache, um mit Alphakanälen umzugehen, nämlich den Hintergrund einzustellen (in diesem Beispiel weiß, aber Sie können ihn ändern) und dann das Bild zu reduzieren

find . -name "*.png" -type f | sed 's/\.png$//' | xargs -I% convert %.png -background white -flatten  %.jpg
Archimedes Trajano
quelle