4

Выбор правильного формата для сохранения ваших изображений имеет решающее значение для сохранения качества изображения и уменьшения артефактов. Различные форматы следуют разным методам сжатия и имеют свои преимущества и недостатки.

Например, JPG подходит для реальных фотографий, богатых цветными градиентами. PNG без потерь, с другой стороны, намного превосходит схематические фигуры:

Выбор правильного формата может быть непростой задачей при работе с большим количеством файлов. Вот почему я хотел бы найти способ автоматизировать его.


Немного предыстории моего конкретного случая использования:

Я работаю над несколькими раздаточными материалами для серии лекций в моем университете. В раздаточном материале много рисунков, которые я должен извлечь из слайдов в формате PDF. Извлечение этих изображений дает мне PNG без потерь, которые иногда слишком велики.

Преобразование этих конкретных файлов в JPEG может уменьшить их размер до менее чем 20% от их исходного размера при сохранении того же качества. Это важно, так как работа с сотнями больших изображений в текстовых процессорах довольно подвержена сбоям.

Пакетное преобразование всех извлеченных PNG-файлов в JPEG-файл не является вариантом, которому я хочу следовать, поскольку многие, если не большинство изображений, лучше подходят для форматирования в формате PNG. Их преобразование приведет к незначительному уменьшению размера, а иногда даже к увеличению размера файла - по крайней мере, так показали мои тесты.


Из этого можно сделать вывод, что размер файла после сжатия может служить индикатором того, какой формат лучше всего подходит для конкретного изображения. Это не очень точный предсказатель, но работает достаточно хорошо. Так почему бы не использовать его в виде скрипта:

Я включил inotifywait, потому что предпочел бы, чтобы скрипт выполнялся автоматически, как только я перетащил извлеченное изображение в папку.

Это более простая версия скрипта, которую я использовал последние пару недель:

#!/bin/bash
inotifywait -m --format "%w%f" --exclude '.jpg' -r -e create -e moved_to --fromfile '/home/MHC/.scripts/Workflow/Conversion/include_inotifywait' | while read file; do mogrify -format jpg -quality 92 "$file"
done

Продвинутая версия скрипта должна была бы

  • уметь обрабатывать пробелы в именах файлов и каталогов
  • сохранить оригинальные имена файлов
  • сглаживать изображения PNG, если установлено альфа-значение
  • сравнить размер файла между временно преобразованным изображением и его оригиналом
  • определить, больше ли разница, чем заданный процент
  • Действуй соответственно

Фактическое преобразование может быть сделано с помощью инструментов imagemagick:

convert -quality 92 -flatten -background white file.png file.jpg

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

Моя репутация здесь довольно низкая, но я с радостью предоставлю самый полезный ответ с самой высокой наградой, которую я могу установить.

Ссылки: http://www.formortals.com/introduction-cnb-imageguide/, http://www.turnkeylinux.org/blog/png-vs-jpg.

Изменить: Также см. Мои комментарии ниже для получения дополнительной информации о том, почему я думаю, что этот скрипт будет лучшим решением проблемы, с которой я сталкиваюсь.

2 ответа2

1

PDF-файлы поддерживают как кодирование без потерь, так и кодирование JPEG. (JPEG 2000 также.) Возможно, вам понадобится инструмент, который извлекает данные изображения непосредственно из PDF-файла и оставляет все как есть. Pdfimages из пакета XPDF сделает это.

ImageMagick фактически отобразит всю страницу и извлечет ее. Это отбрасывает выбор кодировки, которая уже хранится в PDF, и это не лучший способ выполнить эту задачу.

1

Редактировать: Исправлены некоторые проблемы с оригинальным скриптом. Добавлен альтернативный вариант, основанный на предложении Маркса Томаса.

Редактировать 2: Обновлены значения отсечки, основанные на количестве тестовых прогонов. Я все еще не уверен, как оценить размеры файлов для изображений в оттенках серого. Если вы работаете с большим количеством изображений вне цветовых схем RGB, вам может потребоваться реализовать первый сценарий в качестве запасного режима для второго.

