รุ่นที่แปลง PNG เป็น JPG ใน linux


163

ไม่มีใครรู้วิธีที่ดีในการแปลงชุด PNGs เป็น JPGs ใน linux (ฉันใช้ Ubuntu)

ไบนารี png2jpg ที่ฉันสามารถวางลงในเชลล์สคริปต์จะเหมาะ

คำตอบ:


237

ทางออกที่ดีที่สุดของคุณคือใช้Imagemagick

ฉันไม่ใช่ผู้เชี่ยวชาญในการใช้งานจริง แต่ฉันรู้ว่าคุณสามารถทำรูปภาพเกี่ยวกับสิ่งนี้ได้!

ตัวอย่างคือ:

convert image.png image.jpg

และมันจะเก็บต้นฉบับไว้เช่นเดียวกับการสร้างภาพที่ถูกแปลง สำหรับชุด ฉันคิดว่าคุณต้องใช้เครื่องมือ Mogrify (จากบรรทัดคำสั่งเดียวกันเมื่ออยู่ใน imagemagick) โปรดทราบว่าสิ่งนี้จะเขียนทับภาพเก่า

คำสั่งคือ:

mogrify -format jpg *.png  

7
ยอดเยี่ยมนั่นคือสิ่งที่ฉันเป็นหลังจากนั้นและจะใช้อีกครั้ง โดยวิธีการเพียงชี้แจงที่ฉันไม่ได้รู้ว่านี่คือสิ่งที่คุณหมายถึง: แปลงใช้ในการสร้างไฟล์ออกแยกต่างหาก mogrify ใช้ในการปรับเปลี่ยนภาพต้นฉบับ
nedned

1
รูปภาพ png ที่มีพื้นหลังโปร่งใสไม่สามารถแปลงเป็น jpg ได้อย่างเหมาะสม
vishnu

4
ในการแปลง PNG ด้วยพื้นหลังโปร่งใสให้ใช้คำสั่งต่อไปนี้:mogrify -format jpg -background black -flatten *.png
hyperknot

3
@KevinCox บนกล่อง linux ของฉันหลังจากที่mogrify -format jpeg img.pngฉันมี 2 ไฟล์และfile img.*รายงานหนึ่ง png, ไม่มีใครแตะต้องต้นฉบับและ jpeg ใหม่ ดังนั้นmogrifyไม่ได้เขียนทับไฟล์เดิมในกรณีนี้
neurino

4
จากmogrifyเอกสาร " เครื่องมือนี้จะคล้ายกับconvertยกเว้นว่าไฟล์ภาพต้นฉบับจะถูกเขียนทับ (เว้นแต่คุณจะเปลี่ยนคำต่อท้ายไฟล์ที่มีการทำการฟอร์แมตตัวเลือก) มีการเปลี่ยนแปลงใด ๆ ที่คุณขอ. "
แจม

82

ฉันมีทางออกเพิ่มเติมสองสามข้อ

ทางออกที่ง่ายที่สุดเหมือนโพสต์ที่มีอยู่แล้วมากที่สุด ทุบตีง่ายสำหรับวง

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

ด้วยเหตุผลบางอย่างฉันมักจะหลีกเลี่ยงการวนซ้ำในการทุบตีดังนั้นนี่คือวิธี xargs unixy มากขึ้นโดยใช้ทุบตีสำหรับชื่อ mangling

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

คนที่ฉันใช้ มันใช้ GNU Parallel ในการเรียกใช้งานหลายงานพร้อมกันเพื่อเพิ่มประสิทธิภาพให้กับคุณ มันถูกติดตั้งโดยค่าเริ่มต้นในหลาย ๆ ระบบและเกือบจะแน่นอนใน repo ของคุณ (มันเป็นโปรแกรมที่ดีที่จะมีรอบ)

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

จำนวนงานเริ่มต้นที่จำนวนกระบวนการที่คุณมี ฉันพบการใช้ CPU ที่ดีขึ้นโดยใช้ 3 งานในระบบดูอัลคอร์ของฉัน

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

และถ้าคุณต้องการสถิติบางอย่าง (ETA งานเสร็จเวลาเฉลี่ยต่องาน ... )

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

นอกจากนี้ยังมีไวยากรณ์ทางเลือกถ้าคุณใช้ GNU Parallel

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

