Câu hỏi Chuyển đổi hàng loạt PNG sang JPG trong linux


Có ai biết một cách tốt để chuyển đổi hàng loạt một bó PNG vào JPG trong linux? (Tôi đang sử dụng Ubuntu).

Một png2jpg nhị phân mà tôi chỉ có thể thả vào một kịch bản shell sẽ là lý tưởng.


141
2017-11-16 02:06


gốc




Các câu trả lời:


Đặt cược tốt nhất của bạn sẽ là sử dụng Imagemagick

Tôi không phải là một chuyên gia trong việc sử dụng thực tế, nhưng tôi biết bạn có thể làm khá nhiều bất cứ điều gì liên quan đến hình ảnh này!

Một ví dụ là:

convert image.png image.jpg

và nó sẽ giữ nguyên bản gốc cũng như tạo hình ảnh được chuyển đổi. Đối với hàng loạt. Tôi nghĩ rằng bạn cần phải sử dụng công cụ Mogrify (từ cùng một dòng lệnh khi trong imagemagick). Hãy nhớ rằng điều này ghi đè những hình ảnh cũ.

Lệnh này là:

mogrify -format jpg *.png  

210
2017-11-16 02:15



Tuyệt vời, đó là chính xác những gì tôi đã sau và sẽ được sử dụng một lần nữa. Bằng cách này, chỉ cần làm rõ như tôi đã không nhận ra điều này là những gì bạn có nghĩa là: chuyển đổi được sử dụng để tạo ra một tập tin đầu ra riêng biệt, mogrify được sử dụng để sửa đổi hình ảnh ban đầu. - nedned
hình ảnh png với nền trong suốt không chuyển đổi đúng sang jpg. - vishnu
Để chuyển đổi PNG với nền trong suốt, sử dụng lệnh sau: mogrify -format jpg -background black -flatten *.png - hyperknot
@KevinCox trên hộp linux của tôi sau mogrify -format jpeg img.png Tôi có 2 tệp và file img.* báo cáo một png, bản gốc bị ảnh hưởng, và một jpeg mới. Vì thế mogrify làm không phải ghi đè lên các tệp gốc trong trường hợp này. - neurino
Từ mogrify tài liệu: "Công cụ này tương tự convert ngoại trừ tệp hình ảnh gốc bị ghi đè (trừ khi bạn thay đổi hậu tố tệp bằng -định dạng tùy chọn) với bất kỳ thay đổi nào bạn yêu cầu." - janko-m


Tôi có một vài giải pháp nữa.

Giải pháp đơn giản nhất giống như hầu hết đã được đăng. Một bash đơn giản cho vòng lặp.

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

Đối với một số lý do tôi có xu hướng tránh các vòng trong bash vì vậy đây là một cách tiếp cận xargs unixy hơn, sử dụng bash cho tên mangling.

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

Cái tôi dùng. Nó sử dụng GNU Parallel để chạy nhiều công việc cùng một lúc, giúp bạn tăng hiệu suất. Nó được cài đặt theo mặc định trên nhiều hệ thống và gần như chắc chắn trong repo của bạn (nó là một chương trình tốt để có xung quanh).

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

Số lượng công việc mặc định là số lượng quy trình bạn có. Tôi tìm thấy sử dụng CPU tốt hơn bằng cách sử dụng 3 công việc trên hệ thống lõi kép của tôi.

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

Và nếu bạn muốn một số số liệu thống kê (một ETA, công việc đã hoàn thành, thời gian trung bình cho mỗi công việc ...)

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

Ngoài ra còn có một cú pháp thay thế nếu bạn đang sử dụng GNU Parallel.

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

Và một cú pháp tương tự cho một số phiên bản khác (bao gồm cả debian).

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

67
2018-01-28 02:45



