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

187159
nedned

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

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

143

10 ответов на вопрос

214
William Hilsum

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

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

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

convert image.png image.jpg 

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

Команда:

mogrify -format jpg *.png 
Круто, это именно то, что я был после и буду использовать снова. Кстати, просто чтобы прояснить, поскольку я не осознавал, что это то, что вы имели в виду: convert используется для создания отдельного выходного файла, mogrify используется для изменения исходного изображения. nedned 14 лет назад 7
Изображения PNG с прозрачным фоном не преобразуются должным образом в JPG. vishnu 12 лет назад 1
Чтобы преобразовать PNG с прозрачным фоном, используйте следующую команду: `mogrify -format jpg -background black -flatten * .png` hyperknot 11 лет назад 3
Интересно, как это может перезаписать оригинальные файлы *, если * имя файла меняется ... на самом деле файлы jpg остаются нетронутыми;) Ах, +1 neurino 10 лет назад 0
@neurino Имя файла не изменяется в примере с mogrify. Файлы по-прежнему имеют расширение `.png`, но являются изображениями в формате JPEG. Попробуйте использовать `file img.png` (после запуска mogrify), и он скажет вам, что это изображение в формате JPEG. Kevin Cox 10 лет назад 0
@KevinCox на моем linux box после `mogrify -format jpeg img.png` У меня есть 2 файла, и` file img. * `Сообщает об одном png, исходном нетронутом и новом jpeg. Так что `mogrify` ** не ** перезаписывает оригинальные файлы в этом случае. neurino 10 лет назад 3
@neurino Интересно. Со страницы руководства mogrify: "mogrify - измените размер изображения, размытие, обрезка, удаление пятен, сглаживание, рисование, отражение, объединение, повторную выборку и многое другое. Mogrify перезаписывает исходный файл изображения, тогда как convert (1) записывает в другой файл изображения. " Так что я не знаю, почему это происходит на вашей коробке. Kevin Cox 10 лет назад 0
@neurino Это происходит и на моей коробке. Теперь я действительно запутался, это ошибка? Или недокументированная особенность? Kevin Cox 10 лет назад 0
Из документации `mogrify`:" * Этот инструмент похож на `преобразование`, за исключением того, что исходный файл изображения перезаписывается (если вы не измените суффикс файла с помощью опции ** - format **) с любыми изменениями, которые вы запрашиваете. *" janko-m 9 лет назад 4
Если вам нужно сжать png больше, используйте `mogrify -quality 75 -format jpg * .png` Flatron 7 лет назад 0
Я тоже на Ubuntu Desktop 16 сегодня - оригинальные файлы остаются Nam G VU 7 лет назад 0
70
Kevin Cox

I have a couple more solutions.

The simplest solution is like most already posted. A simple bash for loop.

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

For some reason I tend to avoid loops in bash so here is a more unixy xargs approach, using bash for the name-mangling.

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

The one I use. It uses GNU Parallel to run multiple jobs at once, giving you a performance boost. It is installed by default on many systems and is almost definitely in your repo (it is a good program to have around).

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

The number of jobs defaults to the number of processes you have. I found better CPU usage using 3 jobs on my dual-core system.

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

And if you want some stats (an ETA, jobs completed, average time per job...)

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

There is also an alternative syntax if you are using GNU Parallel.

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

And a similar syntax for some other versions (including debian).

