Как PNG без потерь, учитывая, что у него есть параметр сжатия?

157

Говорят, что файлы PNG используют сжатие без потерь. Однако всякий раз, когда я нахожусь в редакторе изображений, таком как GIMP, и пытаюсь сохранить изображение в виде файла PNG, он запрашивает параметр сжатия, который находится в диапазоне от 0 до 9. Если он имеет параметр сжатия, который влияет на визуальную точность сжатое изображение, как это делает PNG без потерь?

Я получаю поведение без потерь, только когда я установил параметр сжатия на 9?

pkout
источник
40
Большинство алгоритмов сжатия без потерь имеют настраиваемые параметры (например, размер словаря), которые обобщаются в ползунке «сколько усилий нужно приложить для минимизации выходного размера». Это действительно для ZIP, GZip, BZip2, LZMA, ...
Даниэль Б
20
Вопрос можно сформулировать по-другому. Если при сжатии качество не теряется, то почему бы не использовать сжатие с наименьшим размером? Тогда ответ будет, потому что для сжатия и распаковки требуется больше оперативной памяти и больше процессорного времени. Иногда вам нужно более быстрое сжатие, и вам не важна степень сжатия.
Касперд
14
Сжатие PNG практически идентично ZIP-файлам. Вы можете сжать их более или менее, но вы получите точный файл обратно, когда он распаковывается - вот что делает его без потерь.
mikebabcock
13
Большинство программ сжатия, таких как Zip и Rar, позволяют вводить «уровень сжатия», который позволяет выбирать между меньшим файлом <-> и более коротким временем. Это не означает, что эти программы сбрасывают данные во время сжатия. Этот параметр (в GIMP, pngcrush и т. Д.) Аналогичен.
Салман А
2
@naxa: Нет никаких предостережений в отношении того, насколько png на самом деле без потерь. Это всегда на 100% без потерь. Статья только предупреждает вас об ошибках, которые были в некоторых старых браузерах в реализации PNG для обработки гамма-коррекции. И это имеет смысл только в том случае, если вам нужно сопоставить цвет с цветами CSS (которые не корректируются гаммой).
Паули Л

Ответы:

184

PNG без потерь. GIMP, скорее всего, просто не использует лучшее слово в этом случае. Думайте об этом как о «качестве сжатия», или, другими словами, «уровне сжатия». При более низком сжатии вы получаете файл большего размера, но для его создания требуется меньше времени, тогда как при более высоком сжатии вы получаете файл меньшего размера, для создания которого требуется больше времени. Как правило, вы получаете убывающую отдачу (т. Е. Не столь значительное уменьшение размера по сравнению с увеличением времени, которое требуется) при переходе на самые высокие уровни сжатия, но это зависит от вас.

jjlin
источник
42
Кроме того, сжатие PNG на самом деле имеет много настраиваемых параметров, где настройки в любом направлении могут уменьшить размер вывода в зависимости от содержимого источника - это гораздо сложнее, чем простой «лучше» и «хуже» ползунок. Для общих целей это не слишком важно, но если вы хотите абсолютное наименьшее, используйте такой инструмент, pngcrushкоторый может сравнить множество вариантов для наименьшего возможного.
Боб
4
Более высокий уровень сжатия увеличивает время сжатия, но влияет ли это также на декомпрессию ?
Нолонар
10
@Nolonar Обычно нет; в противном случае более высокий уровень сжатия обычно уменьшает время декомпрессии, потому что для этого требуется меньше данных для чтения и обработки. Более длительное время сжатия связано с более тщательным поиском шаблонов для сжатия (упрощение).
пушистый
1
В ответе @fluffy LordNeckbeard самая высокая степень сжатия занимает в 5 раз больше времени, чем самая низкая.
Андре Шалелла
1
Для PNG, это является довольно распространенным явлением , чтобы иметь больше времени декомпрессии для более сжатых файлов. Проблема в том, что с PNG один из возможных приемов - применять алгоритм сжатия снова и снова, пока файл становится меньше. Как только размер увеличивается, вы перестаете его применять. Поэтому вполне возможно, что вы применяете алгоритм сжатия 5 или 6 раз, что означает, что вам нужно распаковать файл 5 или 6 раз, чтобы отобразить изображение.
'
213