และไวยากรณ์ที่คล้ายกันสำหรับเวอร์ชันอื่น (รวมถึงเดเบียน)

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

2
+1 สำหรับการขยายสตริง bash ที่ถูกต้องในถ้าหากฉันสามารถให้ upvote อีกอันสำหรับการพูดถึงขนานฉันจะ อย่างไรก็ตามมีข้อผิดพลาดหนึ่งข้อ - คุณต้องมี a doneท้ายสุดของลูป นอกจากนี้สำหรับสิ่งขนานคุณสามารถหลีกเลี่ยงการใช้lsและท่อที่มีโครงสร้างเช่น: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png(ดูที่นี่ )
evilsoup

แก้ไขข้อผิดพลาด นั่นเป็นไวยากรณ์ที่ยอดเยี่ยมที่ฉันไม่รู้ ฉันไม่ทราบว่าฉันชอบสิ่งไหนดีกว่าด้วยเหตุผลเดียวกันฉันไม่ต้องการใช้ลูปในการทุบตี ฉันแก้ปัญหานี้เพราะอาจเป็นวิธีที่ "เหมาะสม" มากกว่า แต่ฉันอาจจะใช้lsวิธีการของตัวเองเพราะมันเหมาะสมกว่าสำหรับฉัน
Kevin Cox

1
... แม้ว่ามันควรจะสังเกตว่าไวยากรณ์นั้นใช้งานได้กับ GNU แบบขนานเท่านั้น ขนานที่บรรจุในลินุกซ์ distros (เช่น Debian & Ubuntu) เป็นรุ่นที่แตกต่างกับไวยากรณ์ที่แตกต่างกันเล็กน้อย (ใช้--มากกว่า:::) - และถึงกระนั้นมันก็ขาดคุณสมบัติบางอย่างของ GNU ขนาน
evilsoup

(แม้ว่าผู้ที่อยู่ใน distros ที่ไม่ได้ทำแพคเกจแบบขนาน GNU สามารถติดตั้งได้จากแหล่งที่มาค่อนข้างง่ายโดยใช้คำแนะนำที่นี่ )
evilsoup

ฉันคิดว่าฉันควรเปลี่ยนกลับไปเพื่อให้สามารถใช้งานได้กับหลาย ๆ เวอร์ชันมากที่สุด
Kevin Cox

26

convertคำสั่งที่พบบนลินุกซ์จำนวนมากถูกติดตั้งเป็นส่วนหนึ่งของชุด ImageMagick นี่คือรหัสทุบตีที่ใช้convertในไฟล์ PNG ทั้งหมดในไดเรกทอรีและหลีกเลี่ยงปัญหาส่วนขยายซ้ำ:

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

8
ตามหน้า man สำหรับการแปลง: "โปรแกรมแปลงเป็นสมาชิกของชุดเครื่องมือ ImageMagick (1)"
nedned

1
คุณถูก. ด้วยเหตุผลบางอย่างฉันคิดว่ามันเป็นส่วนหนึ่งของห้องสมุดที่แตกต่างกัน วิธีที่โค้ดที่ฉันโพสต์ด้านบนเป็นวิธีที่ถูกต้องในการแปลงแบตช์โดยอัตโนมัติภายในไดเรกทอรี
Marcin

2
คุณสามารถใช้การขยาย bash เพื่อปรับปรุงคำสั่งเช่น:for f in *.png; do convert "$f" "${f/%png/jpg}"; done
evilsoup

เพียงจำไว้ว่ามันเป็นกรณี ๆ ไป ชื่อกล้องของฉันมันเป็น * .JPG และไม่ได้ตระหนักถึงสิ่งนี้ในตอนแรก
tsenapathy

10

TL; DR

สำหรับผู้ที่ต้องการคำสั่งที่ง่ายที่สุด:

แปลงและเก็บไฟล์ต้นฉบับ:

mogrify -format jpg *.png

แปลงและลบไฟล์ต้นฉบับ:

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

อธิบายการแปลงเป็นแบทช์

สายไปงานเลี้ยง แต่เพียงเพื่อขจัดความสับสนทั้งหมดสำหรับคนที่อาจไม่สะดวกกับ cli นี่เป็นข้อมูลอ้างอิงและคำอธิบายที่โง่เขลาสุด ๆ