parallel convert '{}' '{.}.jpg' -- *.png 
+1 для правильного расширения строки bash в for, если бы я мог дать вам еще одно возражение за упоминание параллели, я бы сказал. Однако есть одна опечатка - в конце цикла for необходимо выполнить `done`. Кроме того, для параллельной работы вы можете избежать использования этого `ls` и канала с такой конструкцией, как: 'parallel -j 3 --eta convert' {} '' {.}. Jpg '::: * .png` ( см. [здесь] (http://www.gnu.org/software/parallel/man.html#example__reading_arguments_from_command_line)) evilsoup 11 лет назад 2
Исправлена ​​опечатка. Это классный синтаксис, о котором я не знал. Я не знаю, какой из них мне нравится больше, вероятно, по той же причине, по которой я предпочитаю не использовать циклы в bash. Я назвал это решением, потому что это, вероятно, более "правильный" способ, но я, вероятно, буду придерживаться метода `ls` для себя, потому что он имеет больше смысла для меня. Kevin Cox 11 лет назад 0
... хотя следует отметить, что этот синтаксис работает только на параллельной GNU. Параллель, упакованная в некоторых дистрибутивах Linux (например, Debian & Ubuntu), на самом деле представляет собой другую версию с немного другим синтаксисом (используйте `--`, а не` ::: `) - и даже в этом случае, к сожалению, отсутствуют некоторые функции параллельно GNU. evilsoup 11 лет назад 1
(хотя те, на дистрибутивах, которые не упаковывают параллельный GNU, могут установить его из исходного кода довольно легко, используя инструкции [здесь] (http://askubuntu.com/a/142757/112879)) evilsoup 11 лет назад 0
Я думаю, что я должен изменить его тогда, чтобы он работал с максимально возможным количеством версий. Kevin Cox 11 лет назад 0
Если у вас есть каталог с более чем 10 000 изображений PNG в нем ... команда ls, скорее всего, потерпит неудачу. Итак, эта команда работает в следующих ситуациях: `find. -тип f -name '* .png' | параллель --eta convert '{}' '{.}. jpg'` Ahi Tuna 5 лет назад 0
25
Marcin

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

for img in *.png; do filename=$ convert "$filename.png" "$filename.jpg" done 
Согласно справочной странице для convert: «Программа convert является членом набора инструментов ImageMagick (1)». nedned 14 лет назад 8
Ты прав. По некоторым причинам я думал, что это было частью другой библиотеки. В любом случае код, который я разместил выше, является правильным способом автоматизации пакетного преобразования в каталоге. Marcin 14 лет назад 1
Вы можете использовать расширение bash для улучшения этой команды, например: `for f in * .png; конвертировать "$ f" "$ "; done` evilsoup 11 лет назад 2
просто помните, что он чувствителен к регистру. моя камера назвала это * .JPG и не поняла это в первую очередь. tsenapathy 8 лет назад 0
7
Teddy

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

png2pnm foo.png | cjpeg > foo.jpeg 
7
Steven Jeffries

tl;dr

For those who just want the simplest commands:

Convert and keep original files:

mogrify -format jpg *.png 

Convert and remove original files:

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

Batch Converting Explained

Kinda late to the party, but just to clear up all of the confusion for someone who may not be very comfortable with cli, here's a super dumbed-down reference and explanation.

Example Directory

bar.png foo.png foobar.jpg 

Simple Convert

Keeps all original png files as well as creates jpg files.

mogrify -format jpg *.png 

Result

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

Explanation

  • mogrify is part of the ImageMagick suite of tools for image processing.
    • mogrify processes images in place, meaning the original file is overwritten, with the exception of the -format option. (From the site: This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option))
  • The - format option specifies that you will be changing the format, and the next argument needs to be the type (in this case, jpg).
  • Lastly, *.png is the input files (all files ending in .png).

Convert and Remove

Converts all png files to jpg, removes original.

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

Result

bar.jpg foo.jpg foobar.jpg 

Explanation

  • The first part is the exact same as above, it will create new jpg files.
  • The && is a boolean operator. In short:
    • When a program terminates, it returns an exit status. A status of 0 means no errors.
    • Since && performs short circuit evaluation, the right part will only be performed if there were no errors. This is useful because you may not want to delete all of the original files if there was an error converting them.
  • The rm command deletes files.

Fancy Stuff

Now here's some goodies for the people who are comfortable with the cli.

If you want some output while it's converting files:

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

Convert all png files in all subdirectories and give output for each one:

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

Convert all png files in all subdirectories, put all of the resulting jpgs into the all directory, number them, remove original png files, and display output for each file as it takes place:

n=0; find . -iname '*.png' | while read i; do mogrify -format jpg "$i" && rm "$i"; fn="all/$((n++)).jpg"; mv "$.jpg" "$fn"; echo "Moved $i to $fn"; done 
Возможно, лучший ответ, если вы избавитесь от части `while read` (замените или удалите все вместе) ... don_crissti 8 лет назад 0
@don_crissti, что не так во время чтения? Steven Jeffries 8 лет назад 0
Это подвержено ошибкам (если вы не уверены на 100%, что имеете дело с вменяемыми именами файлов) и медленное (как в очень, очень, очень медленном). don_crissti 8 лет назад 0
Какое качество JPG по умолчанию, и как сохранить временные метки файла? Dan Dascalescu 6 лет назад 0
@DanDascalescu Приведенные выше методы (кроме последнего) сохранят имена файлов, но заменит их расширение, поэтому с временными файлами все должно быть в порядке (всегда сначала делайте копию и тестируйте). Согласно ImageMagick, «по умолчанию используется оценочное качество входного изображения, если оно может быть определено, иначе 92» (http://www.imagemagick.org/script/command-line-options.php#quality) Качество можно указать с -quality где от 1 до 100. Steven Jeffries 6 лет назад 0
Благодарю. `mogrify -format jpg foo.png` создал foo.jpg с текущей отметкой времени. Я хотел скопировать метку времени foo.png в foo.jpg, и я не вижу ничего подобного в [options] (https://www.imagemagick.org/script/mogrify.php). Dan Dascalescu 6 лет назад 0
4
emdog4
find . -name "*.png" -print0 | xargs -0 mogrify -format jpg -quality 50 
Спасибо за глубокое / рекурсивное однострочное решение для каталога, которое оставляет полученные файлы `* .jpg` рядом с исходными файлами` * .png`, показывает, как уменьшить размер / качество файла и не ломается из-за каких-либо нечетных символов в каталоге или имени файла. Joel Purra 9 лет назад 1
3
max

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

Это должно быть одна из самых уродливых, самых запутанных командных строк, которые я когда-либо видел evilsoup 11 лет назад 2
@evilsoup Честно говоря, это элегантно для сценариев оболочки. Утверждать, что это запутанно, нечестно. Max Howell 10 лет назад 1
@MaxHowell человек. Нет. Вот элегантная версия этого: `for f in ./*.png; конвертировать "$ f" "$ . jpg"; done`. Это позволяет избежать абсолютно ненужных вызовов `ls`,` grep` и `sed` (и` echo`, но IIRC - встроенная функция bash и поэтому не окажет / очень незначительное влияние на производительность), а также избавит от двух каналов и двух подоболочек. * и * включает в себя меньше печатать. Он даже немного более переносим, ​​поскольку не все версии `ls` безопасны для анализа. evilsoup 10 лет назад 8
@evilsoup Я исправлюсь! Хорошая работа. Max Howell 10 лет назад 0
2
Jeffrey Aylesworth

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

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

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

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

2
user7023624

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

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

#!/bin/sh  for img in *.png do filename=$ png2jpeg -q 95 -o "$filename.jpg" "$filename.png" done 
0
Archimedes Trajano

This is what I use to convert when the files span more than one directory. My original one was TGA to PNG

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

The concept is you find the files you need, strip off the extension then add it back in with xargs. So for PNG to JPG, you'd change the extensions and do one extra thing to deal with alpha channels namely setting the background (in this example white, but you can change it) then flatten the image

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

Похожие вопросы