Conversion par lots de PNG en JPG sous Linux

163

Est-ce que quelqu'un connaît un bon moyen de convertir par lots un groupe de PNG en JPG sous Linux? (J'utilise Ubuntu).

Un fichier binaire png2jpg que je pourrais simplement insérer dans un script shell serait idéal.

nedned
la source

Réponses:

237

Votre meilleur pari serait d'utiliser Imagemagick

Je ne suis pas un expert dans l'utilisation réelle, mais je sais que vous pouvez pratiquement faire n'importe quelle image liée à cela!

Un exemple est:

convert image.png image.jpg

et il conservera l'original et créera l'image convertie. Quant au lot. Je pense que vous devez utiliser l'outil Mogrify (à partir de la même ligne de commande lorsque vous êtes dans imagemagick). Gardez à l'esprit que cela écrase les anciennes images.

La commande est:

mogrify -format jpg *.png  
William Hilsum
la source
7
Génial, c'est exactement ce que je recherchais et utiliserai encore. A propos, juste pour clarifier car je n'avais pas réalisé que c'était ce que vous vouliez dire: convert est utilisé pour générer un fichier de sortie séparé, mogrify est utilisé pour modifier l'image d'origine.
1
Les images png avec un arrière-plan transparent ne sont pas converties correctement en jpg.
Vishnu
4
Pour convertir les mogrify -format jpg -background black -flatten *.png
fichiers
3
@KevinCox sur ma machine Linux après mogrify -format jpeg img.pngavoir 2 fichiers et file img.*rapporte un png, l’original intact, et un nouveau jpeg. Donc, mogrifyne pas écraser les fichiers originaux dans ce cas.
Neurino
4
D'après la mogrifydocumentation: " Cet outil est similaire à l' convertexception du fait que le fichier image d'origine est écrasé (à moins que vous ne changiez le suffixe du fichier avec l' option -format ) avec les modifications que vous demandez. "
janko-m
82

J'ai deux autres solutions.

La solution la plus simple est comme la plupart déjà postée. Une simple bash pour la boucle.

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

Pour une raison quelconque, j'ai tendance à éviter les boucles dans bash, voici donc une approche plus unixy xargs, utilisant bash pour nommer.

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

Celui que j'utilise. Il utilise GNU Parallel pour exécuter plusieurs tâches à la fois, ce qui vous donne un coup de fouet pour les performances. Il est installé par défaut sur de nombreux systèmes et figure presque certainement dans votre dépôt (c’est un bon programme).

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

Le nombre de tâches par défaut correspond au nombre de processus que vous avez. J'ai trouvé une meilleure utilisation du processeur en utilisant 3 tâches sur mon système dual-core.

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

Et si vous voulez des statistiques (ETA, travaux terminés, temps moyen par travail ...)

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

Il existe également une syntaxe alternative si vous utilisez GNU Parallel.

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

Et une syntaxe similaire pour certaines autres versions (y compris debian).

parallel convert '{}' '{.}.jpg' -- *.png
Kevin Cox
la source
2
+1 pour le développement correct de la chaîne bash dans le for, si je pouvais vous donner un autre vote positif pour avoir mentionné parallèle, je le ferais. Il y a cependant une faute de frappe - vous avez besoin d'un doneà la fin de cette boucle for. Aussi, pour les choses parallèles, vous pourriez éviter d'utiliser ça lset pipe avec une construction comme: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png(voir ici )
evilsoup
Correction d'une faute de frappe. C'est une syntaxe intéressante que je ne connaissais pas. Je ne sais pas lequel me plaît le mieux, probablement pour la même raison que je préfère ne pas utiliser de boucles en bash. Je lui ai proposé la solution parce que c'est probablement la lsméthode la plus «appropriée», mais je vais probablement m'en tenir à la méthode car elle me semble plus logique.
Kevin Cox
1
... bien qu'il faille noter que cette syntaxe ne fonctionne que sur GNU parallèle. Le parallèle inclus dans certaines distributions Linux (comme Debian et Ubuntu) est en fait une version différente avec une syntaxe légèrement différente (utiliser --plutôt que :::) - et même dans ce cas, certaines des fonctionnalités de GNU parallel manquent de manière frustrante.
Evilsoup
(Bien que ceux sur les distributions qui n'emballent pas GNU parallèle puissent l'installer à partir du source, en utilisant les instructions ici )
evilsoup
Je pense que je devrais le changer à l'époque pour qu'il fonctionne avec autant de versions que possible.
Kevin Cox
26