1 cho mở rộng chuỗi bash chính xác trong for, nếu tôi có thể cung cấp cho bạn một upvote cho đề cập đến song song, tôi sẽ. Tuy nhiên, có một lỗi chính tả - bạn cần done vào cuối vòng lặp đó. Ngoài ra, đối với nội dung song song, bạn có thể tránh sử dụng ls và ống với một cấu trúc như: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png (xem đây) - evilsoup
Sửa lỗi đánh máy. Đó là một cú pháp tuyệt vời mà tôi không biết. Tôi không biết cái nào tôi thích hơn vì có lẽ lý do tôi không thích sử dụng vòng lặp trong bash. Tôi đặt nó là giải pháp bởi vì nó có lẽ là cách "thích hợp" hơn nhưng tôi có lẽ sẽ gắn bó với ls phương pháp cho bản thân mình bởi vì nó có ý nghĩa hơn với tôi. - Kevin Cox
... mặc dù cần lưu ý rằng cú pháp đó chỉ hoạt động trên GNU song song. Song song được đóng gói trong một số bản phân phối Linux (như Debian & Ubuntu) thực sự là một phiên bản khác với cú pháp hơi khác (sử dụng -- thay vì :::) - và thậm chí sau đó, nó bực bội thiếu một số tính năng của GNU song song. - evilsoup
(mặc dù những người trên bản phân phối không gói GNU song song có thể cài đặt nó từ nguồn khá dễ dàng, bằng cách sử dụng các hướng dẫn đây) - evilsoup
Tôi nghĩ rằng tôi nên thay đổi nó trở lại sau đó để nó hoạt động với nhiều phiên bản nhất có thể. - Kevin Cox


Các convert lệnh tìm thấy trên nhiều bản phân phối Linux được cài đặt như một phần của bộ ImageMagick. Đây là mã bash để chạy convert trên tất cả các tệp PNG trong một thư mục và tránh vấn đề mở rộng đôi đó:

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

25
2017-11-16 03:28



Theo trang hướng dẫn chuyển đổi: "Chương trình chuyển đổi là thành viên của bộ công cụ ImageMagick (1)." - nedned
Bạn nói đúng. Vì lý do nào đó, tôi nghĩ nó là một phần của một thư viện khác. Dù bằng cách nào, mã tôi đăng ở trên là cách chính xác để tự động chuyển đổi hàng loạt trong một thư mục. - Marcin
Bạn có thể sử dụng bash mở rộng để cải thiện lệnh đó như: for f in *.png; do convert "$f" "${f/%png/jpg}"; done - evilsoup
chỉ cần nhớ nó là trường hợp nhạy cảm. máy ảnh của tôi đặt tên nó là * .JPG và không nhận ra điều này trong trường hợp đầu tiên. - tsenapathy


Thực tế "png2jpg"lệnh bạn đang tìm kiếm trong thực tế được chia thành hai lệnh gọi là pngtopnm và cjpegvà chúng là một phần của netpbm và libjpeg-progs gói, tương ứng.

png2pnm foo.png | cjpeg > foo.jpeg

7
2017-11-16 05:29





tl; dr

Đối với những người chỉ muốn các lệnh đơn giản nhất:

Đổi và giữ tệp gốc:

mogrify -format jpg *.png

Đổi và tẩy tệp gốc:

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

Giải thích chuyển đổi hàng loạt

Kinda muộn cho bữa tiệc, nhưng chỉ để làm sáng tỏ tất cả sự nhầm lẫn cho một người có thể không được rất thoải mái với cli, đây là một tham chiếu siêu dumbed xuống và giải thích.

Thư mục mẫu

bar.png
foo.png
foobar.jpg

Chuyển đổi đơn giản

Giữ tất cả các tệp png gốc cũng như tạo tệp jpg.

mogrify -format jpg *.png

Kết quả

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

Giải trình

  • mogrify Là một phần của ImageMagick bộ công cụ để xử lý hình ảnh.
    • quá trình mogrify hình ảnh tại chỗ, nghĩa là tệp gốc bị ghi đè, ngoại trừ -format Tùy chọn. (Từ trang web: This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option))
  • Các - format tùy chọn chỉ định rằng bạn sẽ thay đổi định dạng và đối số tiếp theo cần phải là loại (trong trường hợp này là jpg).
  • Cuối cùng, *.png là các tệp đầu vào (tất cả các tệp kết thúc bằng .png).

Chuyển đổi và xóa

Chuyển đổi tất cả các tệp png thành jpg, loại bỏ tệp gốc.

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

Kết quả

bar.jpg
foo.jpg
foobar.jpg

