Пакетне перетворення PNG в JPG в Linux


163

Хтось знає хороший спосіб пакетної конвертації купки PNG в JPG в Linux? (Я використовую Ubuntu).

Бінарний файл png2jpg, який я міг би просто потрапити в сценарій оболонки, був би ідеальним.

Відповіді:


237

Найкращим варіантом буде використання Imagemagick

Я не фахівець з фактичного використання, але я знаю, що ти можеш зробити майже все, що стосується цього!

Приклад:

convert image.png image.jpg

і він збереже оригінал, а також створить перетворене зображення. Що стосується партії. Я думаю, вам потрібно скористатися інструментом Mogrify (з того самого командного рядка, коли і в imagemagick). Майте на увазі, що це перезаписує старі зображення.

Команда така:

mogrify -format jpg *.png  

7
Чудово, це саме те, що я мав після, і буду використовувати знову. До речі, просто для уточнення, оскільки я не усвідомлював, що це ви мали на увазі: конвертування використовується для створення окремого вихідного файлу, mogrify використовується для зміни вихідного зображення.
недільний

1
png зображення з прозорим фоном не конвертується належним чином у jpg.
vishnu

4
Щоб конвертувати PNG з прозорим фоном, використовуйте таку команду:mogrify -format jpg -background black -flatten *.png
hyperknot

3
@KevinCox на моєму вікні linux після того, як у mogrify -format jpeg img.pngмене є два файли та file img.*звіти про один png, оригінальний недоторканий та новий jpeg. Так mogrifyсамо НЕ перезаписує вихідні файли в цьому випадку.
neurino

4
З mogrifyдокументації: " Цей інструмент схожий, за convertвинятком того, що оригінальний файл зображення буде перезаписаний (якщо ви не змінюєте суфікс файлу за допомогою параметра -формат ) з будь-якими
потрібними

82

У мене є ще пара рішень.

Найпростіше рішення, як і більшість вже опублікованих. Простий баш для петлі.

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

Чомусь я схиляюсь уникати циклів у bash, тому тут є більш уніфікований підхід xargs, використовуючи bash для імені mangling.

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

Той, який я використовую. Він використовує GNU Parallel для запуску декількох завдань одночасно, що підвищує продуктивність. Він встановлений за замовчуванням у багатьох системах і майже напевно є у вашому репо (це гарна програма, щоб мати навколо).

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

Кількість завдань за замовчуванням відповідає кількості процесів. Я знайшов краще використання CPU, використовуючи 3 завдання в моїй двоядерній системі.

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

І якщо ви хочете отримати деякі статистичні дані (ЗНО, завершені робочі місця, середній час на роботу ...)

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

Існує також альтернативний синтаксис, якщо ви використовуєте GNU Parallel.

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

І подібний синтаксис для деяких інших версій (включаючи debian).

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

2
+1 для правильного розширення рядка bash в для, якщо я можу дати вам ще один підсумок для згадування паралельних, я б. Однак є одна помилка - вам потрібна doneкінець для циклу. Крім того, для паралельних речей ви можете уникнути використання цього lsі труби з такою конструкцією, як: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png(див. Тут )
evilsoup

Виправлена ​​помилка. Це класний синтаксис, про який я не знав. Я не знаю, який з них мені подобається краще, напевно, з тієї ж причини, я вважаю за краще не використовувати петлі в баші. Я вважаю, що це рішення, тому що це, мабуть, більш "правильний" спосіб, але я, мабуть, буду дотримуватися lsметоду для себе, тому що це має більше сенсу для мене.
Кевін Кокс

1
... хоча слід зазначити, що цей синтаксис працює лише паралельно GNU. Паралель, упакована в деякі Linux-дистрибутиви (наприклад, Debian & Ubuntu), насправді є іншою версією з дещо іншим синтаксисом (використання, --а не :::), - і навіть тоді йому неприємно не вистачає деяких особливостей паралелі GNU.
злий

(хоча ті, хто знаходиться у дистрибутивах, які не пакують паралельно GNU, можуть встановити його з джерела досить легко, користуючись тут інструкціями )
evilsoup

