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


163

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

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

Câu trả lời:


237

Đặ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 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 ra hình ảnh được chuyển đổi. Đối với lô. Tôi nghĩ rằng bạn cần sử dụng công cụ Mogrify (từ cùng một dòng lệnh khi trong hình ảnh tưởng tượng). Hãy nhớ rằng điều này ghi đè lên những hình ảnh cũ.

Lệnh là:

mogrify -format jpg *.png  

7
Tuyệt vời, đó chính xác là những gì tôi đã và sẽ sử dụng lại. Nhân tiện, chỉ cần làm rõ khi tôi không nhận ra đây là ý của bạn: convert được sử dụng để tạo một tệp đầu ra riêng biệt, mogrify được sử dụng để sửa đổi ảnh gốc.
neded

1
hình ảnh png với nền trong suốt không chuyển đổi đúng sang jpg.
vishnu

4
Để chuyển đổi PNG với nền trong suốt, hãy sử dụng lệnh sau:mogrify -format jpg -background black -flatten *.png
hyperjack

3
@KevinCox trên hộp linux của tôi sau khi mogrify -format jpeg img.pngtôi có 2 tệp và file img.*báo cáo một png, bản gốc chưa được xử lý và một tệp jpeg mới. Vì vậy, mogrifykhông không ghi đè lên file gốc trong trường hợp này.
neurino

4
Từ mogrifytài liệu: " Công cụ này tương tự như convertngoại trừ tệp ảnh gốc bị ghi đè (trừ khi bạn thay đổi hậu tố tệp bằng tùy chọn -format ) với bất kỳ thay đổi nào bạn yêu cầu. "
janko-m

82

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

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

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

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 (đây 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 theo số lượng quy trình bạn có. Tôi thấy việc 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 mình.

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

Và nếu bạn muốn một số thống kê (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

2
+1 để 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 khác để đề cập song song, tôi sẽ làm vậy. Tuy nhiên, có một lỗi đánh máy - bạn cần một lỗi doneở cuối vòng lặp đó. Ngoài ra, đối với các công cụ song song, bạn có thể tránh sử dụng công cụ đó lsvà đường ống có cấu trúc như: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png(xem tại đây )
evilsoup

Sửa lỗi chính tả. Đó 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 có lẽ vì lý do tương tự tôi không thích sử dụng các vòng lặp trong bash. Tôi đặt nó là giải pháp bởi vì nó có thể là cách "phù hợp" hơn nhưng có lẽ tôi sẽ gắn bó với lsphương pháp này vì nó có ý nghĩa hơn đối với tôi.
Kevin Cox

1
... Mặc dù cần lưu ý rằng cú pháp đó chỉ hoạt động trên GNU song song. Bản 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 --chứ không phải :::) - 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 các bản phát hành không đóng gói song song GNU có thể cài đặt nó từ nguồn khá dễ dàng, sử dụng các hướng dẫn tại đây )
evilsoup

Tôi nghĩ rằng tôi nên thay đổi nó sau đó để nó hoạt động với càng nhiều phiên bản càng tốt.
Kevin Cox

26

Các convertlệ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ộ ứng dụng ImageMagick. Đây là mã bash để chạy converttrên tất cả các tệp PNG trong một thư mục và tránh vấn đề mở rộng kép đó:

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

8
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)."
neded

1
Bạn nói đúng. Vì một số lý do, tôi nghĩ rằng 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

2
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 là * .JPG và đã không nhận ra điều này trong trường hợp đầu tiên.
tsenapathy

10

tl; dr

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

Chuyển đổigiữ các tệp gốc:

mogrify -format jpg *.png

Chuyển đổixóa các tập tin gốc:

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

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

Có mặt muộn trong bữa tiệc, nhưng chỉ để giải tỏa tất cả sự nhầm lẫn cho một người có thể không thoải mái lắm với cli, đây là một tài liệu tham khảo và giải thích siêu ngớ ngẩn.

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 các 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 bộ công cụ ImageMagick để xử lý ảnh.
    • mogrify xử lý hình ảnh tại chỗ , có nghĩa là tệp gốc bị ghi đè, ngoại trừ -formattù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 - formattùy chọn xác định rằng bạn sẽ được thay đổi định dạng, và các số tiếp theo cần phải được loại (trong trường hợp này, jpg).
  • Cuối cùng, *.pnglà 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ỏ bản 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 giống hệt như trên, nó sẽ tạo các tệp jpg mới.
  • Đây &&là một toán tử boolean. Nói ngắn gọn:
    • Khi một chương trình kết thúc, nó sẽ trả về trạng thái thoát. Một trạng thái 0có 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 rmlệnh xóa file.