Giải trình

  • Phần đầu tiên là chính xác như trên, nó sẽ tạo ra các tập tin jpg mới.
  • Các && là toán tử boolean. Nói ngắn gọn:
    • Khi một chương trình chấm dứt, nó sẽ trả về trạng thái thoát. Trạng thái của 0 có nghĩa là không có lỗi.
    • && thực hiện đánh giá ngắn mạch, phần bên phải sẽ chỉ được thực hiện nếu không có lỗi. Điều này rất hữu ích vì bạn có thể không muốn xóa tất cả các tệp gốc nếu có lỗi khi chuyển đổi chúng.
  • Các rm lệnh xóa tệp.

Nội dung Ưa thích

Bây giờ đây là một số goodies cho những người  thoải mái với cli.

Nếu bạn muốn một số đầu ra trong khi nó chuyển đổi tập tin:

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

Chuyển đổi tất cả các tệp png trong tất cả các thư mục con và cung cấp đầu ra cho mỗi thư mục:

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

Chuyển đổi tất cả các tệp png trong tất cả các thư mục con, đặt tất cả các kết quả jpg vào all thư mục, đánh số chúng, xóa các tệp png gốc và hiển thị đầu ra cho mỗi tệp khi nó diễn ra:

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



Có lẽ câu trả lời tốt nhất đã cho bạn thoát khỏi while read một phần (thay thế hoặc loại bỏ tất cả lại với nhau) ... - don_crissti
@don_crissti, có gì sai khi đọc? - Steven Jeffries
Đó là lỗi dễ xảy ra (trừ khi bạn chắc chắn 100% bạn đang xử lý với tên tập tin sane) và chậm (như trong rất, rất, rất chậm). - don_crissti
Chất lượng JPG mặc định là gì và làm cách nào để lưu giữ dấu thời gian tệp? - Dan Dascalescu
@DanDascalescu Các phương pháp trên (ngoại trừ cái cuối cùng) sẽ giữ lại tên tập tin, nhưng thay thế phần mở rộng của chúng, vì vậy các tập tin được định thời gian sẽ không sao (luôn luôn sao chép và kiểm tra trước). Theo ImageMagick, "Mặc định là sử dụng chất lượng ước tính của hình ảnh đầu vào của bạn nếu nó có thể được xác định, nếu không thì 92" (imagemagick.org/script/command-line-options.php#quality) Chất lượng có thể được xác định bằng -quality <number> trong đó <number> là từ 1 đến 100. - Steven Jeffries


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

4
2017-10-13 17:12



Cảm ơn bạn đã cung cấp giải pháp một dòng / đệ quy sâu để thoát khỏi kết quả *.jpg tệp bên cạnh tệp gốc *.png tập tin, cho thấy làm thế nào để giảm kích thước tập tin / chất lượng và không phá vỡ vì bất kỳ ký tự lẻ trong thư mục hoặc tên tập tin. - Joel Purra


giải pháp nhanh chóng của tôi for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done


3
2018-05-07 12:42



Điều này đã trở thành một trong những dòng lệnh xấu nhất, phức tạp nhất mà tôi từng thấy - evilsoup
@evilsoup một cách trung thực, điều này là thanh lịch cho các kịch bản shell. Tuyên bố nó là phức tạp không công bằng. - Max Howell
@MaxHowell người đàn ông. Không. Đây sẽ là một phiên bản thanh lịch của điều này: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done. Điều đó tránh hoàn toàn không cần thiết ls, grep và sed cuộc gọi (và echo, nhưng IIRC đó là một bản xây dựng bash và vì vậy sẽ không có / rất ít tác động hiệu suất), và loại bỏ hai đường ống và hai vỏ sò, và liên quan đến việc nhập ít hơn. Nó thậm chí còn di động hơn một chút, vì không phải tất cả các phiên bản ls an toàn để phân tích cú pháp. - evilsoup
@evilsoup Tôi đứng sửa chữa! Làm tốt lắm. - Max Howell


Để xử lý hàng loạt:

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

Bạn sẽ kết thúc với tên tập tin như image1.png.jpg mặc dù.

Điều này sẽ làm việc trong bash, và có thể bourne. Tôi không biết về các shell khác, nhưng sự khác biệt duy nhất có thể là cú pháp vòng lặp.


2
2017-11-16 02:28





Nhiều năm quá muộn, có một png2jpeg tiện ích đặc biệt cho mục đích này, mà tôi đã viết.

Điều chỉnh mã bằng @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