digital-garden/dev/snippet/Сжатие изображений без потери качества.md

4.9 KiB
Raw Blame History

tags date zero-link parents linked
maturity/🌱
2023-11-20
../../meta/zero/00 Снипеты на bash

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

#!/bin/bash
file=comp.flag

if [ -f "$file" ]; then
    option="-newer $file"
fi

find ./images/ -type f -not -path "./images/comp/*" ! -name "*-no-comp.*" $option -iname "*.png" -exec sh -c '
  png_file="${1/\/images\//\/images\/comp\/}"
  png_dir="$(dirname "$png_file")"
  mkdir -p "$png_dir"
  cp "$1" "${png_file}"
  optipng -o7 "${png_file}"
  advpng -z4 "${png_file}"
  pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time -ow "${png_file}"
' _ {} \;

find ./images/ -type f-not -path "./images/comp/*" ! -name "*-no-comp.*" $option -iregex '.*\.\(jpg\|jpeg\)' -exec sh -c '
  jpg_file="${1/\/images\//\/images\/comp\/}"
  jpg_dir="$(dirname "$jpg_file")"
  mkdir -p "$jpg_dir"
  cp "$1" "${jpg_file}"
  jpegoptim --all-progressive "${jpg_file}"
' _ {} \;

touch $file
echo "$(date)" > $file

Этот скрипт сжимает изображения без потери качества. Он размещается рядом с каталогом images, в котором находятся ваши изображения. Разберемся, как он работает.

Сначала скрипт проверяет, существует ли в текущем каталоге файл comp.flag. Если файл существует, он устанавливает значение -newer $file в переменную option, которая будет использоваться в качестве фильтра для поиска только тех файлов, которые были изменены после даты создания файла optimg.flag. Если файл не существует, переменная option будет пустой.

Затем скрипт использует команду find для рекурсивного поиска файлов в каталоге images и его подкаталогах, которые:

  • -type f. Являются обычными файлами.
  • Имеют расширение имени файла .png.jpeg или .jpg.
  • -not -path. Не находятся в указанных каталогах_._ В данном случае это каталоги ./images/comp. Мы будем складывать туда сжатые изображения, и мы не хотим заново по ним проходить поиском и сжимать снова.
  • ! -name "-no-comp.". Оставим возможность не сжимать изображение, если его имя заканчивается на -no-comp.
  • Для каждого из этих файлов сценарий использует свою команду оптимизации.

Мы не будем затирать оригиналы изображений. Вместо этого мы создадим дополнительную папку comp в каталоге images, в которую и сложим преобразованные изображения. Создаваемая структура подкаталогов в comp будет повторять структуру подкатологов в images.

Для файлов PNG сначала используется optipng для сжатия с самым высоким уровнем оптимизации (-o7). Далее используем advpng для дальнейшего сжатия с уровнем сжатия 4 (-z4). И наконец pngcrush для удаления из файла определенных фрагментов, которые можно безопасно удалить для уменьшения размера файла.

Для файлов JPEG используется jpegoptim для их оптимизации со сжатием без потерь (--all-progressive --strip-all).

После оптимизации всех подходящих изображений сценарий пересоздает файл comp.flag. Это гарантирует, что скрипт будет оптимизировать только те файлы, которые были изменены с момента последнего запуска.

Дополнительные материалы