• Методы сжатия данных. Методы сжатия информации

    Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

    хорошую работу на сайт">

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

    Размещено на http://www.allbest.ru/

    Сжатие данных

    1. Информация. Её виды и свойства

    В литературе можно найти достаточно много определений термина «информация», отражающих различные подходы к толкованию этого понятия. Толковый словарь русского языка Ожегова приводит 2 определения слова «информация»:

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

    Сообщения, осведомляющие о положении дел, о состоянии чего-нибудь. (Научно-техническая и газетная информации, средства массовой информации - печать, радио, телевидение, кино).

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

    Информация имеет двойственный характер: материальный - она может передаваться, храниться и т.д.; и нематериальный - по сере передачи она может пополняться. Информация не может существовать без своего материального носителя, средства переноса ее в пространстве и во времени. В качестве носителя может выступать непосредственно сам физический объект или его энергетический эквивалент в качестве звуковых, световых, электрических и других сигналов.

    Для этого в настоящее время изобретено множество способов хранения информации на внешних (относительно мозга человека) носителях и ее передачи на огромные расстояния.

    Основные виды информации по ее форме представления, способам ее кодирования и хранения, что имеет наибольшее значение для информатики, это:

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

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

    · текстовая - способ кодирования речи человека специальными символами - буквами, причем разные народы имеют разные языки и используют различные наборы букв для отображения речи; особенно большое значение этот способ приобрел после изобретения бумаги и книгопечатания;

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

    · видеоинформация - способ сохранения «живых» картин окружающего мира, появившийся с изобретением кино.

    Для передачи информации на большие расстояния первоначально использовались кодированные световые сигналы, с изобретением электричества - передача закодированного определенным образом сигнала по проводам, позднее - с использованием радиоволн.

    С появлением компьютеров (или, как их вначале называли в нашей стране, ЭВМ - электронные вычислительные машины) вначале появилось средство для обработки числовой информации. Однако в дальнейшем, особенно после широкого распространения персональных компьютеров (ПК), компьютеры стали использоваться для хранения, обработки, передачи и поиска текстовой, числовой, изобразительной, звуковой и видеоинформации. С момента появления первых персональных компьютеров - ПК (80-е годы 20 века) - до 80% их рабочего времени посвящено работе с текстовой информацией.

    Хранение информации при использовании компьютеров осуществляется на магнитных дисках или лентах, на лазерных дисках (CD и DVD), специальных устройствах энергонезависимой памяти (флэш-память и пр.). Эти методы постоянно совершенствуются, изобретаются новые устройства и носители информации. Обработку информации (воспроизведение, преобразование, передача, запись на внешние носители) выполняет процессор компьютера. С помощью компьютера возможно создание и хранение новой информации любых видов, для чего служат специальные программы, используемые на компьютерах, и устройства ввода информации.

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

    Свойства информации

    Можно привести немало разнообразных свойств информации. Каждая научная дисциплина рассматривает те, которые ей более важны. С точки зрения информатики, наиболее важными представляются следующие свойства:

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

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

    3. Достоверность информации. Данные возникают в момент регистрации сигналов, но не все сигналы являются «полезными» - всегда присутствует уровень посторонних сигналов.

    5. Доступность информации.

    6. Актуальность.

    2. Сжатие данных

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

    С жатие данных - процедура перекодирования данных, производимая с целью уменьшения их объёма. Применяется для более рационального использования устройств хранения и передачи данных. Если методы сжатия информации применяют к готовым документам, то нередко термин «сжатие данных» подменяют термином «архивация данных».

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

    Алгоритмы сжатия текстов / файлов неизвестного формата

    Имеется 2 основных подхода к сжатию файлов неизвестного формата.

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

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

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

    3. Программные средства сжатия данных

    Если методы сжатия информации применяют к готовым документам. То нередко термин «сжатие данных» подменяют термином «архивация данных», а программные средства, выполняющие эти операции, называют архиваторами.

    Архиваторы предназначены для сжатия файлов, т.е. для уменьшения занимаемого ими места на диске. Они позволяют за счет специальных методов упаковки информации сжимать информацию на дисках, создавая копии файлов в один архивный файл. Несмотря на то, что объемы памяти ЭВМ постоянно растут, потребность в архивации не уменьшается.

    Итак, архивация может пригодиться:

    1) При хранении копий файлов и флоппи-дисках, т.к. флоппи-диск ограничен по размеру;

    2) Для освобождения места на жестком диске;

    3) При передачи информации по сети.

    Архивация информации - это такое преобразование информации, при котором ее объем не уменьшается, а количество информации остается прежним.

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

    Степень сжатия информации зависит от типа исходного файла, от используемой программы, а также от выбранного метода упаковки. Наиболее хорошо сжимаются файлы графических объектов, текстовые файлы и файлы данных, для которых степень сжатия может достигать 5-40%, меньше сжимаются файлы исполняемых программ и загрузочных модулей -60-90%.

    Различными разработчиками созданы много программ-архиваторов. Среди них наиболее распространенные для Windows - WINRAR, WINZIP.

    По своей популярности архиватор WinRAR, без сомнения, находится на первом месте в России, и на одном из первых - во всем мире. Архиватор был разработан Евгением Рошалом в 2003 году. Программа обеспечивает полное управление файлами в архивах, восстановление поврежденных архивов, шифрование, создание самораспаковывающихся и многотомных архивов.

    WinZip - одна из самых популярных в Интернете программ, собравшая значительное число наград самых различных компьютерных изданий во всех концах мира.

    Сам Zip - алгоритм свободно используется в десятках программ, тем не менее для очень многих пользователей Windows ИМЕННО WinZip является стандартной программой для работы с архивами. Встроенные средства обработки архивов WinZIP позволяют упаковывать, просматривать и извлекать файлы из широко распространенных форматов архивов, таких как ZIP, CAB, Microsoft Compress, GZIP, TAR и т.д. WinZip очень прост и удобен в работе.

    Однако не всегда оправдано использовать отдельные архиваторы с их собственными графическими оболочками. Наиболее удобной оболочкой для архиваторов является обычный файловый менеджер, например, Windows Commander, который имеет возможность просматривать и распаковывaть файлы архивов форматов ZTP, ARJ, RAR, TAR, GZ, CAB, ACE. Всё-таки большинство операций с файлами, в том числе и с архивами, выполняются именно в таких менеджерах.

    4. Сжатие данных с потерями информации

    Сжатие данных с потерями - это метод сжатия данных, когда распакованный файл отличается от оригинального, но «достаточно близок» для того, чтобы быть полезным каким-то образом. Этот тип компрессии часто используется в Интернете, особенно в потоковой передаче данных и телефонии. Эти методы часто называются кодеками в этом контексте. Альтернативой является сжатие без потерь.

    Типы сжатия с потерями

    Существуют две основных схемы сжатия с потерями:

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

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

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

    Сжатие с потерями против сжатия без потерь

    Преимущество методов сжатия с потерями над методами сжатия без потерь состоит в том, что первые существенно превосходят по степени сжатия, продолжая удовлетворять поставленным требованиям.

    Методы сжатия с потерями часто используются для сжатия звука или изображений.

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

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

    Звуковые данные, прошедшие сжатие с потерями, не принимаются судами как вещественные доказательства (и даже не берутся во внимание) по причине того, что информация, прошедшая сжатие, приобретает артефакты сжатия и теряет естественные шумы среды, из которой производилась запись. В связи с чем невозможно установить подлинная ли запись или синтезированная. Поэтому важные записи рекомендуется производить в формате ИКМ (PCM) или использовать плёночный диктофон.

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

    Методы сжатия данных с потерями

    v Компрессия изображений:

    · Снижение глубины цвета;

    · Метод главных компонент;

    · Фрактальное сжатие;

    v Компрессия видео:

    · Flash (также поддерживает движущиеся изображения JPEG);

    · MPEG-1 Part 2;

    · MPEG-2 Part 2;

    · MPEG-4 Part 2;

    v Компрессия звука:

    · MP3 - Определён спецификацией MPEG-1;

    · Ogg Vorbis (отличается отсутствием патентных ограничений и более высоким качеством);

    · AAC, AAC+ - существует в нескольких вариантах, определённых спецификациями MPEG-2 и MPEG-4, используется, например, в Apple Computer;

    · eAAC+ - формат, предлагаемый Sony, как альтернатива AAC и AAC+;

    · WMA - собственность Microsoft;

    информация сжатие архиватор потеря

    5. Сжатие данных без потерь информации

    Сжатие без потерь (англ. Lossless data compression) - метод сжатия информации, при использовании которого закодированная информация может быть восстановлена с точностью до бита. При этом оригинальные данные полностью восстанавливаются из сжатого состояния. Этот тип сжатия принципиально отличается от сжатия данных с потерями. Для каждого из типов цифровой информации, как правило, существуют свои оптимальные алгоритмы сжатия без потерь.

    Сжатие данных без потерь используется во многих приложениях. Например, оно используется в популярном файловом формате ZIP и Unix-утилите Gzip. Оно также используется как компонент в сжатии с потерями.

    Сжатие без потерь используется, когда важна идентичность сжатых данных оригиналу. Обычный пример - исполняемые файлы и исходный код. Некоторые графические файловые форматы, такие как PNG или GIF, используют только сжатие без потерь; тогда как другие (TIFF, MNG) могут использовать сжатие как с потерями, так и без.

    Техника сжатия без потерь

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

    Многоцелевые алгоритмы сжатия отличаются тем, что способны уменьшать широкий диапазон данных - исполняемые файлы, файлы данных, тексты, графику и т.д., и применяются в архиваторах. Специализированные же алгоритмы рассчитаны на некоторый тип файлов (текст, графику, звук и т.д.), зато сжимают такие файлы намного сильнее. Например: архиваторы сжимают звук примерно на треть (в 1,5 раза), в то время как FLAC - в 2,5 раза. Большинство специализированных алгоритмов малопригодны для файлов «чужих» типов: так, звуковые данные плохо сжимаются алгоритмом, рассчитанным на тексты.

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

    Статистические модели алгоритмов для текста (или текстовых бинарных данных, таких как исполняемые файлы) включают:

    Преобразование Барроуза - Уилера (блочно-сортирующая предобработка, которая делает сжатие более эффективным)

    LZ77 и LZ78 (используется DEFLATE)

    Алгоритмы кодирования через генерирование битовых последовательностей:

    · Алгоритм Хаффмана (также используется DEFLATE)

    · Арифметическое кодирование

    Методы сжатия без потерь

    · Многоцелевые

    · Кодирование длин серий - простая схема, дающая хорошее сжатие данных, которые содержат много повторяющихся значений

    · LZW - используется в gif и во многих других.

    · Deflate - используется в gzip, усовершенствованной версии zip и как часть процесса сжатия PNG.

    · LZMA - используется в 7-zip.

    v Сжатие аудио:

    · Apple Lossless - ALAC (Apple Lossless Audio Codec);

    · Audio Lossless Coding - также известен как MPEG-4 ALS;

    · Direct Stream Transfer - DST;

    · Free Lossless Audio Codec - FLAC;

    v Сжатие графики

    · ABO - Adaptive Binary Optimization;

    · GIF - (без потерь только для изображений содержащих менее 256 цветов);

    · JBIG2 - (с потерями или без Ч/Б изображений);

    · JPEG-LS - (стандарт сжатия без потерь / почти без потерь);

    · JPEG 2000 - (включает сжатие без потерь; также, испытан Sunil Kumar, профессором университета штата Сан-Диего);

    · PGF - Progressive Graphics File (сжатие с/без потерь);

    · PNG - Portable Network Graphics;

    · WMPhoto - (включая метод сжатия без потерь);

    v Сжатие видео

    · Animation codec;

    · CamStudio Video Codec;

    6. Хранение информации (текстовой, графической, звуковой)

    Хранение информации происходит с помощью определенных носителей информации. Человек хранит свои знания либо в собственной памяти, либо на каких-то внешних носителях.

    Поначалу для хранения и накопления информации человек использовал свою память - он попросту запоминал полученную информацию и помнил ее какое-то время. Постепенно люди пришли к выводу, что такой способ хранения информации имеет ряд недостатков. Понимая всю ненадежность такого способа хранения и накопления информации, человек начал записывать информацию в виде рисунков, с изобретением письменности - на папирусах, а позднее в книгах. Затем появились фотопластинки и звукозаписывающие устройства, как элементы внешней памяти видео- и аудиоинформации, записные книжки, справочники, энциклопедии и т.д., которые мы называем внешними хранилищами данных. К середине XX века был изобретен ЭВМ. Сразу встал вопрос, как он будет хранить информацию.

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

    В ЭВМ в качестве устройств для записи, чтения информации стали использоваться: устройства чтения перфокарт; накопители на магнитной ленте, накопители на гибких (дисковод) и жестких (винчестер) магнитных дисках; накопители на компакт-дисках (CD-ROM) и другие более современные устройства накопления и хранения информации.

    Библиографический список

    1. Федеральный закон Российской Федерации «Об информации, информатизации и защите информации» от 27.07.2006 №149-ФЗ.

    2. Левин А.Ш. Самоучитель работы на компьютере. - СПб.: Питер, 2006. - 655 с.

    3. Романова Н.И. Основы информатики. - СПб.: Политехника, 2004. -224 с.

    4. Симонович С.В. Информатика. Базовый курс. - СПб.: Питер, 2008 -640 с.

    Размещено на Allbest.ru

    Подобные документы

      Типы сжатия данных: с потерями (lossy) и без потерь (lossless). Сжатие с минимальной избыточностью. Кодирование методом Шеннона-Фано. Проверка работы программы по сжатию файлов формата bmp и xls. Реализация на Delphi алгоритма сжатия Шеннона и Хаффмана.

      курсовая работа , добавлен 26.01.2011

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

      курсовая работа , добавлен 17.03.2011

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

      презентация , добавлен 06.01.2014

      Исследование основных видов программ-архиваторов. Сжатие файлов при архивации. Показатель степени сжатия файлов. Оценка функциональности самых популярных программ-упаковщиков. Технические характеристики процессов сжатия. Методы архивации без потерь.

      реферат , добавлен 05.12.2013

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

      презентация , добавлен 05.04.2011

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

      контрольная работа , добавлен 12.03.2011

      Краткий обзор основных теорий сжатия. Концепции идей и их реализация. Сжатие данных с использованием преобразования Барроуза-Вилера. Статический алгоритм Хафмана. Локально адаптивный алгоритм сжатия. Алгоритм Зива-Лемпеля (Welch) и метод Шеннона-Фано.

      практическая работа , добавлен 24.04.2014

      Энтропия и количество информации. Комбинаторная, вероятностная и алгоритмическая оценка количества информации. Моделирование и кодирование. Некоторые алгоритмы сжатия данных. Алгоритм арифметического кодирования. Приращаемая передача и получение.

      курсовая работа , добавлен 28.07.2009

      Применение алгоритмов, обеспечивающих высокую степень сжатия, для увеличения скорости передачи данных по каналам связи. Особенности и методы нахождения сингулярного разложения. Разработка программы, реализующей сжатие изображения с помощью SVD-сжатия.

      дипломная работа , добавлен 13.10.2015

      Программы для создания архивов. Эффективность сжатия данных как важнейшая характеристика архиваторов. Основные методы сжатия данных. Характеристика программы для упаковки текстов и программ WinRar. Распаковка файлов, упаковка файлов и папок в общий архив.

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

    Основоположником науки о сжатии информации принято считать Клода Шеннона. Его теорема об оптимальном кодировании показывает, к чему нужно стремиться при кодировании информации и насколько та или иная информация при этом сожмется. Кроме того, им были проведены опыты по эмпирической оценке избыточности английского текста. Шенон предлагал людям угадывать следующую букву и оценивал вероятность правильного угадывания. На основе ряда опытов он пришел к выводу, что количество информации в английском тексте колеблется в пределах 0,6 – 1,3 бита на символ. Несмотря на то, что результаты исследований Шеннона были по-настоящему востребованы лишь десятилетия спустя, трудно переоценить их значение .

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

    • Сжатие без потерь (полностью обратимое) – это метод сжатия данных, при котором ранее закодированная порция данных восстанавливается после их распаковки полностью без внесения изменений. Для каждого типа данных, как правило, существуют свои оптимальные алгоритмы сжатия без потерь.
    • Сжатие с потерями – это метод сжатия данных, при котором для обеспечения максимальной степени сжатия исходного массива данных часть содержащихся в нем данных отбрасывается. Для текстовых, числовых и табличных данных использование программ, реализующих подобные методы сжатия, является неприемлемыми. В основном такие алгоритмы применяются для сжатия аудио- и видеоданных, статических изображений.

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

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

    Алфавит кода – множество всех символов входного потока. При сжатии англоязычных текстов обычно используют множество из 128 ASCII кодов. При сжатии изображений множество значений пиксела может содержать 2, 16, 256 или другое количество элементов.

    Кодовый символ – наименьшая единица данных, подлежащая сжатию. Обычно символ – это 1 байт , но он может быть битом, тритом {0,1,2}, или чем-либо еще.

    Кодовое слово – это последовательность кодовых символов из алфавита кода. Если все слова имеют одинаковую длину (число символов), то такой код называется равномерным (фиксированной длины) , а если же допускаются слова разной длины, то – неравномерным (переменной длины) .

    Код – полное множество слов.

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

    Фраза – фрагмент данных, помещаемый в словарь для дальнейшего использования в сжатии.

    Кодирование – процесс сжатия данных.

    Декодирование – обратный кодированию процесс, при котором осуществляется восстановление данных.

    Отношение сжатия – одна из наиболее часто используемых величин для обозначения эффективности метода сжатия.

    Значение 0,6 означает, что данные занимают 60% от первоначального объема. Значения больше 1 означают, что выходной поток больше входного (отрицательное сжатие, или расширение).

    Коэффициент сжатия – величина, обратная отношению сжатия.

    Значения больше 1 обозначают сжатие, а значения меньше 1 – расширение.

    Средняя длина кодового слова – это величина, которая вычисляется как взвешенная вероятностями сумма длин всех кодовых слов.

    L cp =p 1 L 1 +p 2 L 2 +...+p n L n ,

    где – вероятности кодовых слов;

    L 1 ,L 2 ,...,L n – длины кодовых слов.

    Существуют два основных способа проведения сжатия.

    Статистические методы – методы сжатия, присваивающие коды переменной длины символам входного потока, причем более короткие коды присваиваются символам или группам символам, имеющим большую вероятность появления во входном потоке. Лучшие статистические методы применяют кодирование Хаффмана.

    Словарное сжатие – это методы сжатия, хранящие фрагменты данных в "словаре" (некоторая структура данных ). Если строка новых данных, поступающих на вход, идентична какому-либо фрагменту, уже находящемуся в словаре, в выходной поток помещается указатель на этот фрагмент. Лучшие словарные методы применяют метод Зива-Лемпела.

    Рассмотрим несколько известных алгоритмов сжатия данных более подробно.

    Метод Хаффмана

    Этот алгоритм кодирования информации был предложен Д.А. Хаффманом в 1952 году. Хаффмановское кодирование (сжатие) – это широко используемый метод сжатия, присваивающий символам алфавита коды переменной длины, основываясь на вероятностях появления этих символов.

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

    Префиксный код – это код, в котором никакое кодовое слово не является префиксом любого другого кодового слова. Эти коды имеют переменную длину.

    Оптимальный префиксный код – это префиксный код , имеющий минимальную среднюю длину.

    Алгоритм Хаффмана можно разделить на два этапа.

    1. Определение вероятности появления символов в исходном тексте.

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

    2. Нахождение оптимального префиксного кода.

      Далее находятся два символа a и b с наименьшими вероятностями появления и заменяются одним фиктивным символом x , который имеет вероятность появления, равную сумме вероятностей появления символов a и b . Затем, используя эту процедуру рекурсивно, находится оптимальный префиксный код для меньшего множества символов (где символы a и b заменены одним символом x ). Код для исходного множества символов получается из кодов замещающих символов путем добавления 0 или 1 перед кодом замещающего символа, и эти два новых кода принимаются как коды заменяемых символов. Например, код символа a будет соответствовать коду x с добавленным нулем перед этим кодом, а для символа b перед кодом символа x будет добавлена единица.

    Коды Хаффмана имеют уникальный префикс , что и позволяет однозначно их декодировать, несмотря на их переменную длину.

    Пример 1 . Программная реализация метода Хаффмана.

    #include "stdafx.h" #include using namespace std; void Expectancy(); long MinK(); void SumUp(); void BuildBits(); void OutputResult(char **Result); void Clear(); const int MaxK = 1000; long k, a, b; char bits; char sk; bool Free; char *res; long i, j, n, m, kj, kk1, kk2; char str; int _tmain(int argc, _TCHAR* argv){ char *BinaryCode; Clear(); cout << "Введите строку для кодирования: "; cin >> str; Expectancy(); SumUp(); BuildBits(); OutputResult(&BinaryCode); cout << "Закодированная строка: " << endl; cout << BinaryCode << endl; system("pause"); return 0; } //описание функции обнуления данных в массивах void Clear(){ for (i = 0; i < MaxK + 1; i++){ k[i] = a[i] = b[i] = 0; sk[i] = 0; Free[i] = true; for (j = 0; j < 40; j++) bits[i][j] = 0; } } /*описание функции вычисления вероятности вхождения каждого символа в тексте*/ void Expectancy(){ long *s = new long; for (i = 0; i < 256; i++) s[i] = 0; for (n = 0; n < strlen(str); n++) s]++; j = 0; for (i = 0; i < 256; i++) if (s[i] != 0){ j++; k[j] = s[i]; sk[j] = i; } kj = j; } /*описание функции нахождения минимальной частоты символа в исходном тексте*/ long MinK(){ long min; i = 1; while (!Free[i] && i < MaxK) i++; min = k[i]; m = i; for (i = m + 1; i <= kk2; i++) if (Free[i] && k[i] < min){ min = k[i]; m = i; } Free[m] = false; return min; } //описание функции подсчета суммарной частоты символов void SumUp(){ long s1, s2, m1, m2; for (i = 1; i <= kj; i++){ Free[i] = true; a[i] = 0; b[i] = 0; } kk1 = kk2 = kj; while (kk1 > 2){ s1 = MinK(); m1 = m; s2 = MinK(); m2 = m; kk2++; k = s1 + s2; a = m1; b = m2; Free = true; kk1--; } } //описание функции формирования префиксных кодов void BuildBits(){ strcpy(bits,"1"); Free = false; strcpy(bits],bits); strcat(bits] , "0"); strcpy(bits],bits); strcat(bits] , "1"); i = MinK(); strcpy(bits[m],"0"); Free[m] = true; strcpy(bits],bits[m]); strcat(bits] , "0"); strcpy(bits],bits[m]); strcat(bits] , "1"); for (i = kk2 - 1; i > 0; i--) if (!Free[i]) { strcpy(bits],bits[i]); strcat(bits] , "0"); strcpy(bits],bits[i]); strcat(bits] , "1"); } } //описание функции вывода данных void OutputResult(char **Result){ (*Result) = new char; for (int t = 0; i < 1000 ;i++) (*Result)[t] = 0; for (i = 1; i <= kj; i++) res] = bits[i]; for (i = 0; i < strlen(str); i++) strcat((*Result) , res]); } Листинг.

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

    Методы сжатия данных имеют достаточно длинную историю развития, которая началась задолго до появления первого компьютера. В этой статье будет произведена попытка дать краткий обзор основных теорий, концепций идей и их реализаций, не претендующий, однако, на абсолютную полноту. Более подробные сведения можно найти, например, в Кричевский Р.Е. , Рябко Б.Я. , Witten I.H. , Rissanen J. , Huffman D.A., Gallager R.G. , Knuth D.E. , Vitter J.S. и др.

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

    Степень сжатия (compress rating) или отношение (ratio) объемов исходного и результирующего потоков;

    Скорость сжатия - время, затрачиваемое на сжатие некоторого объема информации входного потока, до получения из него эквивалентного выходного потока;

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

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

    Под необратимым сжатием подразумевают такое преобразование входного потока данных, при котором выходной поток, основанный на определенном формате информации, представляет, с некоторой точки зрения, достаточно похожий по внешним характеристикам на входной поток объект, однако отличается от него объемом. Степень сходства входного и выходного потоков определяется степенью соответствия некоторых свойств объекта (т.е. сжатой и несжатой информации, в соответствии с некоторым определенным форматом данных), представляемого данным потоком информации. Такие подходы и алгоритмы используются для сжатия, например, данных растровых графических файлов с низкой степенью повторяемости байтов в потоке. При таком подходе используется свойство структуры формата графического файла и возможность представить графическую картинку приблизительно схожую по качеству отображения (для восприятия человеческим глазом) несколькими (а точнее n) способами. Поэтому, кроме степени или величины сжатия, в таких алгоритмах возникает понятие качества, т.к. исходное изображение в процессе сжатия изменяется, то под качеством можно понимать степень соответствия исходного и результирующего изображения, оцениваемая субъективно, исходя из формата информации. Для графических файлов такое соответствие определяется визуально, хотя имеются и соответствующие интеллектуальные алгоритмы и программы. Необратимое сжатие невозможно применять в областях, в которых необходимо иметь точное соответствие информационной структуры входного и выходного потоков. Данный подход реализован в популярных форматах представления видео и фото информации, известных как JPEG и JFIF алгоритмы и JPG и JIF форматы файлов.

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

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

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

    Сжатие способом кодирования серий

    Наиболее известный простой подход и алгоритм сжатия информации обратимым путем - это кодирование серий последовательностей (Run Length Encoding - RLE). Суть методов данного подхода состоит в замене цепочек или серий повторяющихся байтов или их последовательностей на один кодирующий байт и счетчик числа их повторений. Проблема всех аналогичных методов заключается лишь в определении способа, при помощи которого распаковывающий алгоритм мог бы отличить в результирующем потоке байтов кодированную серию от других - некодированных последовательностей байтов. Решение проблемы достигается обычно простановкой меток в начале кодированных цепочек. Такими метками могут быть, например, характерные значения битов в первом байте кодированной серии, значения первого байта кодированной серии и т.п. Данные методы, как правило, достаточно эффективны для сжатия растровых графических изображений (BMP, PCX, TIF, GIF), т.к. последние содержат достаточно много длинных серий повторяющихся последовательностей байтов. Недостатком метода RLE является достаточно низкая степень сжатия или стоимость кодирования файлов с малым числом серий и, что еще хуже - с малым числом повторяющихся байтов в сериях.

    Сжатие без применения метода RLE

    Процесс сжатия данных без применения метода RLE можно разбить на два этапа: моделирование (modelling) и, собственно, кодирование (encoding). Эти процессы и их реализующие алгоритмы достаточно независимы и разноплановы.

    Процесс кодирования и его методы

    Под кодированием обычно понимают обработку потока символов (в нашем случае байтов или полубайтов) в некотором алфавите, причем частоты появления символов в потоке различны. Целью кодирования является преобразование этого потока в поток бит минимальной длины, что достигается уменьшением энтропии входного потока путем учета частот символов. Длина кода, представляющего символы из алфавита потока должна быть пропорциональна объему информации входного потока, а длина символов потока в битах может быть не кратна 8 и даже переменной. Если распределение вероятностей частот появления символов из алфавита входного потока известно, то можно построить модель оптимального кодирования. Однако, ввиду существования огромного числа различных форматов файлов задача значительно усложняется т.к. распределение частот символов данных заранее неизвестно. В таком случае, в общем виде, используются два подхода.

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

    Введение.

    Сжатие сокращает объем пространства, тpебуемого для хранения файлов в ЭВМ, и

    количество времени, необходимого для передачи информации по каналу установленной

    ширины пропускания. Это есть форма кодирования. Другими целями кодирования

    являются поиск и исправление ошибок, а также шифрование. Процесс поиска и

    исправления ошибок противоположен сжатию - он увеличивает избыточность данных,

    когда их не нужно представлять в удобной для восприятия человеком форме. Удаляя

    из текста избыточность, сжатие способствует шифpованию, что затpудняет поиск

    шифpа доступным для взломщика статистическим методом.

    Рассмотpим обратимое сжатие или сжатие без наличия помех, где первоначальный

    текст может быть в точности восстановлен из сжатого состояния. Необратимое или

    ущербное сжатие используется для цифровой записи аналоговых сигналов, таких как

    человеческая речь или рисунки. Обратимое сжатие особенно важно для текстов,

    записанных на естественных и на искусственных языках, поскольку в этом случае

    ошибки обычно недопустимы. Хотя первоочередной областью применения

    рассматриваемых методов есть сжатие текстов, что отpажает и наша терминология,

    однако, эта техника может найти применение и в других случаях, включая обратимое

    кодирование последовательностей дискретных данных.

    Существует много веских причин выделять ресурсы ЭВМ в pасчете на сжатое

    представление, т.к. более быстрая передача данных и сокpащение пpостpанства для

    их хpанения позволяют сберечь значительные средства и зачастую улучшить

    показатели ЭВМ. Сжатие вероятно будет оставаться в сфере внимания из-за все

    возрастающих объемов хранимых и передаваемых в ЭВМ данных, кроме того его можно

    использовать для преодоления некотоpых физических ограничений, таких как,

    напpимеp, сравнительно низкая шиpину пpопускания телефонных каналов.

    ПРИМЕНЕНИЕ РАСШИРЯЮЩИХСЯ ДЕРЕВЬЕВ ДЛЯ СЖАТИЯ ДАННЫХ.

    Алгоритмы сжатия могут повышать эффективность хранения и передачи данных

    посредством сокращения количества их избыточности. Алгоритм сжатия берет в

    качестве входа текст источника и производит соответствующий ему сжатый текст,

    когда как разворачивающий алгоритм имеет на входе сжатый текст и получает из

    него на выходе первоначальный текст источника. Большинство алгоритмов сжатия

    рассматривают исходный текст как набор строк, состоящих из букв алфавита

    исходного текста.

    Избыточность в представлении строки S есть L(S) - H(S), где L(S) есть длина

    представления в битах, а H(S) - энтропия - мера содержания информации, также

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

    строку к меньшему числу бит, чем составляет ее энтропия, не существует. Если из

    исходного текста извлекать по одной букве некоторого случайного набоpа,

    использующего алфавит А, то энтропия находится по формуле:

    H(S) = C(S) p(c) log ---- ,

    где C(S) есть количество букв в строке, p(c) есть статическая вероятность

    появления некоторой буквы C. Если для оценки p(c) использована частота появления

    каждой буквы c в строке S, то H(C) называется самоэнтропией строки S. В этой

    статье H (S) будет использоваться для обозначения самоэнтропии строки, взятой из

    статичного источника.

    Расширяющиеся деревья обычно описывают формы лексикографической упорядоченности

    деpевьев двоичного поиска, но деревья, используемые при сжатии данных могут не

    иметь постоянной упорядоченности. Устранение упорядоченности приводит к

    значительному упрощению основных операций расширения. Полученные в итоге

    алгоритмы предельно быстры и компактны. В случае применения кодов Хаффмана,

    pасширение приводит к локально адаптированному алгоритму сжатия, котоpый

    замечательно прост и быстр, хотя и не позволяет достигнуть оптимального сжатия.

    Когда он применяется к арифметическим кодам, то результат сжатия близок к

    оптимальному и приблизительно оптимален по времени.

    КОДЫ ПРЕФИКСОВ.

    Большинство широко изучаемых алгоритмов сжатия данных основаны на кодах

    Хаффмана. В коде Хаффмана каждая буква исходного текста представляется в архиве

    кодом переменной длины. Более частые буквы представляются короткими кодами,

    менее частые - длинными. Коды, используемые в сжатом тексте должны подчиняться

    свойствам префикса, а именно: код, использованный в сжатом тексте не может быть

    префиксом любого другого кода.

    Коды префикса могут быть найдены посредством дерева, в котором каждый лист

    соответствует одной букве алфавита источника. Hа pисунке 1 показано дерево кода

    префикса для алфавита из 4 букв. Код префикса для буквы может быть прочитан при

    обходе деpева от корня к этой букве, где 0 соответствует выбору левой его ветви,

    а 1 - правой. Дерево кода Хаффмана есть дерево с выравненным весом, где каждый

    лист имеет вес, равный частоте встречаемости буквы в исходном тексте, а

    внутренние узлы своего веса не имеют. Дерево в примере будет оптимальным, если

    частоты букв A, B, C и D будут 0.125, 0.125, 0.25 и 0.5 соответственно.

    Обычные коды Хаффмана требуют предварительной информации о частоте встречаемости

    букв в исходном тексте, что ведет к необходимости его двойного просмотра - один

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

    последующем, значения этих частот нужно объединять с самим сжатым текстом, чтобы

    в дальнейшем сделать возможным его развертывание. Адаптивное сжатие выполняется

    за один шаг, т.к. код, используемый для каждой буквы исходного текста, основан

    на частотах всех остальных кpоме нее букв алфавита. Основы для эффективной

    реализации адаптивного кода Хаффмана были заложены Галлагером, Кнут опубликовал

    практическую версию такого алгоритма, а Уиттер его pазвил.

    Оптимальный адаптированный код Уиттера всегда лежит в пределах одного бита на

    букву источника по отношению к оптимальному статичному коду Хаффмана, что обычно

    составляет несколько процентов от H . К тому же, статичные коды Хаффмана всегда

    лежат в пределах одного бита на букву исходного текста от H (они достигают этот

    предел только когда для всех букв p(C) = 2). Существуют алгоритмы сжатия

    которые могут преодолевать эти ограничения. Алгоритм Зива-Лемпелла, например,

    присваивает слова из аpхива фиксированной длины строкам исходного текста

    пеpеменной длины, а арифметическое сжатие может использовать для кодирования

    букв источника даже доли бита.

    Применение расширения к кодам префикса.

    Расширяющиеся деревья были впервые описаны в 1983 году и более подpобно

    рассмотрены в 1985. Первоначально они понимались как вид самосбалансиpованных

    деpевьев двоичного поиска, и было также показано, что они позволяют осуществить

    самую быструю реализацию приоритетных очередей. Если узел расширяющегося дерева

    доступен, то оно является расширенным. Это значит, что доступный узел становится

    корнем, все узлы слева от него образуют новое левое поддерево, узлы справа -

    новое правое поддерево. Расширение достигается при обходе дерева от старого

    корня к целевому узлу и совершении пpи этом локальных изменений, поэтому цена

    расширения пропорциональна длине пройденного пути.

    Тарьян и Слейтон показали, что расширяющиеся деревья статично оптимальны.

    Другими словами, если коды доступных узлов взяты согласно статичному

    распределению вероятности, то скорости доступа к расширяющемуся дереву и

    статично сбалансированному, оптимизированному этим распределением, будут

    отличаться друг от друга на постоянный коэффициент, заметный при достаточно

    длинных сериях доступов. Поскольку дерево Хаффмана представляет собой пример

    статично сбалансированного дерева, то пpи использовании расширения для сжатия

    данных, pазмер сжатого текста будет лежать в пределах некоторого коэффициента от

    размера архива, полученного при использовании кода Хаффмана.

    Как было первоначально описано, расширение применяется к деревьям, хранящим

    данные во внутренних узлах, а не в листьях. Деревья же кодов префикса несут все

    свои данные только в листьях. Существует, однако, вариант расширения, называемый

    полурасширением, который применим для дерева кодов префикса. При нем целевой

    узел не перемещается в корень и модификация его наследников не производится,

    взамен путь от корня до цели просто уменьшается вдвое. Полурасширение достигает

    тех же теоретических границ в пределах постоянного коэффициента, что и

    расширение.

    В случае зигзагообразного обхода лексикографического дерева, проведение как

    расширения, так и полурасширения усложняется, в отличие от прямого маршрута по

    левому или правому краю дерева к целевому узлу. Этот простой случай показан на

    рисунке 2. Воздействие полурасширения на маршруте от корня (узел w) до листа

    узла A заключается в перемене местами каждой пары внутренних следующих друг за

    другом узлов, в результате чего длина пути от корня до узла-листа сокращается в

    2 раза. В процессе полурасширения узлы каждой пары, более далекие от корня,

    включаются в новый путь (узлы x и z), а более близкие из него

    исключаются (узлы w и y).

    Сохранение операцией полурасширения лексикографического порядка в деревьях кода

    префикса не является обязательным. Единственно важным в операциях с кодом

    префикса является точное соответствие дерева, используемого процедурой сжатия

    дереву, используемому процедурой развертывания. Любое его изменение, допущенное

    между последовательно идущими буквами, производится только в том случае, если

    обе процедуры осуществляют одинаковые изменения в одинаковом порядке.

    Hенужность поддержки лексикографического порядка значительно упрощает проведение

    операции полурасширения за счет исключения случая зигзага. Это может быть

    Мы с моим научным руководителем готовим небольшую монографию по обработке изображений. Решил представить на суд хабрасообщества главу, посвящённую алгоритмам сжатия изображений. Так как в рамках одного поста целую главу уместить тяжело, решил разбить её на три поста:
    1. Методы сжатия данных;
    2. Сжатие изображений без потерь;
    3. Сжатие изображений с потерями.
    Ниже вы можете ознакомиться с первым постом серии.

    На текущий момент существует большое количество алгоритмов сжатия без потерь, которые условно можно разделить на две большие группы:
    1. Поточные и словарные алгоритмы. К этой группе относятся алгоритмы семейств RLE (run-length encoding), LZ* и др. Особенностью всех алгоритмов этой группы является то, что при кодировании используется не информация о частотах символов в сообщении, а информация о последовательностях, встречавшихся ранее.
    2. Алгоритмы статистического (энтропийного) сжатия. Эта группа алгоритмов сжимает информацию, используя неравномерность частот, с которыми различные символы встречаются в сообщении. К алгоритмам этой группы относятся алгоритмы арифметического и префиксного кодирования (с использованием деревьев Шеннона-Фанно, Хаффмана, секущих).
    В отдельную группу можно выделить алгоритмы преобразования информации. Алгоритмы этой группы не производят непосредственного сжатия информации, но их применение значительно упрощает дальнейшее сжатие с использованием поточных, словарных и энтропийных алгоритмов.

    Поточные и словарные алгоритмы

    Кодирование длин серий

    Кодирование длин серий (RLE - Run-Length Encoding) - это один из самых простых и распространённых алгоритмов сжатия данных. В этом алгоритме последовательность повторяющихся символов заменяется символом и количеством его повторов.
    Например, строку «ААААА», требующую для хранения 5 байт (при условии, что на хранение одного символа отводится байт), можно заменить на «5А», состоящую из двух байт. Очевидно, что этот алгоритм тем эффективнее, чем длиннее серия повторов.

    Основным недостатком этого алгоритма является его крайне низкая эффективность на последовательностях неповторяющихся символов. Например, если рассмотреть последовательность «АБАБАБ» (6 байт), то после применения алгоритма RLE она превратится в «1А1Б1А1Б1А1Б» (12 байт). Для решения проблемы неповторяющихся символов существуют различные методы.

    Самым простым методом является следующая модификация: байт, кодирующий количество повторов, должен хранить информацию не только о количестве повторов, но и об их наличии. Если первый бит равен 1, то следующие 7 бит указывают количество повторов соответствующего символа, а если первый бит равен 0, то следующие 7 бит показывают количество символов, которые надо взять без повтора. Если закодировать «АБАБАБ» с использованием данной модификации, то получим «-6АБАБАБ» (7 байт). Очевидно, что предложенная методика позволяет значительно повысить эффективность RLE алгоритма на неповторяющихся последовательностях символов. Реализация предложенного подхода приведена в Листинг 1:

    1. type
    2. function RLEEncode(InMsg: ShortString) : TRLEEncodedString;
    3. MatchFl: boolean ;
    4. MatchCount: shortint ;
    5. EncodedString: TRLEEncodedString;
    6. N, i: byte ;
    7. begin
    8. N : = 0 ;
    9. SetLength(EncodedString, 2 * length(InMsg) ) ;
    10. while length(InMsg) >= 1 do
    11. begin
    12. MatchFl : = (length(InMsg) > 1 ) and (InMsg[ 1 ] = InMsg[ 2 ] ) ;
    13. MatchCount : = 1 ;
    14. while (MatchCount <= 126 ) and (MatchCount < length(InMsg) ) and ((InMsg[ MatchCount] = InMsg[ MatchCount + 1 ] ) = MatchFl) do
    15. MatchCount : = MatchCount + 1 ;
    16. if MatchFl then
    17. begin
    18. N : = N + 2 ;
    19. EncodedString[ N - 2 ] : = MatchCount + 128 ;
    20. EncodedString[ N - 1 ] : = ord (InMsg[ 1 ] ) ;
    21. else
    22. begin
    23. if MatchCount <> length(InMsg) then
    24. MatchCount : = MatchCount - 1 ;
    25. N : = N + 1 + MatchCount;
    26. EncodedString[ N - 1 - MatchCount] : = - MatchCount + 128 ;
    27. for i : = 1 to MatchCount do
    28. EncodedString[ N - 1 - MatchCount + i] : = ord (InMsg[ i] ) ;
    29. end ;
    30. delete(InMsg, 1 , MatchCount) ;
    31. end ;
    32. SetLength(EncodedString, N) ;
    33. RLEEncode : = EncodedString;
    34. end ;

    Декодирование сжатого сообщения выполняется очень просто и сводится к однократному проходу по сжатому сообщению см. Листинг 2:
    1. type
    2. TRLEEncodedString = array of byte ;
    3. function RLEDecode(InMsg: TRLEEncodedString) : ShortString;
    4. RepeatCount: shortint ;
    5. i, j: word ;
    6. OutMsg: ShortString;
    7. begin
    8. OutMsg : = "" ;
    9. i : = 0 ;
    10. while i < length(InMsg) do
    11. begin
    12. RepeatCount : = InMsg[ i] - 128 ;
    13. i : = i + 1 ;
    14. if RepeatCount < 0 then
    15. begin
    16. RepeatCount : = abs (RepeatCount) ;
    17. for j : = i to i + RepeatCount - 1 do
    18. OutMsg : = OutMsg + chr (InMsg[ j] ) ;
    19. i : = i + RepeatCount;
    20. else
    21. begin
    22. for j : = 1 to RepeatCount do
    23. OutMsg : = OutMsg + chr (InMsg[ i] ) ;
    24. i : = i + 1 ;
    25. end ;
    26. end ;
    27. RLEDecode : = OutMsg;
    28. end ;

    Вторым методом повышения эффективности алгоритма RLE является использование алгоритмов преобразования информации, которые непосредственно не сжимают данные, но приводят их к виду, более удобному для сжатия. В качестве примера такого алгоритма мы рассмотрим BWT-перестановку, названную по фамилиям изобретателей Burrows-Wheeler transform. Эта перестановка не изменяет сами символы, а изменяет только их порядок в строке, при этом повторяющиеся подстроки после применения перестановки собираются в плотные группы, которые гораздо лучше сжимаются с помощью алгоритма RLE. Прямое BWT преобразование сводится к последовательности следующих шагов:
    1. Добавление к исходной строке специального символа конца строки, который нигде более не встречается;
    2. Получение всех циклических перестановок исходной строки;
    3. Сортировка полученных строк в лексикографическом порядке;
    4. Возвращение последнего столбца полученной матрицы.
    Реализация данного алгоритма приведена в Листинг 3.
    1. const
    2. EOMsg = "|" ;
    3. function BWTEncode(InMsg: ShortString) : ShortString;
    4. OutMsg: ShortString;
    5. LastChar: ANSIChar;
    6. N, i: word ;
    7. begin
    8. InMsg : = InMsg + EOMsg;
    9. N : = length(InMsg) ;
    10. ShiftTable[ 1 ] : = InMsg;
    11. for i : = 2 to N do
    12. begin
    13. LastChar : = InMsg[ N] ;
    14. InMsg : = LastChar + copy(InMsg, 1 , N - 1 ) ;
    15. ShiftTable[ i] : = InMsg;
    16. end ;
    17. Sort(ShiftTable) ;
    18. OutMsg : = "" ;
    19. for i : = 1 to N do
    20. OutMsg : = OutMsg + ShiftTable[ i] [ N] ;
    21. BWTEncode : = OutMsg;
    22. end ;

    Проще всего пояснить это преобразование на конкретном примере. Возьмём строку «АНАНАС» и договоримся, что символом конца строки будет символ «|». Все циклические перестановки этой строки и результат их лексикографической сортировки приведены в Табл. 1.

    Т.е. результатом прямого преобразования будет строка «|ННАААС». Легко заметить, что это строка гораздо лучше, чем исходная, сжимается алгоритмом RLE, т.к. в ней существуют длинные подпоследовательности повторяющихся букв.
    Подобного эффекта можно добиться и с помощью других преобразований, но преимущество BWT-преобразования в том, что оно обратимо, правда, обратное преобразование сложнее прямого. Для того, чтобы восстановить исходную строку, необходимо выполнить следующие действия:
    Создать пустую матрицу размером n*n, где n-количество символов в закодированном сообщении;
    Заполнить самый правый пустой столбец закодированным сообщением;
    Отсортировать строки таблицы в лексикографическом порядке;
    Повторять шаги 2-3, пока есть пустые столбцы;
    Вернуть ту строку, которая заканчивается символом конца строки.

    Реализация обратного преобразования на первый взгляд не представляет сложности, и один из вариантов реализации приведён в Листинг 4.

    1. const
    2. EOMsg = "|" ;
    3. function BWTDecode(InMsg: ShortString) : ShortString;
    4. OutMsg: ShortString;
    5. ShiftTable: array of ShortString;
    6. N, i, j: word ;
    7. begin
    8. OutMsg : = "" ;
    9. N : = length(InMsg) ;
    10. SetLength(ShiftTable, N + 1 ) ;
    11. for i : = 0 to N do
    12. ShiftTable[ i] : = "" ;
    13. for i : = 1 to N do
    14. begin
    15. for j : = 1 to N do
    16. ShiftTable[ j] : = InMsg[ j] + ShiftTable[ j] ;
    17. Sort(ShiftTable) ;
    18. end ;
    19. for i : = 1 to N do
    20. if ShiftTable[ i] [ N] = EOMsg then
    21. OutMsg : = ShiftTable[ i] ;
    22. delete(OutMsg, N, 1 ) ;
    23. BWTDecode : = OutMsg;
    24. end ;

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

    После сортировки таблицы, полученной на седьмом шаге, необходимо выбрать из таблицы строку, заканчивающуюся символом «|». Легко заметить, что это строка единственная. Т.о. мы на конкретном примере рассмотрели преобразование BWT.

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

    Словарное сжатие (алгоритмы LZ)

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

    Ниже описан простейший вариант словарного алгоритма:
    Инициализировать словарь всеми символами, встречающимися во входной строке;
    Найти в словаре самую длинную последовательность (S), совпадающую с началом кодируемого сообщения;
    Выдать код найденной последовательности и удалить её из начала кодируемого сообщения;
    Если не достигнут конец сообщения, считать очередной символ и добавить Sc в словарь, перейти к шагу 2. Иначе, выход.

    Например, только что инициализированный словарь для фразы «КУКУШКАКУКУШОНКУКУПИЛАКАПЮШОН» приведён в Табл. 3:

    В процессе сжатия словарь будет дополняться встречающимися в сообщении последовательностями. Процесс пополнения словаря приведён в Табл. 4.

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

    Для начала определим словарь как запись, хранящую не только встречавшиеся подстроки, но и количество хранящихся в словаре подстрок:

    Встречавшиеся ранее подпоследовательности хранятся в массиве Words, а их кодом являются номера подпоследовательностей в этом массиве.
    Также определим функции поиска в словаре и добавления в словарь:

    1. const
    2. MAX_DICT_LENGTH = 256 ;
    3. function FindInDict(D: TDictionary; str: ShortString) : integer ;
    4. r: integer ;
    5. i: integer ;
    6. fl: boolean ;
    7. begin
    8. r : = - 1 ;
    9. if D. WordCount > 0 then
    10. begin
    11. i : = D. WordCount ;
    12. fl : = false ;
    13. while (not fl) and (i >= 0 ) do
    14. begin
    15. i : = i - 1 ;
    16. fl : = D. Words [ i] = str;
    17. end ;
    18. end ;
    19. if fl then
    20. r : = i;
    21. FindInDict : = r;
    22. end ;
    23. procedure AddToDict(var D: TDictionary; str: ShortString) ;
    24. begin
    25. if D. WordCount < MAX_DICT_LENGTH then
    26. begin
    27. D. WordCount : = D. WordCount + 1 ;
    28. SetLength(D. Words , D. WordCount ) ;
    29. D. Words [ D. WordCount - 1 ] : = str;
    30. end ;
    31. end ;

    Используя эти функции, процесс кодирования по описанному алгоритму можно реализовать следующим образом:
    1. function LZWEncode(InMsg: ShortString) : TEncodedString;
    2. OutMsg: TEncodedString;
    3. tmpstr: ShortString;
    4. D: TDictionary;
    5. i, N: byte ;
    6. begin
    7. SetLength(OutMsg, length(InMsg) ) ;
    8. N : = 0 ;
    9. InitDict(D) ;
    10. while length(InMsg) > 0 do
    11. begin
    12. tmpstr : = InMsg[ 1 ] ;
    13. while (FindInDict(D, tmpstr) >= 0 ) and (length(InMsg) > length(tmpstr) ) do
    14. tmpstr : = tmpstr + InMsg[ length(tmpstr) + 1 ] ;
    15. if FindInDict(D, tmpstr) < 0 then
    16. delete(tmpstr, length(tmpstr) , 1 ) ;
    17. OutMsg[ N] : = FindInDict(D, tmpstr) ;
    18. N : = N + 1 ;
    19. delete(InMsg, 1 , length(tmpstr) ) ;
    20. if length(InMsg) > 0 then
    21. AddToDict(D, tmpstr + InMsg[ 1 ] ) ;
    22. end ;
    23. SetLength(OutMsg, N) ;
    24. LZWEncode : = OutMsg;
    25. end ;

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

    Единственная проблема возможна в следующей ситуации: когда необходимо декодировать подпоследовательность, которой ещё нет в словаре. Легко убедиться, что это возможно только в случае, когда необходимо извлечь подстроку, которая должна быть добавлена на текущем шаге. А это значит, что подстрока удовлетворяет шаблону cSc, т.е. начинается и заканчивается одним и тем же символом. При этом cS – это подстрока, добавленная на предыдущем шаге. Рассмотренная ситуация – единственная, когда необходимо декодировать ещё не добавленную строку. Учитывая вышесказанное, можно предложить следующий вариант декодирования сжатой строки:

    1. function LZWDecode(InMsg: TEncodedString) : ShortString;
    2. D: TDictionary;
    3. OutMsg, tmpstr: ShortString;
    4. i: byte ;
    5. begin
    6. OutMsg : = "" ;
    7. tmpstr : = "" ;
    8. InitDict(D) ;
    9. for i : = 0 to length(InMsg) - 1 do
    10. begin
    11. if InMsg[ i] >= D. WordCount then
    12. tmpstr : = D. Words [ InMsg[ i - 1 ] ] + D. Words [ InMsg[ i - 1 ] ] [ 1 ]
    13. else
    14. tmpstr : = D. Words [ InMsg[ i] ] ;
    15. OutMsg : = OutMsg + tmpstr;
    16. if i > 0 then
    17. AddToDict(D, D. Words [ InMsg[ i - 1 ] ] + tmpstr[ 1 ] ) ;
    18. end ;
    19. LZWDecode : = OutMsg;
    20. end ;

    К плюсам словарных алгоритмов относится их большая по сравнению с RLE эффективность сжатия. Тем не менее надо понимать, что реальное использование этих алгоритмов сопряжено с некоторыми трудностями реализации.

    Энтропийное кодирование

    Кодирование с помощью деревьев Шеннона-Фано

    Алгоритм Шеннона-Фано - один из первых разработанных алгоритмов сжатия. В основе алгоритма лежит идея представления более частых символов с помощью более коротких кодов. При этом коды, полученные с помощью алгоритма Шеннона-Фано, обладают свойством префиксности: т.е. ни один код не является началом никакого другого кода. Свойство префиксности гарантирует, что кодирование будет взаимно-однозначным. Алгоритм построения кодов Шеннона-Фано представлен ниже:
    1. Разбить алфавит на две части, суммарные вероятности символов в которых максимально близки друг к другу.
    2. В префиксный код первой части символов добавить 0, в префиксный код второй части символов добавить 1.
    3. Для каждой части (в которой не менее двух символов) рекурсивно выполнить шаги 1-3.
    Несмотря на сравнительную простоту, алгоритм Шеннона-Фано не лишён недостатков, самым существенным из которых является неоптимальность кодирования. Хоть разбиение на каждом шаге и является оптимальным, алгоритм не гарантирует оптимального результата в целом. Рассмотрим, например, следующую строку: «ААААБВГДЕЖ». Соответствующее дерево Шеннона-Фано и коды, полученные на его основе, представлены на Рис. 1:

    Без использования кодирования сообщение будет занимать 40 бит (при условии, что каждый символ кодируется 4 битами), а с использованием алгоритма Шеннона-Фано 4*2+2+4+4+3+3+3=27 бит. Объём сообщения уменьшился на 32.5%, но ниже будет показано, что этот результат можно значительно улучшить.

    Кодирование с помощью деревьев Хаффмана

    Алгоритм кодирования Хаффмана, разработанный через несколько лет после алгоритма Шеннона-Фано, тоже обладает свойством префиксности, а, кроме того, доказанной минимальной избыточностью, именно этим обусловлено его крайне широкое распространение. Для получения кодов Хаффмана используют следующий алгоритм:
    1. Все символы алфавита представляются в виде свободных узлов, при этом вес узла пропорционален частоте символа в сообщении;
    2. Из множества свободных узлов выбираются два узла с минимальным весом и создаётся новый (родительский) узел с весом, равным сумме весов выбранных узлов;
    3. Выбранные узлы удаляются из списка свободных, а созданный на их основе родительский узел добавляется в этот список;
    4. Шаги 2-3 повторяются до тех пор, пока в списке свободных больше одного узла;
    5. На основе построенного дерева каждому символу алфавита присваивается префиксный код;
    6. Сообщение кодируется полученными кодами.

    Рассмотрим тот же пример, что и в случае с алгоритмом Шеннона-Фано. Дерево Хаффмана и коды, полученные для сообщения «ААААБВГДЕЖ», представлены на Рис. 2:

    Легко подсчитать, что объём закодированного сообщения составит 26 бит, что меньше, чем в алгоритме Шеннона-Фано. Отдельно стоит отметить, что ввиду популярности алгоритма Хаффмана на данный момент существует множество вариантов кодирования Хаффмана, в том числе и адаптивное кодирование, которое не требует передачи частот символов.
    Среди недостатков алгоритма Хаффмана значительную часть составляют проблемы, связанные со сложностью реализации. Использование для хранения частот символов вещественных переменных сопряжено с потерей точности, поэтому на практике часто используют целочисленные переменные, но, т.к. вес родительских узлов постоянно растёт, рано или поздно возникает переполнение. Т.о., несмотря на простоту алгоритма, его корректная реализация до сих пор может вызывать некоторые затруднения, особенно для больших алфавитов.

    Кодирование с помощью деревьев секущих функций

    Кодирование с помощью секущих функций – разработанный авторами алгоритм, позволяющий получать префиксные коды. В основе алгоритма лежит идея построения дерева, каждый узел которого содержит секущую функцию. Чтобы подробнее описать алгоритм, необходимо ввести несколько определений.
    Слово – упорядоченная последовательность из m бит (число m называют разрядностью слова).
    Литерал секущей – пара вида разряд-значение разряда. Например, литерал (4,1) означает, что 4 бит слова должен быть равен 1. Если условие литерала выполняется, то литерал считается истинным, в противном случае - ложным.
    k-разрядной секущей называют множество из k литералов. Если все литералы истинны, то и сама секущая функция истинная, в противном случае она ложная.

    Дерево строится так, чтобы каждый узел делил алфавит на максимально близкие части. На Рис. 3 показан пример дерева секущих:

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

    Арифметическое кодирование

    Арифметическое кодирование – один из наиболее эффективных способов сжатия информации. В отличие от алгоритма Хаффмана арифметическое кодирование позволяет кодировать сообщения с энтропией меньше 1 бита на символ. Т.к. большинство алгоритмов арифметического кодирования защищены патентами, далее будут описаны только основные идеи.
    Предположим, что в используемом алфавите N символов a_1,…,a_N, с частотами p_1,…,p_N, соответственно. Тогда алгоритм арифметического кодирования будет выглядеть следующим образом:
    В качестве рабочего полуинтервала взять }