ตัวอย่างไดเรกทอรี

bar.png
foo.png
foobar.jpg

แปลงง่าย

เก็บไฟล์ png ดั้งเดิมทั้งหมดรวมทั้งสร้างไฟล์ jpg

mogrify -format jpg *.png

ผลลัพธ์

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

คำอธิบาย

  • mogrifyเป็นส่วนหนึ่งของชุดเครื่องมือImageMagickสำหรับการประมวลผลภาพ
    • mogrify ประมวลผลภาพในสถานที่หมายถึงไฟล์ต้นฉบับจะถูกเขียนทับด้วยข้อยกเว้นของ-formatตัวเลือก (จากเว็บไซต์ : This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option))
  • - formatตัวเลือกที่ระบุว่าคุณจะมีการเปลี่ยนแปลงรูปแบบและข้อโต้แย้งต่อไปจะต้องมีการพิมพ์ (ในกรณีนี้, jpg)
  • สุดท้าย*.pngคือไฟล์อินพุต (ไฟล์ทั้งหมดที่ลงท้ายด้วย. png)

แปลงและลบ

แปลงไฟล์ png ทั้งหมดเป็น jpg ลบต้นฉบับ

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

ผลลัพธ์

bar.jpg
foo.jpg
foobar.jpg

คำอธิบาย

  • ส่วนแรกเหมือนกันทุกประการมันจะสร้างไฟล์ jpg ใหม่
  • &&เป็นผู้ประกอบการบูลีน ในระยะสั้น:
    • เมื่อโปรแกรมหยุดทำงานโปรแกรมจะส่งคืนสถานะการออก สถานะ0หมายถึงไม่มีข้อผิดพลาด
    • ตั้งแต่&&ทำการประเมินการลัดวงจรส่วนที่เหมาะสมจะถูกดำเนินการก็ต่อเมื่อไม่มีข้อผิดพลาดเท่านั้น สิ่งนี้มีประโยชน์เพราะคุณอาจไม่ต้องการลบไฟล์ต้นฉบับทั้งหมดหากมีข้อผิดพลาดในการแปลงไฟล์
  • rmคำสั่งลบไฟล์

สิ่งแฟนซี

ตอนนี้ที่นี่สารพัดบางอย่างสำหรับคนที่มีความสะดวกสบายด้วย CLI

หากคุณต้องการเอาต์พุตบางอย่างในขณะที่กำลังแปลงไฟล์:

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

แปลงไฟล์ png ทั้งหมดในไดเรกทอรีย่อยทั้งหมดและให้เอาต์พุตสำหรับแต่ละไฟล์:

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

แปลงไฟล์ png ทั้งหมดในไดเรกทอรีย่อยทั้งหมดใส่ jpgs ที่เป็นผลลัพธ์ทั้งหมดลงในallไดเรกทอรีให้วางหมายเลขลบไฟล์ png ดั้งเดิมและแสดงผลลัพธ์สำหรับแต่ละไฟล์ตามที่เกิดขึ้น:

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

น่าจะเป็นคำตอบที่ดีที่สุดที่มีให้คุณได้รับการกำจัดwhile readส่วน (แทนที่มันหรือลบมันทั้งหมดเข้าด้วยกัน) ...
don_crissti

@don_crissti เกิดอะไรขึ้นขณะที่อ่าน
Steven Jeffries

เป็นข้อผิดพลาดได้ง่าย (เว้นแต่คุณจะแน่ใจ 100% ว่าคุณกำลังจัดการกับชื่อไฟล์ที่มีเหตุผล) และช้า (เช่นมากมากช้ามาก)
don_crissti

คุณภาพ JPG เริ่มต้นคืออะไรและจะเก็บรักษาบันทึกเวลาไว้ได้อย่างไร
Dan Dascalescu

