Frage Batch-Konvertierung von PNG zu JPG in Linux


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

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


141
2017-11-16 02:06


Ursprung




Antworten:


Ihre beste Wette wäre zu verwenden Imagemagik

Ich bin kein Experte in der tatsächlichen Verwendung, aber ich weiß, dass Sie so ziemlich jedes Bild damit tun können!

Ein Beispiel ist:

convert image.png image.jpg

und es wird das Original beibehalten und das konvertierte Bild erstellen. Wie für die Partie. Ich denke, dass Sie das Mogrify-Werkzeug benutzen müssen (von der gleichen Befehlszeile, wenn Sie in imagemagick sind). Beachten Sie, dass dies überschreibt die alten Bilder.

Der Befehl lautet:

mogrify -format jpg *.png  

210
2017-11-16 02:15



Genial, genau das wollte ich und werde es wieder benutzen. By the way, nur um zu verdeutlichen, wie ich nicht wusste, dass das ist, was Sie meinten: convert wird verwendet, um eine separate Ausgabedatei zu generieren, wird Mogrify verwendet, um das Originalbild zu ändern. - nedned
PNG-Bilder mit transparentem Hintergrund werden nicht richtig in JPG konvertiert. - vishnu
Verwenden Sie den folgenden Befehl, um PNGs mit transparentem Hintergrund zu konvertieren: mogrify -format jpg -background black -flatten *.png - hyperknot
@KevinCox auf meiner Linux-Box nach mogrify -format jpeg img.png Ich habe 2 Dateien und file img.* berichtet ein PNG, das Original unberührt und ein neues JPEG. Damit mogrify tut nicht überschreiben Sie in diesem Fall die Originaldateien. - neurino
Von mogrify Dokumentation: "Dieses Werkzeug ist ähnlich convert außer dass die ursprüngliche Bilddatei überschrieben wird (es sei denn, Sie ändern das Dateisuffix mit dem -Format Option) mit allen von Ihnen gewünschten Änderungen." - janko-m


Ich habe ein paar mehr Lösungen.

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

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

Aus irgendeinem Grund tendiere ich dazu, Schleifen in bash zu vermeiden, also hier ist ein unixy xargs Ansatz, bash für die Namens-Mangling verwenden.

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

Der, den ich benutze. Es verwendet GNU Parallel, um mehrere Jobs gleichzeitig auszuführen, was zu einer Leistungssteigerung führt. Es ist standardmäßig auf vielen Systemen installiert und ist fast definitiv in Ihrem Repo (es ist ein gutes Programm, um zu haben).

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

Die Anzahl der Jobs entspricht standardmäßig der Anzahl der Prozesse, die Sie haben. Ich habe eine bessere CPU-Auslastung mit 3 Jobs auf meinem Dual-Core-System gefunden.

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

Und wenn Sie einige Statistiken 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

67
2018-01-28 02:45



+1 für die richtige Bash String Erweiterung in der, wenn ich Ihnen eine andere Upvote für die Erwähnung parallel geben könnte, würde ich. Es gibt jedoch einen Tippfehler - Sie brauchen einen done am Ende dieser for-Schleife. Für das parallele Zeug könntest du es auch vermeiden lsund Pipe mit einem Konstrukt wie: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png (sehen Hier) - evilsoup
Tippfehler behoben. Das ist eine coole Syntax, von der ich nichts wusste. Ich weiß nicht, welche mir besser gefällt, wahrscheinlich aus demselben Grund, warum ich lieber keine Loops in bash verwende. Ich stelle es die Lösung, weil es wahrscheinlich der "richtige" Weg ist, aber ich werde wahrscheinlich bei der bleiben ls Methode für mich selbst, weil es für mich mehr Sinn macht. - Kevin Cox
... obwohl es beachtet werden sollte, dass diese Syntax nur auf GNU parallel funktioniert. Die Parallele, die in einigen Linux-Distributionen enthalten ist (wie Debian und Ubuntu), ist eigentlich eine andere Version mit einer etwas anderen Syntax -- eher, als :::) - und selbst dann fehlen frustrierend einige der Eigenschaften von GNU parallel. - evilsoup
(obwohl diejenigen auf Distributionen, die GNU-Parallele nicht packen, sie mit der Anleitung recht einfach aus der Quelle installieren können Hier) - evilsoup
Ich denke, ich sollte es dann ändern, damit es mit so vielen Versionen wie möglich funktioniert. - Kevin Cox


