PNG - это комбинация Filters + LZ77 + Huffman (комбинация LZ77 + Huffman называется Deflate) в следующем порядке:
шаг 1) если фильтр отличается от None, значения пикселей заменяются на разницу с соседними пикселями (подробнее см. http://www.libpng.org/pub/png/book/chapter09.html ). , Это увеличивает сжатие изображений с градиентами (поэтому ... 4 5 6 7 становится ... 1 1 1 1), и это может помочь в областях того же цвета (... 3 3 3 5 5 5 5 5 становится 0 0 0 2 0 0 0 0 0). По умолчанию фильтры включены в 24-битные изображения и отключены в 8-битных изображениях с палитрой.
шаг 2) данные сжимаются с помощью LZ77, который заменяет повторяющиеся (совпадающие) строки байтов кортежем, содержащим расстояние до совпадения и длину совпадения.
шаг 3) результат шага 2 кодируется кодом Хаффмана, который заменяет символы фиксированной длины на коды переменной длины, чем чаще встречается символ, тем короче код.
Есть несколько проблем:
Небольшое изменение, затрагивающее несколько пикселей, приведет к изменениям в результатах трех шагов сжатия png:
1) Отфильтрованное значение соседних пикселей изменится (в зависимости от используемого фильтра). Это усилит последствия небольших изменений.
2) Изменение будет означать, что совпадения с этой областью будут другими. Например, изменение 333333 на 333533 приводит к тому, что другое вхождение 333333 больше не будет совпадать, поэтому он выберет другое соответствие 333333 с другим расстоянием или выберет то же совпадение, но с более короткой длиной, а затем другое совпадение для последних 3 байтов. Само по себе это сильно изменит результаты.
3) Самая большая проблема заключается в шаге 3. Код Хаффмана использует переменное число битов, поэтому даже небольшое изменение приведет к тому, что все последующее больше не будет выровнено. AFAIK Большинство алгоритмов сжатия не могут обнаружить совпадения, которые не выровнены по байтам, что предотвратит (или, по крайней мере, значительно сократит) сжатие уже сжатых данных, следующих за изменением, если компрессор не сможет обнаружить совпадения, которые не выровнены по байту.
Другие вопросы уже освещены в других ответах:
4) Gzip использует тот же алгоритм Deflate со словарем 32 КБ, поэтому, если файлы png больше 32 КБ, совпадения не будут обнаружены, даже если они идентичны. Bzip2 лучше в этом аспекте, поскольку он использует блок 900 КБ. XZ использует LZMA, в котором IIRC имеет словарь 4 МБ с уровнем сжатия по умолчанию. 5) Формат Zip не использует сплошное сжатие, поэтому он не будет сжимать аналогичные или идентичные файлы лучше.
Возможно, компрессоры из семейства PAQ или PPMD будут сжимать лучше, но если вам нужно сжать множество похожих файлов изображений, вы можете рассмотреть 3 подхода:
1) Храните изображения без сжатия (с PNG-0 или в формате без сжатия) и сжимайте с помощью компрессора с большим словарем или размером блока. (LZMA будет хорошо работать)
2) Другой вариант - сохранить фильтры, но удалить сжатие Deflate из PNG. Это можно сделать, например, с помощью утилиты ( AdvDef ). Затем вы сжимаете получившиеся несжатые PNG. После распаковки вы можете сохранить несжатый PNG или снова сжать их с помощью AdvDef (но это займет время).
Вам нужно протестировать оба подхода, чтобы увидеть, какие компрессии наиболее эффективны.
3) Последним вариантом будет преобразование PNG-изображений в видео, сжатие его с помощью видео-компрессора без потерь, такого как x264 без потерь (с особой заботой об использовании правильного цветового формата), а затем при извлечении извлекайте кадры в отдельные PNG-изображения. Это можно сделать с помощью ffmpeg. Вам также необходимо сохранить соответствие между номером кадра и исходным именем.
Это был бы самый сложный подход, но если все png являются частью анимации, это может быть наиболее эффективным. Однако вам понадобится видео формат, который поддерживает прозрачность, если вам это нужно.
Изменить: Существует также формат MNG, если бы он не использовался часто.