PNG сжат, но без потерь

Уровень сжатия представляет собой компромисс между размером файла и скоростью кодирования / декодирования. Чтобы чрезмерно обобщить, даже неформатные форматы, такие как FLAC, имеют схожие концепции.

Различные уровни сжатия, один и тот же декодированный выход

Хотя размеры файлов различны, из-за разных уровней сжатия фактический декодированный вывод будет идентичным.

Вы можете сравнить MD5 хэши декодированных выходов с ffmpegиспользованием MD5 muxer .

Лучше всего это показать на нескольких примерах:

Создать PNG-файлы:

$ ffmpeg -i input -vframes 1 -compression_level 0 0.png
$ ffmpeg -i input -vframes 1 -compression_level 100 100.png
  • По умолчанию ffmpegбудет использовать -compression_level 100для вывода PNG.

Сравнить размер файла:

$ du -h *.png
  228K    0.png
  4.0K    100.png

Расшифруйте файлы PNG и покажите хеши MD5:

$ ffmpeg -loglevel error -i 0.png -f md5 -
3d3fbccf770a51f9d81725d4e0539f83

$ ffmpeg -loglevel error -i 100.png -f md5 -
3d3fbccf770a51f9d81725d4e0539f83

Поскольку оба хэша одинаковы, вы можете быть уверены, что декодированные выходы (несжатое видео) одинаковы.

llogan
источник
26
+1 не знал, что ffmpeg может обрабатывать png.
Лекенштейн
21
@Lekensteyn Отлично подходит для создания скриншотов . Пример, чтобы пропустить 30 секунд и сделать снимок экрана: ffmpeg -ss 30 -i input -vframes 1 output.pngтакже хорошо для создания видео из изображений и наоборот.
Llogan
Означает ли это, что PNG нужно распаковывать каждый раз, когда его нужно рендерить? Потому что, если это правда, мы должны быть
akshay2000
Если вы перечитываете файл с диска или из кэша, да, он должен быть распакован. Внутри той же страницы кеш, вероятно, может повторно использовать распакованную версию.
Дэвид Мартенссон,
1
@ akshay2000 Зависит от того, как работает программа, которая отображает PNG. Обычно файл читается с диска, распаковывается и буферизируется в оперативной памяти. Так что, пока он находится в оперативной памяти, ему не нужно снова распаковывать образ.
xZise
24

Сжатие PNG происходит в два этапа.

  1. Предварительное сжатие переупорядочивает данные изображения так, чтобы они были более сжимаемыми с помощью алгоритма сжатия общего назначения.
  2. Фактическое сжатие выполняется DEFLATE, который ищет и устраняет дублирующиеся последовательности байтов, заменяя их короткими токенами.

Поскольку шаг 2 требует очень много времени / ресурсов, базовая библиотека zlib (инкапсуляция необработанного DEFLATE) принимает параметр сжатия в диапазоне от 1 = быстрое сжатие, 9 = наилучшее сжатие, 0 = отсутствие сжатия. Отсюда и диапазон 0-9, и GIMP просто передает этот параметр в zlib. Обратите внимание, что на уровне 0 ваш png будет немного больше, чем эквивалентное растровое изображение.

Тем не менее, 9-й уровень - это только «лучшее», которое попытается использовать zlib, и все еще остается компромиссным решением .
Чтобы действительно почувствовать это, если вы готовы потратить в 1000 раз больше вычислительной мощности на исчерпывающий поиск, вы можете увеличить плотность данных на 3-8%, используя zopfli вместо zlib.
Сжатие по-прежнему без потерь, это просто более оптимальное представление данных DEFLATE. Это приближается к пределам zlib-совместимых библиотек и, следовательно, является истинным «лучшим» сжатием, которого можно достичь с помощью PNG.

Adria
источник
2
Примечание. Время распаковки одинаково независимо от уровня сжатия или числа итераций при использовании zopflipng.
Адрия
16

