Я просто наткнулся на следующее: я положил несколько одинаковых копий png-изображения в папку, а затем попытался сжать эту папку следующими способами:
tar czf folder.tar.gz folder/
tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz
(это хорошо работает для идентичных изображений, однако для похожих изображений усиление равно нулю)zip -r folder.zip folder/
Когда я проверил размер самого .tar.gz
, .tar.xz
, .zip
я понял , что это почти так же , как один из folder/
.
Я понимаю, что само изображение PNG может иметь высокий уровень сжатия и, следовательно, не может быть сжато дальше. Однако при объединении многих похожих (в данном случае даже идентичных) изображений png в архив и последующем сжатии архива, я ожидаю, что требуемый размер заметно уменьшится. В случае идентичных изображений я бы ожидал размер, примерно равный размеру одного изображения.
data-compression
Гость
источник
источник
.bmp
), файл tar.gz должен иметь возможность воспользоваться сходством. (По крайней мере, если сходство много идентичных пикселей)Ответы:
Посмотрите, как работают алгоритмы сжатия. По крайней мере, те, кто в семействе Лемпель-Зив (
gzip
использует LZ77 , по-zip
видимому, в основном тоже , иxz
использует LZMA ) сжимают несколько локально : сходства, которые находятся далеко друг от друга, не могут быть идентифицированы.Детали отличаются между методами, но суть в том, что к тому времени, когда алгоритм достигает второго изображения, он уже «забыл» начало первого. И так далее.
Вы можете попробовать вручную изменить параметры метода сжатия; если размер окна (LZ77) соотв. Размер блока / чанка (более поздние методы) по меньшей мере равен двум изображениям, и вы, вероятно, увидите дальнейшее сжатие.
Обратите внимание, что вышеприведенное действительно применимо, только если у вас есть идентичные изображения или почти идентичные несжатые изображения. Если есть различия, сжатые изображения могут не выглядеть похожими в памяти. Я не знаю, как работает сжатие PNG; Вы можете проверить шестнадцатеричные представления изображений, которые у вас есть для общих подстрок вручную.
Также обратите внимание, что даже с измененными параметрами и избыточностью, которую вы можете использовать, вы не получите размер одного изображения. Большие словари означают больший размер кодового слова, и даже если два изображения точно идентичны, вам, возможно, придется кодировать второе, используя несколько кодовых слов (которые указывают на первое).
источник
Почему это происходит? Здесь на самом деле происходит два разных эффекта:
Каждый файл сжимается независимо. Некоторые архивные программы, в том числе zip, сжимают каждый файл независимо, без памяти из одного файла в другой файл. Другими словами, каждый файл сжимается отдельно, а затем сжатые файлы объединяются в архив.
Краткосрочная память. Некоторые архивные программы могут использовать информацию об одном файле для лучшего сжатия следующего файла. Они эффективно объединяют файлы, а затем сжимают результат. Это улучшение.
Смотрите также ответ Наюки для более подробного обсуждения этого.
Однако есть вторая проблема. Некоторые схемы сжатия, включая zip, gzip и bzip2, имеют ограниченную память. Они сжимают данные на лету и запоминают последние 32 КБ данных, но ничего не помнят о данных, которые произошли намного раньше в файле. Другими словами, они не могут найти дублированные данные, если дубликаты встречаются на расстоянии более 32 КБ. В результате, если идентичные файлы короткие (короче, чем около 32 КБ), алгоритм сжатия может удалить дублирующиеся данные, но если идентичные файлы имеют длинную длину, алгоритм сжатия скрывается и становится бесполезным: он не может обнаружить любой из дубликат в ваших данных. (Bzip запоминает данные за последние 900 КБ или около того, вместо 32 КБ.)
Все стандартные алгоритмы сжатия имеют некоторый максимальный объем памяти, сверх которого они не могут обнаружить шаблоны ... но для некоторых это число намного больше, чем для других. Для Bzip это что-то вроде 900KB. Для xz это что-то вроде 8 МБ (с настройками по умолчанию). Для 7z это что-то вроде 2ГБ. 2 ГБ более чем достаточно для распознавания дублированных копий файлов PNG (которые обычно намного меньше 2 ГБ). Кроме того, 7z также старается уметь размещать файлы, которые могут быть похожи друг на друга, в архиве, чтобы помочь компрессору работать лучше; Тар ничего не знает об этом.
Смотрите также ответ Рафаэля и ответ Nayuki в для более подробного объяснения этого эффекта.
Как это относится к вашим настройкам. Для вашего конкретного примера вы работаете с изображениями PNG. Сами изображения PNG сжимаются, поэтому вы можете рассматривать каждый файл PNG как последовательность произвольно выглядящих байтов без шаблонов или дублирования в файле. Там нет ничего для компрессора, чтобы использовать, если он смотрит на одно изображение PNG. Таким образом, если вы попытаетесь сжать один файл PNG (или создать архив zip / tar / ..., содержащий только один файл PNG), вы не получите никакого сжатия.
Теперь давайте посмотрим, что произойдет, если вы попытаетесь сохранить несколько копий одного и того же файла PNG:
Маленькие файлы. Если файл PNG очень маленький, то все, кроме zip, будет отлично работать. Zip эффектно потерпит неудачу: он сжимает каждый файл независимо, поэтому у него нет шансов обнаружить избыточность / дублирование между файлами. Более того, поскольку он пытается сжать каждый файл PNG, он не достигает сжатия; размер почтового архива будет огромным. Напротив, размер архива tar (сжатого с помощью gzip, bzip2 или xz) и архива 7z будет небольшим, поскольку он в основном хранит одну копию файла, а затем замечает, что все остальные идентичны - это выгодно от сохранения памяти из одного файла в другой.
Большие файлы. Если файл PNG большой, то хорошо работает только 7z. В частности, почтовый индекс продолжает эффектно проваливаться. Также tar.zip и tar.bzip2 терпят неудачу, так как размер файла больше, чем окно памяти компрессора: поскольку компрессор видит первую копию файла, он не может сжать ее (так как он уже был сжат ); к тому времени, когда он начинает видеть начало второй копии файла, он уже забыл последовательности байтов, видимых в начале первого файла, и не может установить соединение, что эти данные на самом деле являются дубликатами.
В отличие от них tar.xz и 7z продолжают успешно работать с несколькими копиями большого файла PNG. Они не имеют ограничения «малого объема памяти» и могут заметить, что вторая копия файла идентична первой, поэтому нет необходимости хранить ее во второй раз.
Что вы можете сделать по этому поводу. Используйте 7z. У него есть набор эвристик, которые помогут обнаружить идентичные или похожие файлы и действительно хорошо сжать в этом случае. Вы также можете посмотреть на lrzip со сжатием lzop.
Откуда я знаю? Я смог убедиться в этом, попробовав несколько экспериментов со 100 копиями файла, содержащего случайные байты. Я попробовал 100 копий файла размером 4 КБ, 100 копий файла объемом 1 МБ и 100 копий файла размером 16 МБ. Вот что я нашел:
Как видите, почтовый индекс ужасен независимо от того, насколько мал ваш файл. 7z и xz оба хороши, если ваши изображения не слишком велики (но xz будет хрупким и зависит от порядка, в котором изображения помещаются в архив, если у вас есть несколько дубликатов и несколько недубликатов, смешанных вместе). 7z чертовски хорош, даже для больших файлов.
Ссылки. Это также хорошо объясняется в куче постов в Super User. Взглянем:
источник
tar
их затем сжатьxz
(что очень хорошо работало для идентичных изображений), однако в случае похожих изображений усиление равно нулю. Я попробовал 71 изображение, каждое размером ~ 831 КБ.Во-первых, обратите внимание, что формат изображения PNG - это в основном необработанные пиксели RGB (с небольшой фильтрацией света), проталкиваемые через формат сжатия DEFLATE. Вообще говоря, сжатые файлы (PNG, JPEG, MP3 и т. Д.) Не получат никакой выгоды от повторного сжатия. Поэтому для практических целей мы можем рассматривать ваш файл PNG как несжимаемые случайные данные до конца эксперимента.
Во-вторых, обратите внимание, что форматы ZIP и gzip также используют кодек DEFLATE. (Это объясняет, почему сжатие по сравнению с сжатием одного файла приведет к практически одинаковому размеру вывода.)
Теперь позвольте мне прокомментировать каждый тест в отдельности:
tar czf folder.tar.gz folder/
Это создает (несжатый) файл TAR, который объединяет все ваши идентичные файлы PNG (с небольшим количеством добавленных метаданных и отступов). Затем этот единственный файл отправляется через компрессор gzip для создания одного сжатого выходного файла.
К сожалению, формат DEFLATE поддерживает только окно словаря LZ77 размером 32768 байт. Таким образом, даже несмотря на то, что TAR содержит повторяющиеся данные, если размер файла PNG превышает 32 КиБ, то компрессор DEFLATE наверняка не сможет запомнить данные достаточно далеко назад, чтобы воспользоваться тем фактом, что идентичные данные повторяются.
С другой стороны, если вы попытаетесь повторить этот эксперимент с, скажем, 20-килограммовым PNG-файлом, дублированным 10 раз, то весьма вероятно, что вы получите gzip-файл, только немного превышающий 20 КБ.
tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz
Это создает файл TAR, как и прежде, а затем использует формат xz и компрессор LZMA / LZMA2. Я не мог найти информацию о LZMA в этой ситуации, но из 7-Zip для Windows я знаю, что он может поддерживать большие размеры окна словаря (например, 64 МБ). Таким образом, вполне возможно, что вы использовали неоптимальные настройки и кодек LZMA мог бы уменьшить файл TAR до размера только одного файла PNG.
zip -r folder.zip folder/
Формат ZIP не поддерживает «сплошные» архивы; то есть каждый файл сжимается независимо. Мы предполагали, что каждый файл несжимаемый. Следовательно, тот факт, что каждый файл идентичен, не может быть использован, и ZIP-файл будет таким же большим, как прямая конкатенация всех файлов.
источник
xz
по умолчанию работает вxz -6
режиме, в котором используется словарь 8 MiB LZMA2 . Я не смог сразу найти на странице руководства, доступной в моей системе Debian, размер окна по умолчанию для компрессора.tar czf folder.tar.gz folder/ && xz --stdout folder.tar.gz > folder.tar.gz.xz
без какого-либо эффекта (что имеет смысл согласно тому, что вы объяснили). Я думаю, что я немного потерял во всех этих вещах сжатия: D При использованииtar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz
я на самом деле получаю чуть больше, чем размер одного изображения (что также имеет смысл в соответствии с размером окна dict по умолчанию 64 МиБ). Я обновил свой вопрос соответственно. Благодарность!tar -> gzip -> xz
, что gzip DEFLATE может сжимать каждую копию данных PNG по-своему, поэтому xz не сможет обнаружить избыточность.Проблема в том, что (большинству) схем сжатия не хватает знаний о ваших данных. Даже если вы распакуете ваши PNG в растровые изображения и сожмете их в архиве, вы не получите (значительно) меньших результатов.
В случае многих похожих изображений подходящей схемой сжатия будет видеокодек.
Используя кодирование без потерь, вы должны достичь почти идеального результата сжатия, который вы ожидаете.
Если вы хотите проверить это, используйте что-то вроде этого:
https://trac.ffmpeg.org/wiki/Create%20a%20video%20slideshow%20from%20images
источник
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, если бы он не использовался часто.
источник
Когда у вас есть специальные наборы данных, вы используете специальные алгоритмы, а не многофункциональные инструменты.
Ответ в том, что выбранные вами сжатия без потерь не созданы для того, что вы делаете. Никто не ожидает, что вы сожмете одно и то же изображение дважды, и даже если вы сделаете это (случайно), проверяя все предыдущие входные данные, вы получите алгоритм O (n ^ 2) (возможно, немного лучше, но наивный подход по крайней мере будет n ^ 2).
Большинство ваших программ сжатия, которые вы тестировали на O (n), подчеркивают скорость по сравнению с оптимальной степенью сжатия. Никто не хочет запускать свой компьютер в течение 5 часов, чтобы сэкономить несколько мегабайт, особенно в наши дни. Для больших входных данных все, что выше O (n), становится проблемой времени выполнения.
Другая проблема - это баран. Вы не можете получить доступ к каждой части вашего ввода в любой момент времени, когда он становится достаточно большим. Даже игнорируя это, большинство людей не хотят отказываться от всего своего барана или процессора, чтобы просто сжать что-то.
Если в ваших файлах есть шаблоны, которые вы хотите сжать, вам придется выполнить над ними ручные операции, написать собственное сжатие или потенциально использовать сжатие типа «архив» (nano). Сжатие для длительного хранения, слишком медленное для повседневного использования.
Другой вариант - сжатие видео без потерь.
источник
Формат файла PNG уже использует алгоритм сжатия DEFLATE внутри. Это тот же алгоритм, который используется в xz, gzip и zip - только в некоторых вариантах.
tar.gz
иtar.xz
воспользоваться преимуществами сходства между файлами, чегоzip
нет.Таким образом, на самом деле вы выполняете сжатие DEFLATE поверх сжатых файлов DEFLATE - вот почему файлы сохраняют практически исходный размер.
bzip2
Программа (также родственный алгоритм) лучше , когда дело доходит до (почти) идентичных файлов.источник
bzip2
ловит его:tar -cjf archive.tar.bz2 *.png
. Обновлено в моем ответе.