@DanDascalescu วิธีการด้านบน (ยกเว้นอันสุดท้าย) จะเก็บชื่อไฟล์ไว้ แต่แทนที่ส่วนขยายดังนั้นไฟล์ที่ประทับเวลาควรจะโอเค (ทำสำเนาและทดสอบก่อนเสมอ) ตาม ImageMagick "ค่าเริ่มต้นคือการใช้คุณภาพโดยประมาณของภาพที่คุณป้อนหากสามารถกำหนดได้มิฉะนั้น 92" ( imagemagick.org/script/command-line-options.php#quality ) สามารถระบุคุณภาพด้วย -quality <number> โดยที่ <number> คือ 1 ถึง 100
Steven Jeffries

8

png2jpgคำสั่งจริง " " ที่คุณกำลังค้นหาอยู่ในความเป็นจริงแบ่งออกเป็นสองคำสั่งที่เรียกว่าpngtopnmและcjpegและเป็นส่วนหนึ่งของnetpbmและlibjpeg-progsแพ็คเกจตามลำดับ

png2pnm foo.png | cjpeg > foo.jpeg

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

1
ขอบคุณสำหรับโซลูชันหนึ่งบรรทัดที่มีไดเรกทอรีลึก / วนซ้ำซึ่งทิ้ง*.jpgไฟล์ผลลัพธ์ไว้ถัดจาก*.pngไฟล์ต้นฉบับแสดงวิธีลดขนาด / คุณภาพของไฟล์และไม่แตกเพราะอักขระแปลก ๆ ในไดเรกทอรีหรือชื่อไฟล์
Joel Purra

5

ทางออกที่รวดเร็วของฉัน for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done


2
นี้ได้จะต้องเป็นหนึ่งในที่น่าเกลียดที่สุดคำสั่งสายที่ซับซ้อนที่สุดเท่าที่ผมเคยเห็น
evilsoup

1
@evilsoup สุจริตนี่คือเชลล์สคริปต์ที่ยอดเยี่ยม การอ้างว่ามีความซับซ้อนไม่ยุติธรรม
Max Howell

8
@ MaxHowell คน for f in ./*.png; do convert "$f" "${f%.*}.jpg"; doneฉบับที่นี่จะเป็นรุ่นที่สง่างามของนี้: ที่หลีกเลี่ยงไม่จำเป็นครบถ้วนls, grepและsedการโทร (และechoแต่ IIRC ที่เป็น builtin ทุบตีและอื่น ๆ จะไม่มี / ผลกระทบต่อประสิทธิภาพน้อยมาก) และได้รับการกำจัดของทั้งสองท่อและสอง subshells, และเกี่ยวข้องกับการพิมพ์น้อย มันพกพาได้มากกว่าเดิมเล็กน้อยเนื่องจากไม่ใช่ทุกเวอร์ชั่นlsที่จะแยกวิเคราะห์ได้อย่างปลอดภัย
evilsoup

@evilsoup ฉันยืนแก้ไข! ทำได้ดีมาก
Max Howell

4

หลายปีสายเกินไปมียูทิลิตีpng2jpegสำหรับจุดประสงค์นี้โดยเฉพาะซึ่งฉันเขียน

การปรับรหัสโดย @Marcin:

#!/bin/sh

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

3

สำหรับการประมวลผลแบทช์:

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

คุณจะจบลงด้วยชื่อไฟล์เช่น image1.png.jpg

นี้จะทำงานในทุบตีและอาจ bourne ฉันไม่รู้เกี่ยวกับเชลล์ตัวอื่น แต่ความแตกต่างเพียงอย่างเดียวน่าจะเป็นไวยากรณ์ลูป


1

นี่คือสิ่งที่ฉันใช้ในการแปลงเมื่อไฟล์ครอบคลุมมากกว่าหนึ่งไดเรกทอรี อันแรกของฉันคือ TGA ถึง PNG

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

แนวคิดคือคุณไฟล์ที่คุณต้องการเปลื้องผ้านามสกุลแล้วเพิ่มกลับไปอยู่กับfind xargsดังนั้นสำหรับ PNG ถึง JPG คุณจะต้องเปลี่ยนนามสกุลและทำสิ่งพิเศษอย่างหนึ่งในการจัดการกับช่องอัลฟาคือการตั้งค่าพื้นหลัง (ในตัวอย่างนี้เป็นสีขาว แต่คุณสามารถเปลี่ยนได้) จากนั้นปรับภาพให้เรียบ

find . -name "*.png" -type f | sed 's/\.png$//' | xargs -I% convert %.png -background white -flatten  %.jpg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.