Fancy Stuff

Bây giờ đây là một số goodies cho những người đang cảm thấy 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 tệp:

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 jpg kết quả vào allthư 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

Có lẽ câu trả lời tốt nhất miễn là bạn thoát khỏi while readphần đó (thay thế hoặc xóa tất cả cùng nhau) ...
don_crissti

@don_crissti, có gì sai trong khi đọc?
Steven Jeffries

Đó là lỗi dễ xảy ra (trừ khi bạn chắc chắn 100% rằng bạn đang xử lý tên tệp lành mạnh) và chậm (như rất, rất, rất chậm).
don_crissti

Chất lượng JPG mặc định là gì và làm thế nào để giữ dấu thời gian của tệp?
Dan Dascalescu

@DanDascalescu Các phương thức trên (ngoại trừ phương pháp cuối cùng) sẽ giữ nguyên tên tệp, nhưng thay thế phần mở rộng của chúng, vì vậy các tệp được đánh dấu thời gian sẽ ổn (luôn tạo bản sao 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 có thể xác định được, nếu không thì 92" ( fantemagick.org/script/command-line-options.php#quality ) Chất lượng có thể được chỉ định với -quality <number> trong đó <number> là 1 đến 100.
Steven Jeffries

8

Lệnh "" thực tế png2jpgmà bạn đang tìm kiếm trong thực tế được chia thành hai lệnh được gọi pngtopnmcjpeg, và chúng là một phần của gói netpbmlibjpeg-progstương ứng.

png2pnm foo.png | cjpeg > foo.jpeg

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

1
Cảm ơn về giải pháp một dòng thư mục sâu / đệ quy để lại các *.jpgtệp kết quả bên cạnh các *.pngtệp gốc , cho thấy cách giảm kích thước / chất lượng tệp và không bị hỏng do có bất kỳ ký tự lẻ nào trong thư mục hoặc tên tệp.
Joel Purra

5

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


2
Đây phải là một trong những dòng lệnh xấu xí nhất, phức tạp nhất mà tôi từng thấy
evilsoup

1
@evilsoup thành thật mà nói, đây là thanh lịch cho shell script. Yêu cầu bồi thường là không công bằng.
Max Howell

8
@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. Đó tránh được hoàn toàn không cần thiết ls, grepsedcác cuộc gọi (và echo, nhưng IIRC đó là một bash BUILTIN và như vậy sẽ không có / rất ít tác động hiệu suất), và được thoát khỏi hai ống và hai subshells, bao gồm ít gõ. Nó thậm chí còn dễ mang theo hơn một chút, vì không phải tất cả các phiên bản lsđều an toàn để phân tích.
evilsoup

@evilsoup Tôi đứng sửa! Làm tốt lắm.
Max Howell

4

Nhiều năm đã quá muộn, có một tiện ích png2jpeg dành riêng cho mục đích này, mà tôi là tác giả.

Điều chỉnh mã bởi @Marcin:

#!/bin/sh

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

3

Để 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 như image1.png.jpg.

Đ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.


1

Đây là những gì tôi sử dụng để chuyển đổi khi các tệp trải rộng trên một thư mục. Bản gốc của tôi là TGA to PNG

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

Khái niệm này là findcác tệp bạn cần, loại bỏ phần mở rộng sau đó thêm lại vào xargs. Vì vậy, đối với PNG sang JPG, bạn sẽ thay đổi các tiện ích mở rộng và thực hiện thêm một điều nữa để xử lý các kênh alpha cụ thể là đặt nền (trong ví dụ này là màu trắng, nhưng bạn có thể thay đổi nó) sau đó làm phẳng hình ảnh

find . -name "*.png" -type f | sed 's/\.png$//' | xargs -I% convert %.png -background white -flatten  %.jpg
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.