Das convert Befehl, der auf vielen Linux-Distributionen gefunden wird, wird als Teil der ImageMagick-Suite installiert. Hier ist der Bash-Code zum Ausführen convert auf alle PNG-Dateien in einem Verzeichnis und vermeiden Sie das doppelte Erweiterungsproblem:

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

25
2017-11-16 03:28



Laut der man-Seite für konvertieren: "Das Konvertierungsprogramm ist ein Mitglied der ImageMagick (1) Suite von Tools." - nedned
Du hast Recht. Aus irgendeinem Grund dachte ich, es wäre Teil einer anderen Bibliothek. In jedem Fall ist der Code, den ich oben gepostet habe, der richtige Weg, die Stapelkonvertierung in einem Verzeichnis zu automatisieren. - Marcin
Sie können die bash-Erweiterung verwenden, um diesen Befehl wie folgt zu verbessern: for f in *.png; do convert "$f" "${f/%png/jpg}"; done - evilsoup
nur daran denken, es ist Groß-und Kleinschreibung. Meine Kamera nennt es als * .JPG und hat das in erster Instanz nicht erkannt. - tsenapathy


Das eigentliche "png2jpg"Befehl, nach dem Sie suchen, ist in Wirklichkeit in zwei Befehle aufgeteilt, genannt pngtopnm und cjpegund sie sind Teil der netpbm und libjpeg-progs Pakete jeweils.

png2pnm foo.png | cjpeg > foo.jpeg

7
2017-11-16 05:29





tl; dr

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

Konvertieren und behalten Originaldateien:

mogrify -format jpg *.png

Konvertieren und Löschen Originaldateien:

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

Batch-Konvertierung erklärt

Irgendwie zu spät zur Party, aber um all die Verwirrung für jemanden aufzuklären, der sich mit cli nicht sehr wohl fühlt, hier ist eine super verdummte Referenz und Erklärung.

Beispielverzeichnis

bar.png
foo.png
foobar.jpg

Einfache Konvertierung

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 von ImageMagick Suite von Werkzeugen für die Bildverarbeitung.
    • mogrify verarbeitet Bilder an Ort und Stelle, dh die ursprüngliche Datei wird überschrieben, mit Ausnahme von -format Möglichkeit. (Von der Standort: This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option))
  • Das - format Option gibt an, dass Sie das Format ändern werden, und das nächste Argument muss der Typ sein (in diesem Fall jpg).
  • Zuletzt, *.png sind die Eingabedateien (alle Dateien mit der Endung .png).

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 derselbe wie oben, es werden neue JPG-Dateien erstellt.
  • Das && ist ein boolescher Operator. Zusamenfassend:
    • Wenn ein Programm beendet wird, gibt es einen Exit-Status zurück. Ein Status von 0 bedeutet keine Fehler.
    • Schon seit && führt durch Kurzschlussauswertung, der rechte Teil wird nur ausgeführt, wenn Es gab keine Fehler. Dies ist nützlich, weil Sie möglicherweise nicht alle Originaldateien löschen möchten, wenn beim Konvertieren ein Fehler aufgetreten ist.
  • Das rm Befehl löscht Dateien.

Schickes Zeug

Hier sind einige Leckereien für die Leute, die sind gemütlich mit dem CLI.

Wenn Sie beim Konvertieren von Dateien etwas ausgeben möchten:

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

Konvertieren Sie alle PNG-Dateien in allen Unterverzeichnissen und geben Sie für jede eine Ausgabe ein:

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