Основной мотивацией для формата PNG было создание замены для GIF, которая была бы не только бесплатной, но и улучшала ее по существу во всех отношениях. В результате сжатие PNG полностью без потерь, то есть исходные данные изображения могут быть восстановлены точно, бит за битом - так же, как в GIF и большинстве форм TIFF.

PNG использует двухэтапный процесс сжатия:

  1. Предварительное сжатие: фильтрация (прогноз)
  2. Сжатие: DEFLATE (см. Википедию )

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

В качестве простого примера рассмотрим последовательность байтов, равномерно увеличивающуюся от 1 до 255:

1, 2, 3, 4, 5, .... 255

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

1, 1, 1, 1, 1, .... 1

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

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

образ

Алгоритм работает с байтами, но для больших пикселей (например, 24-битного RGB или 64-битного RGBA) сравниваются только соответствующие байты, то есть красные компоненты цветов пикселей обрабатываются отдельно от зеленого и синего компонентов пикселей.

Чтобы выбрать лучший фильтр для каждой строки, кодировщик должен проверить все возможные комбинации. Это явно невозможно, так как даже 20-строчное изображение потребовало бы тестирования более 95 триллионов комбинаций, где «тестирование» включало бы фильтрацию и сжатие всего изображения.

Уровни сжатия обычно определяются как числа от 0 (нет) до 9 (наилучшее). Они относятся к компромиссам между скоростью и размером и относятся к тому, сколько комбинаций фильтров строк нужно попробовать. Нет никаких стандартов относительно этих уровней сжатия, поэтому у каждого графического редактора могут быть свои собственные алгоритмы относительно того, сколько фильтров использовать при оптимизации размера изображения.

Уровень сжатия 0 означает, что фильтры вообще не используются, что быстро, но расточительно. Более высокие уровни означают, что в строках изображений пробуется все больше и больше комбинаций, и сохраняются только лучшие.

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

В дополнение к фильтрам уровень сжатия может также влиять на уровень сжатия zlib, который представляет собой число от 0 (без Deflate) до 9 (максимальное Deflate). То, как указанные уровни 0-9 влияют на использование фильтров, которые являются основной функцией оптимизации PNG, все еще зависит от разработчика инструмента.

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

Источники:

Wikipedia Portable Network Graphics
документация libpng Глава 9 - Сжатие и фильтрация

harrymc
источник
1
Я не думаю, что настройка уровня сжатия меняет использование фильтров. Настройка уровня 1-9, вероятно, просто выбирает уровень сжатия zlib 1-9, а уровень 0 означает, что алгоритм дефляции вообще не используется. Большинство реализаций, вероятно, не изменяют фильтры для каждой строки, а просто используют фильтр Path все время.
Паули Л
@PauliL: Я не согласен, потому что во всех сравнениях программного обеспечения для сжатия PNG существуют очень большие различия между размерами генерируемых изображений. Если все продукты использовали одинаковые параметры для одной и той же библиотеки, то все размеры должны быть одинаковыми, как и скорость.
harrymc
Есть ли у вас ссылки на такие сравнения?
Паули Л
@PauliL: быстрый поиск показал это сравнение .
harrymc
@PauliL: Вы, вероятно, правы, что уровни сжатия zlib зависят от уровней сжатия PNG. Я соответственно изменил свой ответ, хотя ни один инструмент сжатия не документирует, что именно он делает. Возможно, объяснение для инструментов с наихудшими размерами в том, что они вообще не используют фильтры, только сжатие zlib.
Harrymc
5

Хорошо, я опоздал на награду, но вот мой ответ в любом случае.

PNG всегда без потерь . Он использует алгоритм Deflate / Inflate, аналогичный тем, которые используются в программах zip.

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

Во многих реализациях PNG для сжатия используется библиотека zlib. У Zlib девять уровней сжатия, 1-9. Я не знаю внутренностей Gimp, но так как он имеет настройки уровня сжатия 0-9 (0 = нет сжатия), я бы предположил, что этот параметр просто выбирает уровень сжатия zlib.

Алгоритм Deflate - это алгоритм сжатия общего назначения , он не предназначен для сжатия изображений. В отличие от большинства других форматов файлов изображений без потерь, формат PNG этим не ограничивается. Сжатие PNG использует тот факт, что мы сжимаем 2D-изображение . Это достигается с помощью так называемых фильтров .

