Pregunta Convertir lotes de PNG a JPG en Linux


¿Alguien sabe una buena manera de convertir por lotes un montón de PNG en JPG en Linux? (Estoy usando Ubuntu).

Un binario png2jpg que podría colocar en un script de shell sería ideal.


141


origen




Respuestas:


Tu mejor opción sería usar Imagemagick

No soy un experto en el uso real, pero sé que puedes hacer cualquier cosa relacionada con esto.

Un ejemplo es:

convert image.png image.jpg

y mantendrá el original así como también la creación de la imagen convertida. En cuanto a lote Creo que debes usar la herramienta Mogrify (desde la misma línea de comando cuando está en imagemagick). Tenga en cuenta que esto sobrescribe las viejas imágenes

El comando es:

mogrify -format jpg *.png  

210



Impresionante, eso es exactamente lo que estaba buscando y lo volveré a utilizar. Por cierto, solo para aclarar, ya que no me di cuenta de que esto es lo que quería decir: convertir se utiliza para generar un archivo de salida por separado, mogrify se utiliza para modificar la imagen original. - nedned
Las imágenes png con fondo transparente no se convierten correctamente a jpg. - vishnu
Para convertir PNG con fondo transparente, use el siguiente comando: mogrify -format jpg -background black -flatten *.png - hyperknot
@KevinCox en mi linux box después mogrify -format jpeg img.png Tengo 2 archivos y file img.* informa una png, la original intacta y una nueva jpeg. Asi que mogrify hace no sobrescribir los archivos originales en este caso. - neurino
De mogrify documentación: "Esta herramienta es similar a convert excepto que el archivo de imagen original se sobrescribe (a menos que cambie el sufijo del archivo con -formato opción) con cualquier cambio que solicite." - janko-m


Tengo un par de soluciones más.

La solución más simple es como la mayoría ya publicada. Un simple golpe para el bucle.

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

Por alguna razón, tiendo a evitar los bucles en bash, así que aquí hay un enfoque de xargs más unixy, usando bash para la manipulación de nombres.

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

El que uso Utiliza GNU Parallel para ejecutar múltiples trabajos a la vez, dándole un aumento de rendimiento. Se instala por defecto en muchos sistemas y está casi definitivamente en su repositorio (es un buen programa para tener).

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

El número de trabajos predeterminado es la cantidad de procesos que tiene. Encontré un mejor uso de la CPU usando 3 trabajos en mi sistema dual-core.

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

Y si quieres algunas estadísticas (una ETA, trabajos completados, tiempo promedio por trabajo ...)

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

También hay una sintaxis alternativa si está utilizando GNU Parallel.

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

Y una sintaxis similar para algunas otras versiones (incluido Debian).

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

67



+1 para la correcta expansión de la cadena de bash en el, si pudiera darle otro voto alternativo para mencionar el paralelismo, lo haría. Sin embargo, hay un error tipográfico: necesitas un done al final de ese ciclo for. Además, para las cosas paralelas, puedes evitar usar eso ls y pipa con una construcción como: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png (ver aquí) - evilsoup
Corregido error tipográfico. Esa es una sintaxis genial que no sabía. No sé cuál me gusta más, probablemente por la misma razón por la que prefiero no usar loops en bash. Puse la solución porque probablemente sea la manera más "adecuada", pero probablemente me quedo con la ls método para mí porque tiene más sentido para mí. - Kevin Cox
... aunque debe tenerse en cuenta que esa sintaxis solo funciona en paralelo GNU. El paralelo que está empaquetado en algunas distribuciones de Linux (como Debian y Ubuntu) es en realidad una versión diferente con una sintaxis ligeramente diferente (uso -- más bien que :::) - e incluso entonces, frustrantemente carece de algunas de las características de GNU paralelas. - evilsoup
(aunque aquellos en las distribuciones que no empaquetan GNU en paralelo pueden instalarlo desde la fuente con bastante facilidad, usando las instrucciones aquí) - evilsoup
Creo que debería cambiarlo en ese momento para que funcione con tantas versiones como sea posible. - Kevin Cox


los convert El comando encontrado en muchas distribuciones de Linux se instala como parte del conjunto de aplicaciones de ImageMagick. Aquí está el código bash para ejecutar convert en todos los archivos PNG en un directorio y evitar ese problema de doble extensión:

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

25



De acuerdo con la página man para convert: "El programa convert es un miembro del paquete de herramientas ImageMagick (1)". - nedned
Estás en lo correcto. Por alguna razón, pensé que era parte de una biblioteca diferente. De cualquier forma, el código que publiqué anteriormente es la forma correcta de automatizar la conversión por lotes dentro de un directorio. - Marcin
Puedes usar la expansión bash para mejorar ese comando como: for f in *.png; do convert "$f" "${f/%png/jpg}"; done - evilsoup
solo recuerda que es sensible a mayúsculas y minúsculas. mi cámara lo nombra como * .JPG y no se dio cuenta de esto en primera instancia. - tsenapathy


