Пакетное преобразование PNG в JPG в Linux

163

Кто-нибудь знает хороший способ пакетного преобразования группы PNG в JPG в Linux? (Я использую Ubuntu).

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

nedned
источник

Ответы:

237

Лучше всего будет использовать Imagemagick

Я не эксперт по фактическому использованию, но я знаю, что вы можете в значительной степени сделать что-нибудь изображение, связанное с этим!

Примером является:

convert image.png image.jpg

и он сохранит оригинал, а также создаст преобразованное изображение. Что касается партии. Я думаю, что вам нужно использовать инструмент Mogrify (из той же командной строки, когда в imagemagick). Имейте в виду, что это перезаписывает старые изображения.

Команда:

mogrify -format jpg *.png  
Уильям Хилсум
источник
7
Круто, это именно то, что я был после и буду использовать снова. Кстати, просто чтобы уточнить, как я не понял, это то, что вы имели в виду: convert используется для создания отдельного выходного файла, mogrify используется для изменения исходного изображения.
nedned
1
PNG изображения с прозрачным фоном не конвертируются должным образом в JPG.
Вишну
4
Чтобы преобразовать PNG с прозрачным фоном, используйте следующую команду:mogrify -format jpg -background black -flatten *.png
hyperknot
3
@KevinCox на моем linux box после того, как у mogrify -format jpeg img.pngменя есть 2 файла и file img.*сообщается один png, оригинальный нетронутый и новый jpeg. Так mogrifyчто не перезаписывать оригинальные файлы в этом случае.
неврино
4
Из mogrifyдокументации: « Этот инструмент похож на за convertисключением того, что исходный файл изображения будет перезаписан (если вы не измените суффикс файла с -format опция) с любыми изменениями вы запрашиваете. »
Янко-м
82

У меня есть еще пара решений.

Самое простое решение похоже на большинство уже опубликованных. Простой удар для цикла.

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

По какой-то причине я стараюсь избегать циклов в bash, так что здесь есть более юниксный подход xargs, использующий bash для искажения имен.

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

Тот, который я использую. Он использует GNU Parallel для одновременного запуска нескольких заданий, что повышает производительность. Он устанавливается по умолчанию во многих системах и почти наверняка находится в вашем репозитории (это хорошая программа, чтобы иметь вокруг).

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

Количество заданий по умолчанию равно числу процессов, которые у вас есть. Я нашел лучшее использование процессора, используя 3 задания в моей двухъядерной системе.

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

И если вам нужна статистика (ETA, выполненные задания, среднее время работы ...)

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

Существует также альтернативный синтаксис, если вы используете GNU Parallel.

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

И похожий синтаксис для некоторых других версий (включая Debian).

parallel convert '{}' '{.}.jpg' -- *.png
Кевин Кокс
источник
2
+1 для правильного расширения строки bash в for, если бы я мог дать вам еще одно возражение за упоминание параллели, я бы сказал. Однако есть одна опечатка - вам нужен doneконец цикла for. Кроме того, для параллельной работы вы можете избежать использования этого lsи pipe с такой конструкцией, как: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png(см. Здесь )
evilsoup
Исправлена ​​опечатка. Это классный синтаксис, о котором я не знал. Я не знаю, какой мне нравится больше, вероятно, по той же причине, по которой я предпочитаю не использовать циклы в bash. Я назвал это решением, потому что это, вероятно, более "правильный" способ, но я, вероятно, буду придерживаться lsметода для себя, потому что он имеет больше смысла для меня.
Кевин Кокс
1
... хотя следует отметить, что этот синтаксис работает только на параллельной GNU. Параллель, которая упакована в некоторых дистрибутивах Linux (таких как Debian и Ubuntu), на самом деле представляет собой другую версию с немного другим синтаксисом (используйте, --а не :::) - и даже тогда, к сожалению, ей не хватает некоторых функций параллели GNU.
evilsoup
(хотя те, на дистрибутивах, которые не упаковывают параллельный GNU, могут установить его из исходного кода довольно легко, используя инструкции здесь )
evilsoup
Я думаю, что я должен изменить его тогда, чтобы он работал с максимально возможным количеством версий.
Кевин Кокс
26

Команда, convertнайденная во многих дистрибутивах Linux, устанавливается как часть пакета ImageMagick. Вот код bash для запуска convertвсех файлов PNG в каталоге и избежания этой проблемы двойного расширения:

for img in *.png; do
    filename=${img%.*}
    convert "$filename.png" "$filename.jpg"
done
Marcin
источник
8
Согласно справочной странице для convert: «Программа convert является членом набора инструментов ImageMagick (1)».
nedned
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 для обработки изображений.
    • 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удаляет файлы.

Модные вещи

Теперь вот некоторые лакомства для людей , которые являются удобными с кли.

Если вы хотите выводить данные во время конвертации файлов:

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
emdog4
источник
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
@evilsoup Я исправлюсь! Отличная работа.
Макс Хауэлл
4

Слишком много лет спустя, специально для этой цели есть утилита png2jpeg , которую я создал.

Адаптация кода с помощью @Marcin:

#!/bin/sh

for img in *.png
do
    filename=${img%.*}
    png2jpeg -q 95 -o "$filename.jpg" "$filename.png"
done
user7023624
источник
3

Для пакетной обработки:

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

Вы получите имена файлов вроде image1.png.jpg.

Это будет работать в Bash, и, возможно, 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
Архимед Траяно
источник