Batch mengkonversi PNG ke JPG di linux

163

Adakah yang tahu cara yang baik untuk mengonversi sekelompok PNG menjadi JPG di linux? (Saya menggunakan Ubuntu).

Biner png2jpg yang bisa saya masukkan ke shell script akan ideal.

nedned
sumber

Jawaban:

237

Taruhan terbaik Anda adalah menggunakan Imagemagick

Saya bukan ahli dalam penggunaan aktual, tetapi saya tahu Anda bisa melakukan banyak hal terkait gambar ini!

Contohnya adalah:

convert image.png image.jpg

dan itu akan menjaga yang asli serta membuat gambar yang dikonversi. Adapun batch. Saya pikir Anda perlu menggunakan alat Mogrify (dari baris perintah yang sama ketika di imagemagick). Perlu diingat bahwa ini menimpa gambar lama.

Perintahnya adalah:

mogrify -format jpg *.png  
William Hilsum
sumber
7
Luar biasa, itulah yang saya cari dan akan digunakan kembali. By the way, hanya untuk mengklarifikasi karena saya tidak menyadari ini yang Anda maksud: convert digunakan untuk menghasilkan file output terpisah, mogrify digunakan untuk memodifikasi gambar asli.
nedned
1
gambar png dengan latar belakang transparan tidak dikonversi dengan benar ke jpg.
vishnu
4
Untuk mengonversi PNG dengan latar belakang transparan, gunakan perintah berikut:mogrify -format jpg -background black -flatten *.png
hyperknot
3
@KevinCox pada kotak linux saya setelah mogrify -format jpeg img.pngsaya memiliki 2 file dan file img.*melaporkan satu png, yang asli tidak tersentuh, dan yang baru jpeg. Jadi mogrifytidak tidak menimpa file asli dalam kasus ini.
neurino
4
Dari mogrifydokumentasi: " Alat ini serupa dengan convertkecuali bahwa file gambar asli ditimpa (kecuali Anda mengubah akhiran file dengan opsi -format ) dengan perubahan apa pun yang Anda minta. "
janko-m
82

Saya punya beberapa solusi lagi.

Solusi paling sederhana adalah seperti kebanyakan sudah diposting. Bash sederhana untuk loop.

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

Untuk beberapa alasan saya cenderung menghindari loop di bash jadi di sini adalah pendekatan xargs yang lebih unixy, menggunakan bash untuk nama-mangling.

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

Yang saya gunakan. Ini menggunakan GNU Parallel untuk menjalankan banyak pekerjaan sekaligus, memberi Anda peningkatan kinerja. Ini diinstal secara default pada banyak sistem dan hampir pasti di repo Anda (ini adalah program yang bagus untuk dimiliki).

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

Jumlah pekerjaan default ke jumlah proses yang Anda miliki. Saya menemukan penggunaan CPU yang lebih baik menggunakan 3 pekerjaan pada sistem dual-core saya.

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

Dan jika Anda menginginkan beberapa statistik (ETA, pekerjaan selesai, waktu rata-rata per pekerjaan ...)

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

Ada juga sintaks alternatif jika Anda menggunakan GNU Parallel.

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

Dan sintaksis yang serupa untuk beberapa versi lain (termasuk debian).

parallel convert '{}' '{.}.jpg' -- *.png
Kevin Cox
sumber
2
+1 untuk ekspansi string bash yang benar di dalam, jika saya bisa memberi Anda upvote lain untuk menyebutkan paralel, saya akan melakukannya. Ada satu kesalahan ketik, namun - Anda perlu donedi akhir untuk loop. Juga, untuk hal-hal paralel, Anda bisa menghindari menggunakan itu lsdan pipa dengan konstruk seperti: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png(lihat di sini )
evilsoup
Memperbaiki kesalahan ketik. Itu adalah sintaks keren yang tidak saya ketahui. Saya tidak tahu yang mana yang saya sukai lebih baik untuk alasan yang mungkin sama saya memilih untuk tidak menggunakan loop di bash. Saya meletakkannya solusinya karena mungkin cara yang lebih "tepat" tetapi saya mungkin akan tetap dengan lsmetode untuk diri saya sendiri karena lebih masuk akal bagi saya.
Kevin Cox
1
... walaupun perlu dicatat bahwa sintaks hanya berfungsi pada GNU parallel. Paralel yang dipaketkan dalam beberapa distro linux (seperti Debian & Ubuntu) sebenarnya adalah versi yang berbeda dengan sintaks yang sedikit berbeda (gunakan --daripada :::) - dan bahkan kemudian, secara frustasi tidak memiliki beberapa fitur paralel GNU.
evilsoup
(meskipun mereka yang berada di distro yang tidak mengemas GNU paralel dapat menginstalnya dari sumber dengan cukup mudah, menggunakan instruksi di sini )
evilsoup
Saya pikir saya harus mengubahnya saat itu sehingga berfungsi dengan versi sebanyak mungkin.
Kevin Cox
26

