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


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

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


141
2017-11-16 02:06


происхождения




ответы:


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

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

Пример:

convert image.png image.jpg

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

Команда:

mogrify -format jpg *.png  

210
2017-11-16 02:15



Удивительно, это именно то, что я получил и буду использовать снова. Кстати, просто уточнить, поскольку я не понимал, что это то, что вы имели в виду: convert используется для создания отдельного выходного файла, mogrify используется для изменения исходного изображения. - nedned
Изображения png с прозрачным фоном неправильно конвертируются в jpg. - vishnu
Чтобы преобразовать PNG с прозрачным фоном, используйте следующую команду: mogrify -format jpg -background black -flatten *.png - hyperknot
@KevinCox на моем linux box после mogrify -format jpeg img.png У меня есть 2 файла и file img.* сообщает один png, оригинальный нетронутый и новый jpeg. Так mogrify делает не перезапишите исходные файлы в этом случае. - neurino
Из mogrify документация: "Этот инструмент аналогичен convert за исключением того, что исходный файл изображения перезаписан (если вы не измените суффикс файла на -формат ) с любыми изменениями, которые вы запрашиваете." - janko-m


У меня есть еще несколько решений.

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

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

67
2018-01-28 02:45



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


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

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

25
2017-11-16 03:28



Согласно странице man для конвертации: «Программа конвертации является частью набора инструментов ImageMagick (1)». - nedned
Ты прав. По какой-то причине я думал, что это часть другой библиотеки. В любом случае код, который я опубликовал выше, является правильным способом автоматизации пакетного преобразования в каталоге. - Marcin
Вы можете использовать расширение bash, чтобы улучшить эту команду: for f in *.png; do convert "$f" "${f/%png/jpg}"; done - evilsoup
просто помните, что он чувствителен к регистру. моя камера называла его как .JPG и не понимала этого в первом случае. - tsenapathy


Настоящий "png2jpg«команда, которую вы ищете, на самом деле разделена на две команды, называемые pngtopnm а также cjpeg, и они являются частью netpbm а также libjpeg-progs пакетов, соответственно.

png2pnm foo.png | cjpeg > foo.jpeg

7
2017-11-16 05:29





ТЛ; др

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

Конвертировать а также держать исходные файлы:

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 option указывает, что вы будете изменять формат, а следующий аргумент должен быть типом (в данном случае, 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-файлы во все подкаталоги, поместите все полученные jpg в 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

6
2017-10-17 15:02



Вероятно, лучший ответ, если вы избавитесь от 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>, где <число> - от 1 до 100. - Steven Jeffries


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

4
2017-10-13 17:12



Спасибо за глубокое / рекурсивное однолинейное решение каталога, которое оставляет результат *.jpg файлы рядом с оригиналом *.png файлы, показывает, как уменьшить размер файла / качество и не прерывается из-за каких-либо нечетных символов в каталоге или имени файла. - Joel Purra


мое быстрое решение for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done


3
2018-05-07 12:42



Это должно быть одной из самых уродливых, самых запутанных команд, которые я когда-либо видел - evilsoup
@evilsoup честно, это изящно для shell-скриптов. Утверждение, что оно запутано, несправедливо. - Max Howell
@MaxHowell человек. Нет. Здесь будет изящная версия: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done, Это позволяет избежать совершенно ненужных ls, grep а также sed звонков (и echo, но IIRC, который встроен в bash и поэтому не будет иметь / очень мало влияния на производительность), и избавится от двух труб и двух подоболочек, а также включает в себя меньшую типизацию. Это даже немного более портативно, поскольку не все версии ls безопасны для синтаксического анализа. - evilsoup
@evilsoup Я стою исправлено! Отличная работа. - Max Howell


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

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

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

Это будет работать в bash, и, возможно, bourne. Я не знаю о других оболочках, но единственная разница, скорее всего, будет синтаксисом цикла.


2
2017-11-16 02:28





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

Адаптация кода от @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





Это то, что я использую для преобразования, когда файлы охватывают более одного каталога. Мой оригинальный был 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

0
2017-09-17 02:34