(Фильтр на самом деле вводит в заблуждение термин. Он фактически не меняет содержимое изображения, он просто кодирует его по-другому. Более точное название будет дельта-кодировщик.)

Спецификация PNG определяет 5 различных фильтров (в том числе 0 = нет). Фильтр заменяет абсолютные значения пикселей на отличие от предыдущего пикселя влево, вверх, по диагонали или их комбинации. Это может значительно улучшить степень сжатия. Каждая строка сканирования на изображении может использовать разные фильтры. Кодировщик может оптимизировать сжатие, выбирая лучший фильтр для каждой строки.

Подробнее о формате файла PNG см. В разделе « Спецификация PNG» .

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

Программа командной строки pngcrush пробует несколько стратегий, чтобы найти лучший результат. Это может значительно уменьшить размер файла PNG, созданного другими программами, но это может занять довольно много времени на больших изображениях. См. Source Forge - pngcrush .

Паули Л
источник
3

Уровень сжатия в материалах без потерь всегда просто торгует ресурсами кодирования (обычно временем, иногда также оперативной памятью) и битрейтом. Качество всегда на 100%.

Конечно, компрессоры без потерь НИКОГДА не могут гарантировать фактическое сжатие. Случайные данные несжимаемы, шаблонов для поиска нет и сходства нет. Теория информации Шеннона и все такое. Весь смысл сжатия данных без потерь состоит в том, что люди обычно работают с очень неслучайными данными, но для передачи и хранения мы можем сжать их до минимально возможного количества бит. Надеюсь вплоть до максимально приближенной к колмогоровской сложности оригинала.

Будь то общие данные в формате zip или 7z, изображения png, аудио flac или видео h.264 (в режиме без потерь), это одно и то же. При использовании некоторых алгоритмов сжатия, таких как lzma (7zip) и bzip2, запуск настройки сжатия приведет к увеличению времени ЦП DECODER (bzip2) или чаще всего необходимого объема ОЗУ (lzma и bzip2 и h.264 с большим количеством опорных кадров). , Часто декодер должен сохранять больше декодированного вывода в ОЗУ, потому что декодирование следующего байта может ссылаться на байт, декодированный много мегабайт назад (например, видеокадр, который наиболее похож на кадр с полсекунды назад, будет закодирован со ссылками на 12 кадров назад). ). То же самое с bzip2 и выбором большого размера блока, но это также распаковывает медленнее. У lzma есть словарь переменного размера, и вы можете создавать файлы, которые требуют 1.

Питер Кордес
источник
Хм-м-м, я увидел реализацию, позволяющую управлять рычагами шагового двигателя и головки напрямую, чтобы обеспечить гарантированное сжатие без потерь. Манчестерское кодирование легко обойти, если у вас есть источник синхронизации высокого разрешения.
Иисус Навин
@Joshua: Использование физического формата хранения с более высокой плотностью не совпадает со сжатием данных ...
SamB
0

Во-первых, PNG всегда без потерь. Очевидный парадокс связан с тем, что возможны два различных типа сжатия (для любого типа данных): с потерями и без потерь.

Сжатие без потерь сжимает данные (то есть размер файла), используя различные приемы, сохраняя все и не прибегая к каким-либо приближениям. В результате, возможно, что сжатие без потерь вообще не сможет сжимать вещи вообще. (Технически данные с высокой энтропией могут быть очень трудными или даже невозможными для сжатия для методов без потерь.) Сжатие с потерями аппроксимирует реальные данные, но аппроксимация несовершенна, но такое «отбрасывание» точности позволяет обычно лучше сжать.

Вот тривиальный пример сжатия без потерь: если у вас есть изображение, состоящее из 1000 черных пикселей, вместо сохранения значения для черного 1000 раз, вы можете сохранить счетчик (1000) и значение (черный), сжимая таким образом 1000 пикселей ». изображение "всего на два номера. (Это грубая форма метода сжатия без потерь, называемого кодированием по длине прогона).

GregD
источник