The convertperintah yang ditemukan pada banyak distribusi Linux diinstal sebagai bagian dari ImageMagick suite. Inilah kode bash untuk dijalankan convertpada semua file PNG dalam direktori dan hindari masalah ekstensi ganda:

for img in *.png; do
    filename=${img%.*}
    convert "$filename.png" "$filename.jpg"
done
Marcin
sumber
8
Menurut halaman manual untuk konversi: "Program konversi adalah anggota dari rangkaian alat ImageMagick (1)."
nedned
1
Anda benar. Untuk beberapa alasan saya pikir itu adalah bagian dari perpustakaan yang berbeda. Either way kode saya diposting di atas adalah cara yang benar untuk mengotomatisasi konversi batch dalam direktori.
Marcin
2
Anda dapat menggunakan ekspansi bash untuk meningkatkan perintah itu seperti:for f in *.png; do convert "$f" "${f/%png/jpg}"; done
evilsoup
hanya ingat itu sensitif huruf. nama kamera saya sebagai * .JPG dan tidak menyadari hal ini pada contoh pertama.
Tsenapathy
10

tl; dr

Bagi mereka yang hanya menginginkan perintah paling sederhana:

Konversi dan simpan file asli:

mogrify -format jpg *.png

Konversi dan hapus file asli:

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

Penjelasan Konversi Gelombang Dijelaskan

Agak terlambat ke pesta, tetapi hanya untuk menjernihkan semua kebingungan bagi seseorang yang mungkin tidak terlalu nyaman dengan cli, berikut ini adalah referensi dan penjelasan yang sangat bodoh.

Direktori Contoh

bar.png
foo.png
foobar.jpg

Konversi sederhana

Menyimpan semua file png asli serta membuat file jpg.

mogrify -format jpg *.png

Hasil

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

Penjelasan

  • mogrify adalah bagian dari rangkaian alat ImageMagick untuk pemrosesan gambar.
    • mogrify memproses gambar di tempat , artinya file asli ditimpa, dengan pengecualian -formatopsi. (Dari situs : This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option))
  • The - formatpilihan menentukan bahwa Anda akan mengubah format, dan argumen berikutnya perlu jenis (dalam hal ini, jpg).
  • Terakhir, *.pngadalah file input (semua file berakhiran .png).

Konversi dan Hapus

Mengonversi semua file png ke jpg, menghapus yang asli.

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

Hasil

bar.jpg
foo.jpg
foobar.jpg

Penjelasan

  • Bagian pertama sama persis seperti di atas, itu akan membuat file jpg baru.
  • The &&adalah operator boolean. Pendeknya:
    • Ketika sebuah program berakhir, ia mengembalikan status keluar. Status 0berarti tidak ada kesalahan.
    • Sejak &&melakukan evaluasi hubung singkat , bagian kanan hanya akan dilakukan jika tidak ada kesalahan . Ini berguna karena Anda mungkin tidak ingin menghapus semua file asli jika ada kesalahan mengonversi mereka.
  • The rmperintah menghapus file.

Barang Mewah

Sekarang inilah beberapa barang untuk orang-orang yang yang nyaman dengan cli tersebut.

Jika Anda ingin output saat mengonversi file:

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

Konversikan semua file png di semua subdirektori dan berikan output untuk masing-masingnya:

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