El actual "png2jpg"El comando que estás buscando en realidad está dividido en dos comandos llamados pngtopnm y cjpeg, y son parte de la netpbm y libjpeg-progs paquetes, respectivamente.

png2pnm foo.png | cjpeg > foo.jpeg

7





tl; dr

Para aquellos que solo quieren los comandos más simples:

Convertir y mantener archivos originales:

mogrify -format jpg *.png

Convertir y retirar archivos originales:

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

Conversión por lotes explicada

Un poco tarde para la fiesta, pero solo para aclarar toda la confusión de alguien que puede no estar muy cómodo con cli, aquí hay una referencia y una explicación súper simplificadas.

Directorio de ejemplos

bar.png
foo.png
foobar.jpg

Conversión simple

Mantiene todos los archivos originales png y crea archivos jpg.

mogrify -format jpg *.png

Resultado

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

Explicación

  • mogrificar es parte del ImageMagick conjunto de herramientas para el procesamiento de imágenes.
    • mogrify procesa imágenes en su lugar, lo que significa que el archivo original se sobrescribe, con la excepción de -format opción. (De el sitio: This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option))
  • los - format opción especifica que va a cambiar el formato, y el siguiente argumento debe ser del tipo (en este caso, jpg).
  • Finalmente, *.png son los archivos de entrada (todos los archivos terminan en .png).

Convertir y eliminar

Convierte todos los archivos png a jpg, elimina el original.

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

Resultado

bar.jpg
foo.jpg
foobar.jpg

Explicación

  • La primera parte es exactamente la misma que la anterior, creará nuevos archivos jpg.
  • los && es un operador booleano. En breve:
    • Cuando un programa termina, devuelve un estado de salida. Un estado de 0 significa que no hay errores.
    • Ya que && realiza evaluación de cortocircuito, la parte correcta solo se realizará si no hubo errores. Esto es útil porque es posible que no desee eliminar todos los archivos originales si hubo un error al convertirlos.
  • los rm comando borra archivos.

Cosas lujosas

Ahora aquí hay algunos regalos para las personas que son cómodo con el cli.

Si quieres algo de salida mientras está convirtiendo archivos:

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

Convierta todos los archivos png en todos los subdirectorios y dé salida para cada uno:

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

Convierta todos los archivos png en todos los subdirectorios, coloque todos los jpgs resultantes en el all directorio, numerarlos, eliminar archivos png originales y mostrar el resultado de cada archivo a medida que se lleva a cabo:

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



Probablemente la mejor respuesta siempre que te deshagas de la while read parte (sustitúyalo o quítelo todo junto) ... - don_crissti
@don_crissti, ¿qué pasa con la lectura? - Steven Jeffries
Es propenso a errores (a menos que esté 100% seguro de que está tratando con nombres de archivos sanos) y lento (como en muy, muy, muy lento). - don_crissti
¿Cuál es la calidad JPG predeterminada y cómo se pueden preservar las marcas de tiempo de los archivos? - Dan Dascalescu
@DanDascalescu Los métodos anteriores (excepto el último) conservarán los nombres de los archivos, pero reemplazarán su extensión, por lo que los archivos con fecha de vencimiento deberían estar bien (siempre haga una copia y pruebe primero). Según ImageMagick, "el valor predeterminado es usar la calidad estimada de su imagen de entrada si se puede determinar, de lo contrario 92" (imagemagick.org/script/command-line-options.php#quality) La calidad se puede especificar con -quality <number> donde <number> es de 1 a 100. - Steven Jeffries


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

4



Gracias por una solución de directorio profunda / recursiva de una sola línea que deja el resultado *.jpg archivos al lado del original *.png archivos, muestra cómo reducir el tamaño / calidad del archivo y no se rompe debido a caracteres extraños en el directorio o nombre de archivo. - Joel Purra


mi solución rápida for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done


3



Esta tiene que ser una de las líneas de comando más feas y complicadas que he visto en mi vida - evilsoup
@evilsoup honestamente, esto es elegante para los scripts de shell. Afirmar que es intrincado no es justo. - Max Howell
@MaxHowell hombre. No. Aquí estaría una versión elegante de esto: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done. Eso evita lo completamente innecesario ls, grep y sed llamadas (y echo, pero IIRC es una falla interna y no tendrá / muy poco impacto en el rendimiento), y se deshace de dos tubos y dos subcapas, y implica menos tipeo. Es incluso un poco más portátil, ya que no todas las versiones de ls son seguros de analizar. - evilsoup
@evilsoup ¡Estoy corregido! Buen trabajo. - Max Howell