Вывод вперёд: PNG — это сжатие без потерь, потому что он использует алгоритм DEFLATE — оба этапа, словарное сжатие LZ77 и кодирование Хаффмана, являются полностью обратимыми математическими операциями, после распаковки данные побайтово идентичны исходным. Процесс сжатия PNG: данные пикселей сначала проходят предсказание строк фильтрации для устранения избыточности между соседними пикселями, затем сжимаются алгоритмом DEFLATE. Скриншот UI 3000x2000: PNG сжимает исходные 17.2MB до 0.35MB, снижение на 97.9%, при этом значение каждого пикселя не меняется. Ниже подробно объясняется на двух уровнях: структура файла PNG и принцип алгоритма DEFLATE.
Если вы не очень знакомы с общими методами сжатия изображений, рекомендуется сначала прочитать Руководство по сжатию изображений: сравнение форматов JPG/PNG/WebP.
1. Структура файла PNG: как организованы данные
Файл PNG состоит из серии блоков данных (chunk), каждый chunk содержит четыре части: тип, длина, данные и контрольная сумма. Понимание роли этих chunk означает понимание внутренней структуры файла PNG.
| Блок данных | Полное название | Функция | Обязательность | Типичный размер |
|---|---|---|---|---|
| Сигнатура | PNG Signature | 8-байтовый идентификатор файла (89 50 4E 47 0D 0A 1A 0A) | Обязательный | 8 байт |
| IHDR | Image Header | Основная информация об изображении (ширина/высота/глубина цвета/тип цвета) | Обязательный | 25 байт |
| IDAT | Image Data | Сжатые данные пикселей (кодирование DEFLATE) | Обязательный | Переменный (основной) |
| IEND | Image End | Маркер конца файла | Обязательный | 12 байт |
| PLTE | Palette | Палитра (режим индексированного цвета) | Обязательный для индексированного цвета | ≤768 байт |
| tRNS | Transparency | Информация о прозрачности | Необязательный | Переменный |
| tEXt | Text | Текстовые метаданные (автор/описание и т.д.) | Необязательный | Переменный |
| gAMA | Image Gamma | Информация о гамма-коррекции | Необязательный | 16 байт |
Самый важный chunk в файле PNG — это IDAT, он хранит данные пикселей после предсказания строк фильтрации и сжатия DEFLATE. Изображение 3000x2000 с 24-битным RGB, исходные данные пикселей около 17.2MB (3000x2000x3 байта), после сжатия PNG часть IDAT может быть всего 0.3-0.5MB. Эффект сжатия в основном зависит от повторяемости содержимого изображения — большие области однотонного цвета имеют самую высокую степень сжатия, фотографии с шумом — самую низкую.
2. Принцип алгоритма DEFLATE: двухэтапное сжатие LZ77+Хаффман
Основной движок сжатия PNG — алгоритм DEFLATE, он состоит из двух этапов: первый этап — словарное сжатие LZ77 устраняет повторяющиеся последовательности, второй этап — кодирование Хаффмана устраняет избыточность кодирования. Оба этапа — это операции без потерь и обратимые, это фундаментальная причина, почему сжатие PNG без потерь.
| Этап | Алгоритм | Принцип | Устраняемая избыточность | Обратимость |
|---|---|---|---|---|
| Первый этап | LZ77 | Поиск повторяющихся последовательностей байтов, замена ссылками (расстояние, длина) | Избыточность повторяющихся последовательностей | Полностью обратим |
| Второй этап | Кодирование Хаффмана | Частые данные — короткие коды, редкие данные — длинные коды | Избыточность кодирования | Полностью обратим |
1. Словарное сжатие LZ77
LZ77 — это алгоритм словарного сжатия на основе "скользящего окна". Он поддерживает скользящее окно (обычно 32KB), в пределах окна ищет самую длинную последовательность байтов, совпадающую с текущей позицией. Если совпадение найдено, заменяет эту последовательность байтов ссылкой (расстояние, длина); если совпадения нет, выводит исходный байт.
Пример: предположим, в данных изображения есть непрерывные белые пиксели (RGB 255,255,255), повторяющиеся 1000 раз. LZ77 найдёт этот повторяющийся шаблон в окне, после записи первого триплета последующие 999 триплетов заменяются ссылкой "вернуться на 3 байта, скопировать 3 байта, повторить 999 раз". 3000 байт исходных данных сжимаются в последовательность из десятка байт ссылок, степень сжатия более 99%.
| Характеристика данных | Эффект сжатия LZ77 | Типичная степень сжатия | Причина |
|---|---|---|---|
| Большие области однотонного цвета | Отличный | 95%+ | Длинные повторяющиеся последовательности, высокая эффективность замены ссылками |
| Горизонтальные градиенты | Хороший | 70%-85% | Шаблоны градиентов могут совпадать |
| Регулярные текстуры | Хороший | 60%-80% | Повторяющиеся текстуры могут быть заменены ссылками |
| Случайный шум | Плохой | 0%-10% | Нет повторяющихся последовательностей для совпадения |
| Естественные фотографии | Плохой | 5%-20% | Большая разница между пикселями, мало совпадений |
2. Кодирование Хаффмана
Данные, выводимые LZ77 (смешанные ссылки и исходные байты), затем проходят кодирование Хаффмана. Основная идея кодирования Хаффмана: часто встречающиеся символы используют короткие коды, редкие — длинные коды, тем самым уменьшая среднюю длину кодирования.
Пример: если в выводе LZ77 "маркер ссылки" встречается с частотой 60%, исходное значение байта 255 — 20%, другие значения — по небольшому проценту. Хаффман назначит "маркеру ссылки" 2-битный код, значению 255 — 3-битный код, редким значениям — 8-12-битные коды. Таким образом средняя длина кодирования каждого символа снижается с фиксированных 8 бит до 3-4 бит, дальнейшее сжатие около 50%.
DEFLATE использует два способа кодирования Хаффмана: фиксированное дерево Хаффмана (предустановленная таблица кодирования, высокая скорость, но средняя степень сжатия) и динамическое дерево Хаффмана (построение оптимальной таблицы кодирования на основе фактической частоты данных, более высокая степень сжатия, но требует дополнительного хранения таблицы кодирования). Стандарт PNG требует использования динамического кодирования Хаффмана для достижения наилучшего эффекта сжатия.
3. Механизм сжатия без потерь: фильтрация строк + DEFLATE
Сжатие PNG без потерь зависит не только от алгоритма DEFLATE, но и от ключевого этапа предварительной обработки — предсказания строк фильтрации (Filter). Этот этап выполняется перед DEFLATE, цель — сделать данные пикселей более подходящими для сжатия LZ77.
Соседние пиксели в изображении обычно имеют похожие значения (например, пиксели в области голубого неба близки). Предсказание строк фильтрации путём вычитания значения каждого пикселя из значения его левого или верхнего соседа преобразует абсолютные значения в разности — разности обычно малы или равны нулю, такой шаблон данных более подходит для сжатия LZ77 и Хаффмана.
| Тип фильтрации | Название | Формула предсказания | Применимый сценарий |
|---|---|---|---|
| 0 | None | Без предсказания, исходное значение | Данные с нерегулярным шумом |
| 1 | Sub | Текущее значение - левое значение | Изображения с горизонтальными градиентами |
| 2 | Up | Текущее значение - верхнее значение | Изображения с вертикальными градиентами |
| 3 | Average | Текущее значение - (левое+верхнее)/2 | Изображения с плавными переходами |
| 4 | Paeth | Текущее значение - предсказанное значение Paeth | Универсальное (оптимально для большинства изображений) |
Кодировщик PNG может независимо выбирать тип фильтрации для каждой строки. SmartSlim на основе собственного движка сжатия Rust пробует все 5 способов фильтрации для каждой строки и выбирает тот, который даёт наилучший эффект сжатия, это позволяет дополнительно уменьшить размер на 10%–20% по сравнению с фиксированным использованием одного способа фильтрации.
Полный процесс сжатия:
Исходные пиксели -> Предсказание строк фильтрации (выбор оптимальной фильтрации) -> Словарное сжатие LZ77 -> Кодирование Хаффмана -> Блок данных IDAT
Процесс распаковки полностью обратный:
Блок данных IDAT -> Декодирование Хаффмана -> Распаковка LZ77 -> Обратная фильтрация -> Исходные пиксели
Оба этапа — точные математические обратные операции, данные пикселей после распаковки побайтово идентичны исходным данным, это фундаментальная гарантия того, что PNG без потерь.
4. Практическое сравнение: PNG vs JPEG vs WebP по размеру
Мы сравниваем эффект сжатия трёх форматов на одном и том же наборе тестовых изображений, охватывающих разные типы содержимого.
| Тип изображения | Размер | Исходный BMP | PNG | JPEG(q80) | WebP(q80) | Степень сжатия PNG |
|---|---|---|---|---|---|---|
| Скриншот UI | 1920x1080 | 5.93MB | 0.35MB | 0.82MB | 0.28MB | 94.1% |
| Схема | 2000x1500 | 8.58MB | 0.42MB | 1.15MB | 0.35MB | 95.1% |
| Естественная фотография | 3000x2000 | 17.16MB | 12.50MB | 1.80MB | 1.42MB | 27.2% |
| Портретная фотография | 4000x3000 | 34.33MB | 28.80MB | 3.50MB | 2.80MB | 16.1% |
| Набор иконок | 1024x1024 | 3.00MB | 0.08MB | 0.45MB | 0.06MB | 97.3% |
| Сканированный документ | 2480x3508 | 24.80MB | 1.20MB | 0.85MB | 0.72MB | 95.2% |
Практические данные раскрывают ключевой вывод: эффект сжатия PNG сильно зависит от типа изображения. Для скриншотов UI, схем, иконок с большими областями однотонного цвета степень сжатия PNG достигает 94%–97%, значительно превышая JPEG. Но для естественных фотографий, портретов с большой разницей между пикселями степень сжатия PNG составляет только 16%–27%, значительно уступая JPEG с 89%–90%.
Далее сравнение до и после оптимизации PNG, на примере стандартного PNG и оптимизированного PNG:
| Тип изображения | Стандартный PNG | Оптимизированный PNG | Снижение после оптимизации | Способ оптимизации |
|---|---|---|---|---|
| Скриншот UI | 0.42MB | 0.35MB | 16.7% | Фильтрация Paeth + максимальный уровень zlib |
| Схема | 0.52MB | 0.42MB | 19.2% | Построчная оптимальная фильтрация + удаление метаданных |
| Набор иконок | 0.12MB | 0.08MB | 33.3% | Преобразование в 8-битный индексированный цвет + оптимизация фильтрации |
| Сканированный документ | 1.50MB | 1.20MB | 20.0% | Построчная оптимальная фильтрация + удаление gAMA |
Оптимизация PNG в SmartSlim может уменьшить размер ещё на 15%–33% по сравнению со стандартным PNG, ключевой момент — комбинация построчного выбора оптимальной фильтрации и максимального уровня сжатия zlib.
Больше сравнений форматов можно найти в Сжатие без потерь vs сжатие с потерями: ключевые различия и Сравнение форматов WebP vs PNG vs JPG.
5. Часто задаваемые вопросы FAQ
Q1: Почему PNG — это сжатие без потерь?
PNG использует алгоритм DEFLATE для сжатия данных, который состоит из двух этапов: словарное сжатие LZ77 и кодирование Хаффмана. LZ77 ищет повторяющиеся последовательности байтов и заменяет их ссылками расстояние+длина, Хаффман использует коды переменной длины, позволяя часто встречающимся данным использовать короткие коды. Оба этапа обратимы — при распаковке декодирование Хаффмана восстанавливает коды переменной длины, LZ77 по ссылкам восстанавливает исходные байты, данные полностью идентичны без потери какой-либо информации, поэтому PNG — это сжатие без потерь.
Q2: У PNG или JPEG выше степень сжатия?
Для фотографий степень сжатия JPEG значительно выше, чем PNG. Фотография 3000x2000: PNG около 12.5MB, JPEG качество 80 около 1.8MB, разница в 7 раз. Потому что JPEG использует сжатие с потерями DCT, отбрасывая высокочастотные детали, а PNG должен без потерь сохранять каждый пиксель. Но для схем, скриншотов, иконок с большими областями однотонного цвета PNG наоборот меньше — скриншот UI: PNG 0.3MB, JPEG качество 80 около 0.8MB. Выбор формата зависит от типа содержимого.
Q3: Какова максимальная степень сжатия PNG?
Зависит от содержимого изображения. Изображения с большими областями однотонного цвета или градиентов могут иметь степень сжатия более 90% (например, скриншот UI с 5MB до 0.3MB); фотографии с большим количеством шума обычно имеют степень сжатия только 10%-30%, потому что большая разница между пикселями, LZ77 не может найти повторяющиеся последовательности. Теоретический предел PNG с алгоритмом DEFLATE примерно на уровне сжатия ZIP, невозможно получить такую высокую степень сжатия, как JPEG, путём отбрасывания информации.
Q4: В чём разница между оптимизацией PNG и сжатием PNG?
Сжатие PNG означает кодирование исходных данных пикселей с помощью DEFLATE в формат PNG, это стандартный процесс. Оптимизация PNG — это дальнейшее уменьшение размера на основе стандартного сжатия, включая: попытку 5 видов предсказания строк фильтрации и выбор оптимального, использование максимального уровня сжатия zlib, удаление метаданных chunk (например, tEXt/gAMA), преобразование 24-битного RGBA в 8-битный индексированный цвет (если цветов ≤256). Оптимизация PNG в SmartSlim может уменьшить размер ещё на 15%-30% по сравнению со стандартным PNG.
Заключение
PNG может обеспечить сжатие без потерь, ключевой момент в том, что оба этапа алгоритма DEFLATE, LZ77 и Хаффман, — это полностью обратимые математические операции, плюс предварительная обработка предсказанием строк фильтрации повышает сжимаемость данных. PNG показывает отличный эффект сжатия для скриншотов UI, схем, иконок с большими областями однотонного цвета (степень сжатия 94%–97%), но для фотографий степень сжатия ограничена (16%–27%), в этом сценарии следует выбрать JPEG или WebP.
Если вам нужно оптимизировать размер PNG-изображений, SmartSlim на основе движка сжатия Rust предоставляет построчную оптимальную фильтрацию и максимальный уровень сжатия zlib, уменьшая размер ещё на 15%–33% по сравнению со стандартным PNG, поддерживает 9 форматов изображений png/jpg/jpeg/webp/bmp/tiff, локальное сжатие без передачи данных.
Связанные рекомендации
Нужно сжать файлы? Попробуйте SmartSlim
Основан на собственном движке сжатия Rust, поддерживает 10 основных категорий и более 40 форматов, включая PDF/изображения/видео/Office/OFD, локальное сжатие без передачи данных.