La convertcommande trouvée sur de nombreuses distributions Linux est installée dans le cadre de la suite ImageMagick. Voici le code bash à exécuter convertsur tous les fichiers PNG d'un répertoire et évitez ce problème de double extension:

for img in *.png; do
    filename=${img%.*}
    convert "$filename.png" "$filename.jpg"
done
Marcin
la source
8
Selon la page de manuel relative à convert: "Le programme convert est membre de la suite d'outils ImageMagick (1)".
Noté
1
Vous avez raison. Pour une raison quelconque, j'ai pensé que cela faisait partie d'une bibliothèque différente. De toute façon, le code que j'ai posté ci-dessus est la bonne façon d'automatiser la conversion par lots dans un répertoire.
Marcin
2
Vous pouvez utiliser bash expansion pour améliorer cette commande, par exemple:for f in *.png; do convert "$f" "${f/%png/jpg}"; done
evilsoup
Rappelez-vous qu'il est sensible à la casse. mon appareil photo le nomme * .JPG et ne l’a pas compris en premier lieu.
Tsenapathy
10

tl; dr

Pour ceux qui veulent juste les commandes les plus simples:

Convertir et conserver les fichiers originaux:

mogrify -format jpg *.png

Convertir et supprimer les fichiers d'origine:

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

La conversion par lots expliquée

Un peu tard pour le parti, mais pour dissiper toute la confusion qui règne pour quelqu'un qui n'est peut-être pas très à l'aise avec Cli, voici une référence et des explications parfaitement simplifiées.

Exemple de répertoire

bar.png
foo.png
foobar.jpg

Conversion simple

Conserve tous les fichiers png originaux et crée des fichiers jpg.

mogrify -format jpg *.png

Résultat

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

Explication

  • Mogrify fait partie de la suite d’images ImageMagick pour le traitement des images.
    • Mogrify traite les images en place , ce qui signifie que le fichier d'origine est écrasé, à l'exception de l' -formatoption. ( A partir du site : This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option))
  • L' - formatoption spécifie que vous allez changer le format, et le prochain argument doit être le type (dans ce cas, jpg).
  • Enfin, *.pngsont les fichiers d'entrée (tous les fichiers se terminant par .png).

Convertir et supprimer

Convertit tous les fichiers png en jpg, supprime l'original.

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

Résultat

bar.jpg
foo.jpg
foobar.jpg

Explication

  • La première partie est exactement la même que ci-dessus, elle créera de nouveaux fichiers jpg.
  • Le &&est un opérateur booléen. En bref:
    • Lorsqu'un programme se termine, il retourne un statut de sortie. Un statut 0signifie aucune erreur.
    • Étant donné qu’il &&effectue une évaluation de court-circuit , la partie droite ne sera exécutée que s’il n’ya pas eu d’erreurs . Cela est utile car vous ne souhaitez peut-être pas supprimer tous les fichiers d'origine en cas d'erreur de conversion.
  • La rmcommande supprime les fichiers.

Trucs de fantaisie

Maintenant, voici quelques goodies pour les personnes qui sont à l' aise avec la Cli.

Si vous voulez une sortie pendant la conversion des fichiers:

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

Convertissez tous les fichiers png de tous les sous-répertoires et donnez le résultat pour chacun d’entre eux:

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

