- Нет возможности оптимизировать автоматически много файлов
- Сложно и неудобно использовать в рабочем процессе
Но прежде всего следует отметить, что описанный ниже способ нельзя причислить к самым лучшим хотя бы потому, что в идеале каждое изображение следует оптимизировать индивидуально.
Оптимизация изображений с помощью командой строки
Для каждого png файла используются optipng и pngcrush, а для jpg — jpegtran. Для начала опробуем optipng:
Примечание: С параметр -o7 optipng работает в самом медленном режиме. Для быстрого используется -o0.
Затем pngcrush:
Оптимизация JPG с помощью jpegtran:
Написание скрипта
Готовый скрипт можно посмотреть на GitHub’е. Ниже подробно представлен процесс написания.
Прежде всего необходимо задать основные параметры:
- -i или —input для исходной папки
- -o или —output для папки с результатом
- -q или —quiet для отключения вывода процесса выполнения
- -s или —no-stats для отключения вывода статистики
- -h или —help для вызова справки
Две переменные для коротких и полных имен параметров:
SHORTOPTS="h,i:,o:,q,s" LONGOPTS="help,input:,output:,quiet,no-stats"
Используем getopt для передаваемых в скрипт параметров, цикл для вызова функция или определения переменных для хранения:
ARGS=$(getopt -s bash --options $SHORTOPTS --longoptions $LONGOPTS --name $PROGNAME -- "$@") eval set -- "$ARGS" while true; do case $1 in -h|--help) usage exit 0 ;; -i|--input) shift INPUT=$1 ;; -o|--output) shift OUTPUT=$1 ;; -q|--quiet) QUIET='1' ;; -s|--no-stats) NOSTATS='1' ;; --) shift break ;; *) shift break ;; esac shift done
HELP
Создаем две функции:
- usage(), в цикле, для вызова справки
- main() для оптимизации изображений
Они должны быть объявлены до цикла.
PROGNAME=${0##*/} usage() { cat <<EO Usage: $PROGNAME [options] Script to optimize JPG and PNG images in a directory. Options: EO cat <<EO | column -s\& -t -h, --help & shows this help -q, --quiet & disables output -i, --input [dir] & specify input directory (current directory by default) -o, --output [dir] & specify output directory ("output" by default) -ns, --no-stats & no stats at the end EO } SHORTOPTS="h,i:,o:,q,s" LONGOPTS="help,input:,output:,quiet,no-stats" ARGS=$(getopt -s bash --options $SHORTOPTS --longoptions $LONGOPTS --name $PROGNAME -- "$@")
Проверим, что получилось.
Примечание: если возникают ошибки, вроде "./optimize.sh: line 2: $’\r’: command not found", то необходимо открыть скрипт в Sublime Text 2 и включить Unix Mode в View > Line endings > Unix.
Главная функция (main)
main() { # If $INPUT is empty, then we use current directory if [[ "$INPUT" == "" ]]; then INPUT=$(pwd) fi # If $OUTPUT is empty, then we use the directory "output" in the current directory if [[ "$OUTPUT" == "" ]]; then OUTPUT=$(pwd)/output fi # We create the output directory mkdir -p $OUTPUT # To avoid some troubles with filename with spaces, we store the current IFS (Internal File Separator)... SAVEIFS=$IFS # ...and we set a new one IFS=$(echo -en "\n\b") max_filelength=`get_max_file_length` pad=$(printf '%0.1s' "."{1..600}) sDone=' [ DONE ]' linelength=$(expr $max_filelength + ${#sDone} + 5) # Search of all jpg/jpeg/png in $INPUT # We remove images from $OUTPUT if $OUTPUT is a subdirectory of $INPUT IMAGES=$(find $INPUT -regextype posix-extended -regex '.*\.(jpg|jpeg|png)' | grep -v $OUTPUT) if [ "$QUIET" == "0" ]; then echo --- Optimizing $INPUT --- echo fi for CURRENT_IMAGE in $IMAGES; do filename=$(basename $CURRENT_IMAGE) if [ "$QUIET" == "0" ]; then printf '%s ' "$filename" printf '%*.*s' 0 $((linelength - ${#filename} - ${#sDone} )) "$pad" fi optimize_image $CURRENT_IMAGE $OUTPUT/$filename if [ "$QUIET" == "0" ]; then printf '%s\n' "$sDone" fi done # we restore the saved IFS IFS=$SAVEIFS if [ "$NOSTATS" == "0" -a "$QUIET" == "0" ]; then echo echo "Input: " $(human_readable_filesize $max_input_size) echo "Output: " $(human_readable_filesize $max_output_size) space_saved=$(expr $max_input_size - $max_output_size) echo "Space save: " $(human_readable_filesize $space_saved) fi }
Необходимо дать возможность задать директории, либо выполнять скрипт в текущей, используя команду mkdir. Далее необходимо заставить скрипт корректно работать с файлами, в названиях которых есть пробелы. Для этого используем IFS (Internal File Separator). Функция optimize_image, оптимизирующая изображения, имеет два параметра — для исходной и финальной директорий.
optimize_image:
# $1: input image # $2: output image optimize_image() { input_file_size=$(stat -c%s "$1") max_input_size=$(expr $max_input_size + $input_file_size) if [ "${1##*.}" = "png" ]; then optipng -o1 -clobber -quiet $1 -out $2 pngcrush -q -rem alla -reduce $1 $2 >/dev/null fi if [ "${1##*.}" = "jpg" -o "${1##*.}" = "jpeg" ]; then jpegtran -copy none -progressive $1 > $2 fi output_file_size=$(stat -c%s "$2") max_output_size=$(expr $max_output_size + $output_file_size) }
Выходная информация
Результат выполнения скрипта должен наглядно отображаться, например так:
file1 ...................... [ DONE ] file2 ...................... [ DONE ] file_with_a_long_name ...... [ DONE ] ...
Сначала необходимо сделать следующие шаги:
- Определить длины названий файлов
- Заменить промежутки точками
- Задать максимальную длина названия и текста " [ DONE ]"
В итоге строки должны содержать название файла, точки и DONE и должны быть одинаковой длины.
max_filelength=`get_max_file_length` pad=$(printf '%0.1s' "."{1..600}) sDone=' [ DONE ]' linelength=$(expr $max_filelength + ${#sDone} + 5) # Search of all jpg/jpeg/png in $INPUT # We remove images from $OUTPUT if $OUTPUT is a subdirectory of $INPUT IMAGES=$(find $INPUT -regextype posix-extended -regex '.*\.(jpg|jpeg|png)' | grep -v $OUTPUT) if [ "$QUIET" == "0" ]; then echo --- Optimizing $INPUT --- echo fi for CURRENT_IMAGE in $IMAGES; do filename=$(basename $CURRENT_IMAGE) if [ "$QUIET" == "0" ]; then printf '%s ' "$filename" printf '%*.*s' 0 $((linelength - ${#filename} - ${#sDone} )) "$pad" fi optimize_image $CURRENT_IMAGE $OUTPUT/$filename if [ "$QUIET" == "0" ]; then printf '%s\n' "$sDone" fi done
Проверим скрипт, запустив с параметрами:
# All parameters to default ./optimize.sh # Or with custom options ./optimize.sh --input images --output optimized-images # Or with custom options and shorthand ./optimize.sh -i images -o optimized-images
Статистика
Для отображения статистики работы скрипта используем input_file_size и output_file_size, которые возвращают исходный и конечный размер изображения. Для удобства чтения информации используем human_readable_filesize().
Запускаем скрипт еще раз и видим статистику:
Осталось только отображать процесс выполнения оптимизации:
if [ "$QUIET" == "0" ]; then echo --- Optimizing $INPUT --- echo fi for CURRENT_IMAGE in $IMAGES; do filename=$(basename $CURRENT_IMAGE) if [ "$QUIET" == "0" ]; then printf '%s ' "$filename" printf '%*.*s' 0 $((linelength - ${#filename} - ${#sDone} )) "$pad" fi optimize_image $CURRENT_IMAGE $OUTPUT/$filename if [ "$QUIET" == "0" ]; then printf '%s\n' "$sDone" fi done
Все! В результате получился скрипт, который умеет автоматически оптимизировать изображения. Скачать на GitHub’е.
ссылка на оригинал статьи http://habrahabr.ru/post/154683/
Добавить комментарий