Konversikan semua file png di semua subdirektori, masukkan semua jpg yang dihasilkan ke dalam alldirektori , beri nomor, hapus file png asli, dan tampilkan output untuk setiap file saat terjadi:

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
sumber
Mungkin jawaban terbaik asalkan Anda menyingkirkan while readbagian tersebut (ganti atau hapus semuanya) ...
don_crissti
@don_crissti, ada apa dengan saat membaca?
Steven Jeffries
Ini rawan kesalahan (kecuali jika Anda 100% yakin Anda berurusan dengan nama file yang waras) dan lambat (seperti di sangat, sangat, sangat lambat).
don_crissti
Apa kualitas JPG default, dan bagaimana cara cap waktu file dipertahankan?
Dan Dascalescu
@DanDascalescu Metode di atas (kecuali yang terakhir) akan mempertahankan nama file, tetapi ganti ekstensi mereka, jadi file yang dicentang waktu harusnya baik-baik saja (selalu buat salinan dan uji dulu). Menurut ImageMagick, "Defaultnya adalah menggunakan estimasi kualitas gambar input Anda jika dapat ditentukan, jika tidak, 92" ( imagemagick.org/script/command-line-options.php#quality ) Kualitas dapat ditentukan dengan -kualitas <nomor> di mana <nomor> adalah 1 hingga 100.
Steven Jeffries
8

Sebenarnya " png2jpg" perintah Anda cari adalah pada kenyataannya dibagi menjadi dua perintah yang disebut pngtopnmdan cjpeg, dan mereka adalah bagian dari netpbmdan libjpeg-progspaket, masing-masing.

png2pnm foo.png | cjpeg > foo.jpeg
Teddy
sumber
6
find . -name "*.png" -print0 | xargs -0 mogrify -format jpg -quality 50
emdog4
sumber
1
Terima kasih atas solusi one-line direktori mendalam / rekursif yang meninggalkan *.jpgfile yang dihasilkan di sebelah file asli *.png, menunjukkan cara mengurangi ukuran / kualitas file dan tidak pecah karena ada karakter aneh dalam direktori atau nama file.
Joel Purra
5

solusi cepat saya for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done

maks
sumber
2
Ini harus menjadi salah satu dari baris perintah yang paling jelek dan paling berbelit-belit yang pernah saya lihat
evilsoup
1
@ evilsoup jujur, ini elegan untuk skrip shell. Mengklaim itu berbelit-belit tidak adil.
Max Howell
8
@MaxHowell man. No Berikut akan menjadi versi elegan ini: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done. Itu menghindari yang benar-benar tidak perlu ls, grepdan sedpanggilan (dan echo, tapi IIRC itu adalah bash builtin dan karenanya tidak akan memiliki / sangat sedikit dampak kinerja), dan menghilangkan dua pipa dan dua subkulit, dan melibatkan kurang mengetik. Ini bahkan sedikit lebih portabel, karena tidak semua versi lsaman untuk diuraikan.
evilsoup
@ evilsoup Saya berdiri dikoreksi! Kerja bagus.
Max Howell
4

Bertahun-tahun terlambat, ada utilitas png2jpeg khusus untuk tujuan ini, yang saya tulis.

Mengadaptasi kode oleh @Marcin:

#!/bin/sh

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

Untuk pemrosesan batch:

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

Anda akan berakhir dengan nama file seperti image1.png.jpg.

Ini akan bekerja di bash, dan mungkin bourne. Saya tidak tahu tentang shell lain, tetapi satu-satunya perbedaan adalah sintaks loop.

Jeffrey Aylesworth
sumber
1

Ini yang saya gunakan untuk mengonversi ketika file menjangkau lebih dari satu direktori. Yang asli saya adalah TGA ke PNG

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

Konsepnya adalah Anda findfile yang Anda butuhkan, menanggalkan ekstensi lalu menambahkannya kembali xargs. Jadi untuk PNG ke JPG, Anda akan mengubah ekstensi dan melakukan satu hal tambahan untuk menangani saluran alfa yaitu mengatur latar belakang (dalam contoh ini putih, tetapi Anda dapat mengubahnya) kemudian ratakan gambar

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