Convertissez tous les fichiers png de tous les sous-répertoires, mettez tous les fichiers jpgs résultants dans le allrépertoire, numérotez-les, supprimez les fichiers png d'origine et affichez la sortie de chaque fichier au fur et à mesure de son déroulement :

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
la source
Probablement la meilleure réponse à condition de vous débarrasser de la while readpièce (la remplacer ou la supprimer en
entier
@don_crissti, qu'est-ce qui ne va pas pendant la lecture?
Steven Jeffries
Il est sujet aux erreurs (sauf si vous êtes sûr à 100% que vous avez affaire à des noms de fichiers sains) et lent (comme dans très, très, très lent).
don_crissti
Quelle est la qualité JPG par défaut et comment conserver les horodatages de fichiers?
Dan Dascalescu
@DanDascalescu Les méthodes ci-dessus (à l'exception de la dernière) conservent les noms de fichiers, mais remplacent leur extension, afin que les fichiers horodatés soient corrects (faites toujours une copie et testez d'abord). Selon ImageMagick, "La valeur par défaut consiste à utiliser la qualité estimée de votre image d'entrée si elle peut être déterminée, sinon 92" ( imagemagick.org/script/command-line-options.php#quality ). La qualité peut être spécifiée avec -quality <numéro> où <nombre> est compris entre 1 et 100.
Steven Jeffries
8

La " png2jpg" commande que vous recherchez est en réalité divisée en deux commandes appelées pngtopnmand cjpeg, et elles font partie des packages netpbmet libjpeg-progs, respectivement.

png2pnm foo.png | cjpeg > foo.jpeg
Nounours
la source
6
find . -name "*.png" -print0 | xargs -0 mogrify -format jpg -quality 50
emdog4
la source
1
Merci pour cette solution monoligne à répertoire profond / récursif qui laisse les *.jpgfichiers résultants à côté des *.pngfichiers originaux , montre comment réduire la taille / qualité du fichier et ne craquera pas à cause de caractères bizarres dans le répertoire ou le nom de fichier.
Joel Purra
5

ma solution rapide for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done

max
la source
2
Cela doit être l'une des lignes de commande les plus laides et les plus compliquées que j'ai jamais vues
evilsoup
1
@ evilsoup honnêtement, c'est élégant pour les scripts shell. Affirmer que c'est compliqué n'est pas juste.
Max Howell
8
@ MaxHowell man. Non serait ici une version élégante de ceci: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done. Cela évite tout à fait inutile ls, grepet les sedappels (et echo, mais l'IIRC est une bash construit et n'aura donc pas / très peu d'impact sur les performances), et supprime deux canaux et deux sous-coques, et implique moins de dactylographie. Il est même légèrement plus portable, car toutes les versions de ne lssont pas analysables en toute sécurité.
Evilsoup
@evilsoup je suis corrigé! Bon travail.
Max Howell
4

De nombreuses années trop tard, il existe un utilitaire png2jpeg spécialement conçu à cet effet, dont je suis l'auteur.

Adapter le code par @Marcin:

#!/bin/sh

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

Pour le traitement par lots:

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

Vous vous retrouverez avec des noms de fichiers comme image1.png.jpg.

Cela fonctionnera à bash et peut-être même. Je ne connais pas les autres shells, mais la seule différence serait probablement la syntaxe de la boucle.

Jeffrey Aylesworth
la source
1

C’est ce que j’utilise pour convertir lorsque les fichiers couvrent plusieurs répertoires. Mon original était TGA to PNG

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

Le concept est que vous avez findles fichiers dont vous avez besoin, supprimez l’extension, puis rajoutez-la xargs. Donc, pour les fichiers PNG en JPG, vous devez modifier les extensions et faire une chose supplémentaire pour traiter les canaux alpha, à savoir régler le fond (dans cet exemple, le blanc, mais vous pouvez le changer), puis aplatir l'image.

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