Редактировать 3: Добавлена optipng интеграция. Это оптимизирует размеры файлов PNG без потери качества. Смотрите здесь для получения дополнительной информации. Некоторые небольшие улучшения.


Версия 0.1

Важное примечание: этот скрипт устарел.Новые версии гораздо эффективнее.

Хорошо, мой вопрос, возможно, был немного слишком локализован, поэтому я потратил немного времени на это и сам скомпилировал сценарий:

#!/bin/bash

# AUTHOR:   (c) MHC (http://askubuntu.com/users/81372/mhc)
# NAME:     Intelliconvert 0.1
# DESCRIPTION:  A script to automate and optimize the choice between different image formats.
# LICENSE:  GNU GPL v3 (http://www.gnu.org/licenses/gpl.html)
# REQUIREMENTS:  Imagemagick

ORIGINAL="$1"

###Filetype check###

MIME=$(file -ib "$ORIGINAL")

if [ "$MIME" = "image/png; charset=binary" ]
  then
    echo "PNG Mode"

###Variables###

      ##Original Image##
    FILENAME=$(basename "$ORIGINAL")
    PARENTDIR=$(dirname "$ORIGINAL")
        SUBFOLDER=$(echo "$PARENTDIR" | cut -d"/" -f10-)
    ORIGARCHIVE="~/ORIG"

      ##Converted Image##
    TEMPDIR="/tmp/imgcomp"
    CONVERTED="$TEMPDIR/$FILENAME.jpg"

      ##Image comparison##
    DIFFLO="50"
    DIFFHI="75"
    CUTOFF="1000000"

      ##DEBUG
    echo "#### SETTINGS ####"
    echo "Filepath to original = $ORIGINAL"
    echo "Filename= $FILENAME"
    echo "Parent directory = $PARENTDIR"
    echo "Archive directory = $ORIGARCHIVE"
    echo "Temporary directory = $TEMPDIR"
    echo "Filepath to converted image = $CONVERTED"
    echo "Low cut-off = $DIFFLO"
    echo "High cut-off = $DIFFHI"

###Conversion###

    convert -quality 92 -flatten -background white "$ORIGINAL" "$CONVERTED"

###Comparison###

    F1=$(stat -c%s "$ORIGINAL" )
    F2=$(stat -c%s "$CONVERTED" )
    FQ=$(echo "($F2*100/$F1)" | bc)

      #Depending on filesize we use a different Cut-off#
    if [ "$F1" -ge "$CUTOFF" ]
      then
        DIFF="$DIFFHI"
      else  
        DIFF="$DIFFLO"
    fi

      ##DEBUG
    echo "### COMPARISON ###"
    echo "Filesize original = $F1 Bytes"
    echo "Filesize converted = $F2 Bytes"
    echo "Chosen cut-off = $DIFF %"
    echo "Actual Ratio = $FQ %"


    if [ "$FQ" -le "$DIFF" ]
      then
           echo "JPEG is more efficient, converting..."
           mv -v "$CONVERTED" "$PARENTDIR"
               mkdir -p "$ORIGARCHIVE/$SUBFOLDER"
           mv -v "$ORIGINAL" "$ORIGARCHIVE/$SUBFOLDER"
      else
           echo "PNG is fine, exiting."
           rm -v "$CONVERTED"
    fi


  else
    echo "File does not exist or unknown MIME type, exiting."

fi

Сценарий прекрасно работает в сочетании с Watcher.

Это мой первый правильный сценарий, поэтому могут быть некоторые нерешенные ошибки и проблемы, которые я просто не видел. Не стесняйтесь использовать это для себя и улучшить это. Если вы это сделаете, я был бы признателен, если бы вы могли оставить здесь комментарий, чтобы я мог извлечь уроки из него.