Я думаю, що мені слід змінити його ще тоді, щоб він працював з якомога більшою кількістю версій.
Кевін Кокс

26

convertКоманда на багатьох дистрибутивах Linux встановлюється як частина пакету ImageMagick. Ось базовий код для запуску convertвсіх файлів PNG у каталозі та уникнення проблеми подвійного розширення:

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

8
Відповідно до сторінки man для конвертування: "Програма перетворення є членом набору інструментів ImageMagick (1)."
недільний

1
Ви праві. Я чомусь подумав, що це частина іншої бібліотеки. У будь-якому випадку код, який я розмістив вище, є правильним способом автоматизації пакетного перетворення в каталозі.
Марцін

2
Ви можете використовувати розширення bash для вдосконалення команди, наприклад:for f in *.png; do convert "$f" "${f/%png/jpg}"; done
evilsoup

просто пам’ятайте, що це враховує регістри. моя камера назвала його як * .JPG і не усвідомила цього в першу чергу.
ценапатія

10

тл; д-р

Для тих, хто хоче просто найпростіші команди:

Перетворення та збереження оригінальних файлів:

mogrify -format jpg *.png

Перетворення та видалення оригінальних файлів:

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

Пояснено пакетне перетворення

Якихось спізнився на вечірку, але просто для того, щоб усунути всю плутанину для того, хто може не дуже зручно ставитись до Клі, ось супер довідковий посилання та пояснення.

Приклад каталогу

bar.png
foo.png
foobar.jpg

Просте перетворення

Зберігає всі оригінальні файли png, а також створює jpg-файли.

mogrify -format jpg *.png

Результат

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

Пояснення

  • mogrify є частиною набору інструментів для обробки зображень ImageMagick .
    • маґрифікувати обробляє зображення на місці , тобто вихідний файл буде перезаписаний, за винятком -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Команда видаляє файли.

Фантазії

Тепер ось деякі ласощі для людей , які є зручними з клі.

Якщо ви хочете отримати якийсь результат під час перетворення файлів:

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, що з цим читати?
Стівен Джефріс

Це схильність до помилок (якщо ви не впевнені на 100%, що маєте справу з нормальними іменами файлів) і повільна (як у дуже, дуже, дуже повільно).
don_crissti

Яка якість JPG за замовчуванням і як можна зберегти часові позначки?
Дан Даскалеску

@DanDascalescu Наведені вище методи (крім останнього) дозволять зберегти назви файлів, але замінять їх розширення, тому файли з тимчасовими позначками повинні бути добре (завжди слід зробити копію та перевірити). Відповідно до ImageMagick, "за замовчуванням - використовувати оцінену якість вхідного зображення, якщо його можна визначити, інакше 92" ( imagemagick.org/script/command-line-options.php#quality ) Якість можна вказати за допомогою -quality <число> де <число> від 1 до 100.
Стівен Джефріс

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файлами, показує, як зменшити розмір / якість файлу і не зламатися через відсутність непарних символів у каталозі чи імені файлу.
Джоел Пурра

5

моє швидке рішення for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done


2
Це повинно бути одним з найпотворніших, найскладніших командних рядків, які я коли-небудь бачив
evilsoup

1
@evilsoup чесно, це елегантно для сценаріїв оболонок. Стверджувати, що це суперечка, не справедливо.
Макс Хоуелл

8
@MaxHowell людина. Ні . От би елегантний варіант цього: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done. Це дозволяє уникнути абсолютно непотрібних ls, grepі sedдзвінків (і echo, але IIRC, це вбудований баш і тому не матиме / дуже малого впливу на продуктивність), і позбавляється від двох труб і двох підпакетів і передбачає менший набір тексту. Це навіть трохи портативніше, оскільки не всі версії системи lsє безпечними для розбору.
зол

@evilsoup Я стою виправлений! Хороша робота.
Макс Хоуелл

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.

Це буде спрацьовувати в баші, а може, і поквапитися. Я не знаю про інші оболонки, але єдиною різницею, ймовірно, буде синтаксис циклу.


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.