Konvertiere alle PNG - Dateien in alle Unterverzeichnisse, lege alle resultierenden jpgs in die all Verzeichnis, nummerieren 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

6
2017-10-17 15:02



Wahrscheinlich die beste Antwort vorausgesetzt, dass Sie die while read Teil (ersetzen Sie es oder entfernen Sie alles zusammen) ... - don_crissti
@don_crissti, was ist falsch beim Lesen? - Steven Jeffries
Es ist fehleranfällig (es sei denn, Sie sind zu 100% sicher, dass es sich um vernünftige Dateinamen handelt) und langsam (wie in sehr, sehr, sehr langsam). - don_crissti
Wie lautet die Standard-JPG-Qualität und wie können Dateizeitstempel beibehalten werden? - Dan Dascalescu
@DanDascalescu Die oben genannten Methoden (mit Ausnahme der letzten) behalten Dateinamen bei, ersetzen aber ihre Erweiterung, sodass die Zeitstempel der Dateien in Ordnung sein sollten (immer eine Kopie erstellen und zuerst testen). Gemäß ImageMagick, "Die Standardeinstellung ist, die geschätzte Qualität Ihres Eingabebildes zu verwenden, wenn es bestimmt werden kann, andernfalls 92" (imagemagick.org/script/command-line-options.php#quality) Die Qualität kann mit -quality <Nummer> angegeben werden, wobei <Zahl> 1 bis 100 ist. - Steven Jeffries


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

4
2017-10-13 17:12



Danke für eine tiefgehende / rekursive Verzeichnis-Ein-Zeilen-Lösung, die das Ergebnis übrig lässt *.jpg Dateien neben dem Original *.png Dateien, zeigt, wie Dateigröße / Qualität reduziert werden kann und nicht wegen irgendwelcher ungeraden Zeichen im Verzeichnis- oder Dateinamen bricht. - Joel Purra


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


3
2018-05-07 12:42



Dies muss eine der hässlichsten und verworrensten Befehlszeilen sein, die ich je gesehen habe - evilsoup
@evilsoup ehrlich gesagt, das ist elegant für Shell-Skripte. Zu behaupten, es sei verschachtelt, ist nicht fair. - Max Howell
@MaxHowell Mann. Nein. Hier wäre eine elegante Version von diesem: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done. Das vermeidet das völlig unnötig ls, grep und sed Anrufe (und echo, aber IIRC, das ist ein Bash Built-in und so wird keine / sehr geringe Performance-Auswirkungen haben), und wird zwei Pfeifen und zwei Subhells loswerden, und beinhaltet weniger Tipparbeit. Es ist sogar etwas tragbarer, da nicht alle Versionen von ls sind sicher zu analysieren. - evilsoup
@evilsoup Ich stehe richtig! Gut gemacht. - Max Howell


Für die Stapelverarbeitung:

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

Sie werden jedoch mit Dateinamen wie image1.png.jpg enden.

Dies wird in Bash und vielleicht Bourne funktionieren. Ich weiß nichts über andere Shells, aber der einzige Unterschied wäre wahrscheinlich die Schleifensyntax.


2
2017-11-16 02:28





Viele Jahre zu spät, da ist ein png2jpeg Dienstprogramm speziell für diesen Zweck, den ich verfasst habe.

Anpassung des Codes an @Marcin:

#!/bin/sh

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

2
2017-10-22 09:37





Das ist es, was ich zum Konvertieren verwende, 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 bist du find die Dateien, die Sie benötigen, entfernen Sie die Erweiterung und fügen Sie sie dann wieder hinzu xargs. Also für PNG zu JPG, würden Sie die Erweiterungen ändern und eine zusätzliche Sache tun, um mit Alphakanälen umzugehen, nämlich den Hintergrund einzustellen (in diesem Beispiel weiß, aber Sie können es ändern) und dann das Bild abflachen

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

0
2017-09-17 02:34