Версия 0.2.1

Более эффективный способ найти правильный формат может быть достигнут путем сравнения размера файла оригинала с его предполагаемым размером в виде несжатого изображения:

#!/bin/bash

# AUTHOR:   (c) MHC (http://askubuntu.com/users/81372/mhc)
# NAME:     Intelliconvert 0.2.1
# DESCRIPTION:  A script to automate and optimize the choice between different image formats.
# LICENSE:  GNU GPL v3 (http://www.gnu.org/licenses/gpl.html)
# REQUIREMENTS:  Imagemagick, Optipng

################ Filetype Check#################

MIME=$(file -ib "$1")

if [ "$MIME" = "image/png; charset=binary" ]
  then
    echo "###PNG Mode###"

####################Settings####################

##Folders##
ORIGARCHIVE="~/ORIG"

##Comparison##
DIFFLO="25"
DIFFHI="20"
CUTOFF="1000000"

################################################

###Variables###

ORIGINAL="$1"
FILENAME=$(basename "$ORIGINAL")
PARENTDIR=$(dirname "$ORIGINAL")
SUBFOLDER=$(echo "$PARENTDIR" | cut -d"/" -f10-)
CONVERTED="$PARENTDIR/$FILENAME.jpg"

#DEBUG#
    echo "###SETTINGS###"
    echo "Filepath to original = $ORIGINAL"
    echo "Filename= $FILENAME"
    echo "Parent directory = $PARENTDIR"
    echo "Archive directory = $ORIGARCHIVE"
    echo "Filepath to converted image = $CONVERTED"
    echo "Low cut-off = $DIFFLO"
    echo "High cut-off = $DIFFHI"


###Image data###

        WIDTH=$(identify -format "%w" "$ORIGINAL")
        HEIGHT=$(identify -format "%h" "$ORIGINAL")
        ZBIT=$(identify -format "%z" "$ORIGINAL")
        COL=$(identify -format "%[colorspace]" "$ORIGINAL")
        F1=$(stat -c%s "$ORIGINAL")

        if [ "$COL" = "RGB" ]
          then
              CHANN="3"
          else
              CHANN="1"
        fi


###Cutoff setting###

    if [ "$F1" -ge "$CUTOFF" ]
      then
        DIFF="$DIFFHI"
      else  
        DIFF="$DIFFLO"
    fi


###Calculations on uncompressed image###

        BMPSIZE=$(echo "($WIDTH*$HEIGHT*$ZBIT*$CHANN/8)" | bc)
        FR=$(echo "($F1*100/$BMPSIZE)" | bc)

#DEBUG#

        echo "###IMAGE DATA###"
        echo "Image Dimensions = $WIDTH x $HEIGHT"
        echo "Colour Depth = $ZBIT"
        echo "Colour Profile = $COL"
        echo "Channels = $CHANN"
        echo "Estimated uncompressed size = $BMPSIZE"
        echo "Actual file size = $F1"
        echo "Estimated size ratio = $FR %"
        echo "Cutoff at $DIFF %"

###Backup###

        echo "###BACKUP###"
        mkdir -p "$ORIGARCHIVE/$SUBFOLDER"  #keep the original folder structure
        cp -v "$ORIGINAL" "$ORIGARCHIVE/$SUBFOLDER"
        echo ""

###Comparison###

    if [ "$FR" -ge "$DIFF" ]
      then
          echo "JPEG is more efficient, converting..."
          convert -quality 92 -flatten -background white "$ORIGINAL" "$CONVERTED"
              echo "Done."
          echo "Cleaning up..."
          rm -v "$ORIGINAL"
      else
          echo "PNG is fine, passing over to optipng."
              echo "Optimizing..."
              optipng "$ORIGINAL"
              echo "Done."
    fi

################ Filetype Check#################

  else
    echo "File does not exist or unknown MIME type, exiting."

fi

Рекомендую @Marcks Thomas за отличную идею.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .