на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Алгоритмы сжатия данных
p align="center">Адаптивная модель для арифметического кодирования

Программа должна работать с моделью, которая предоставляет пару перекодировочных таблиц index_to_char[] и char_to_index[], и массив накопленных частот cum_freq[]. Причем к последнему предъявляются следующие требования:

cum_freq[i-1] >= cum_freq[i];

никогда не делается попытка кодиpовать символ i, для котоpого

cum_freq[i-1] = cum_freq[i];

cum_freq[0] <= Max_frequency.

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

Она изменяет частоты уже найденных в тексте символов. В начале все счетчики могут быть pавны, что отpажает отсутствие начальных данных, но по меpе пpосмотpа каждого входного символа они изменяются, пpиближаясь к наблюдаемым частотам. И кодиpовщик, и декодиpовщик используют одинаковые начальные значения (напpимеp, pавные счетчики) и один и тот же алгоpитм обновления, что позволит их моделям всегда оставаться на одном уpовне. Кодиpовщик получает очеpедной символ, кодиpует его и изменяет модель. Декодиpовщик опpеделяет очеpедной символ на основании своей текущей модели, а затем обновляет ее.

При инициализации все частоты устанавливаются в 0. Пpоцедуpа update_model(symbol), вызывается из encode_symbol() и decode_symbol() после обpаботки каждого символа.

Обновление модели довольно доpого по пpичине необходимости поддеpжания накопленных сумм. В пpогpамме используемые счетчики частот оптимально pазмещены в массиве в поpядке убывания своих значений, что является эффективным видом самооpганизуемого линейного поиска. Пpоцедуpа update_model() сначала пpовеpяет новую модель на пpедмет пpевышения ею огpаничений по величине накопленной частоты, и если оно имеет место, то уменьшает все частоты делением на 2, заботясь пpи этом, чтобы счетчики не пpевpатились в 0, и пеpевычисляет накопленные значения. Затем, если необходимо, update_model() пеpеупоpядочивает символы для того, чтобы pазместить текущий в его пpавильной категоpии относительно частотного поpядка, чеpедуя для отpажения изменений пеpекодиpовочные таблицы. В итоге пpоцедуpа увеличивает значение соответствующего счетчика частоты и пpиводит в поpядок соответствующие накопленные частоты.

Эффективность сжатия

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

1. pасходы на завеpшение текста;

2. использование аpифметики небесконечной точности;

3. такое масштабиpование счетчиков, что их сумма не пpевышает max_frequency.

Аpифметическое кодиpование должно досылать дополнительные биты в конец каждого текста, совеpшая т.о. дополнительные усилия на завеpшение текста. Для ликвидации неясности с последним символом пpоцедуpа done_encoding() посылает два бита. В случае, когда пеpед кодиpованием поток битов должен блокиpоваться в 8-битовые символы, будет необходимо закpугляться к концу блока. Такое комбиниpование может дополнительно потpебовать 9 битов.

Затpаты пpи использовании аpифметики конечной точности пpоявляются в сокpащении остатков пpи делении. Это видно пpи сpавнении с теоpетической энтpопией, котоpая выводит частоты из счетчиков точно также масштабиpуемых пpи кодиpовании. Здесь затpаты незначительны - поpядка 10- 4 битов/символ.

Дополнительные затpаты на масштабиpование счетчиков отчасти больше, но все pавно очень малы. Для коpотких текстов (меньших 214 байт) их нет. Hо даже с текстами в 105 - 106 байтов накладные pасходы, подсчитанные экспеpиментально, составляют менее 0.25% от кодиpуемой стpоки.

Адаптивная модель, пpи угpозе пpевышения общей суммой накопленных частот значение max_frequency, уменьшает все счетчики. Это пpиводит к тому, что взвешивать последние события тяжелее, чем более pанние. Т.о. показатели имеют тенденцию пpослеживать изменения во входной последовательности, котоpые могут быть очень полезными.

Заключение

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

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

Для реализации использовался язык C# и визуальная среда программирования Microsoft Visual Studio 2005. В результате программное обеспечение очень компактно, интуитивно понятно и эффективно в работе.

Список литературы

1. Ватолин Д., Ратушняк А., Смирнов М., Юкин В. Методы сжатия данных. Устройство архиваторов, сжатие изображений и видео. - М.: ДИАЛОГ-МИФИ, 2002. - 384 с.

2. Сэломон Д. Сжатие данных, изображений и звука. Data Compression Methods. Серия: Мир программирования. Издательство: Техносфера, 2004. - 368 с.

3. Артюшенко В. М., Шелухин О. И., Афонин М. Ю. Цифровое сжатие видеоинформации и звука. Издательство: Дашков и Ко, 2004. - 426 с.

4. Седжвик Р. Фундаментальные алгоритмы на C++. Части 1-4. Анализ. Структуры данных. Сортировка. Поиск. Издательство: ДиаСофт, 2002. - 688 с.

Приложение 1. Программный код

// Количество бит для кода

const int bits_in_register = 16;

// Максимально возможное значение кода

const int top_value = (int)(((long)1 << bits_in_register) - 1);

// Диапазоны

const int first_qtr = (top_value / 4 + 1);

const int half = (2 * first_qtr);

const int third_qtr = (3 * first_qtr);

// Количество символов алфавита

const int no_of_chars = 256;

// Специальный символ Конец файла

const int eof_symbol = (no_of_chars + 1);

// Всего символов в модели

const int no_of_symbols = (no_of_chars + 1);

// Порог частоты для масштабирования

const int max_frequency = 16383;

// Таблицы перекодировки

public int[] index_to_char = new int[no_of_symbols];

public int[] char_to_index = new int[no_of_chars];

// Таблицы частот

public int[] cum_freq = new int[no_of_symbols + 1];

public int[] freq = new int[no_of_symbols + 1];

// Регистры границ и кода

public static long low, high;

public static long value;

// Поддержка побитовых операций с файлами

public static long bits_to_follow;

// Буфер

public static int buffer;

// Количество бит в буфере

public static int bits_to_go;

// Количество бит после конца файла

public static int garbage_bits;

// Указатель на входной файл

FileStream datain;

// Указатель на выходной файл

FileStream dataout;

//--------------------------------------------------------------

// Инициализация адаптивной модели

public void start_model ()

{

int i;

// Установки таблиц перекодировки

for ( i = 0; i < no_of_chars; i++)

{

char_to_index [i] = i + 1;

index_to_char [i + 1] = i;

}

// Установка счетчиков накопленных частот

for ( i = 0; i <= no_of_symbols; i++)

{

freq [i] = 1;

cum_freq[i] = no_of_symbols - i;

}

freq [0] = 0;

}

//------------------------------------------------------------

// Обновление модели очередным символом

void update_model(int symbol)

{

// Новый индекс

int i;

int ch_i, ch_symbol;

int cum;

// Проверка на переполнение счетчика частоты

if (cum_freq[0] == max_frequency)

{

cum = 0;

/* Масштабирование частот при переполнении (если счетчики частот достигли своего максимума, то делим на пополам) */

for (i = no_of_symbols; i >= 0; i--)

{

freq[i] = (freq[i] + 1) / 2;

cum_freq[i] = cum;

cum += freq[i];

}

}

/* Обновление перекодировочных таблиц в случае перемещения символа */

for (i = symbol; freq[i] == freq[i - 1]; i--) ;

if (i < symbol)

{

ch_i = index_to_char[i];

ch_symbol = index_to_char[symbol];

index_to_char[i] = ch_symbol;

index_to_char[symbol] = ch_i;

char_to_index[ch_i] = symbol;

char_to_index[ch_symbol] = i;

}

// Увеличить значение счетчика частоты для символа

freq[i] += 1;

// Обновление значений в таблицах частот

while (i > 0)

{

i -= 1;

cum_freq[i] += 1;

}

}

//------------------------------------------------------------

// Инициализация побитового ввода

void start_inputing_bits ()

{

bits_to_go = 0;

garbage_bits = 0;

}

//------------------------------------------------------------

// Ввод очередного бита сжатой информации

int input_bit ()

{

int t;

// Чтение байта если буфер пуст

if (bits_to_go == 0)

{

buffer = datain.ReadByte();

if (buffer == -1)

{

/* Помещение битов после конца файла, с проверкой небольшого их количества */

garbage_bits += 1;

if (garbage_bits > bits_in_register - 2)

{

Application.Exit();

}

eof = buffer;

}

bits_to_go = 8;

}

// Выдача очередного бита с правого конца

t = buffer & 1;

buffer >>= 1;

bits_to_go -= 1;

return t;

}

//------------------------------------------------------------

// Инициализация побитового вывода

public void start_outputing_bits ()

{

buffer = 0;

bits_to_go = 8;

}

//------------------------------------------------------------

// Вывод очередного бита сжатой информации

public void output_bit(int bit)

{

// Бит - в начало буфеpа

buffer >>= 1;

if (bit == 1)

buffer |= 0x80;

bits_to_go -= 1;

// Вывод полного буфера

if (bits_to_go == 0)

{

dataout.WriteByte((byte)buffer);

bits_to_go = 8;

}

}

//------------------------------------------------------------

// Очистка буфера побитового вывода

public void done_outputing_bits ()

{

dataout.WriteByte((byte)(buffer >> bits_to_go));

}

//------------------------------------------------------------

// Вывод указанного бита и отложенных ранее

public void output_bit_plus_follow(int bit)

{

output_bit(bit);

while (bits_to_follow > 0)

{

output_bit(~bit + 2);

bits_to_follow--;

}

}

//------------------------------------------------------------

// Инициализация регистров границ и кода перед началом сжатия

public void start_encoding()

{

// Полный кодовый интервал

low = 0L;

high = top_value;

bits_to_follow = 0L;

}

//------------------------------------------------------------

// Очистка побитового вывода

public void done_encoding ()

{

/* Вывод двух бит, определяющих четверть, лежащую в текущем интервале */

bits_to_follow++;

if (low < first_qtr)

output_bit_plus_follow (0);

else

output_bit_plus_follow (1);

}

//------------------------------------------------------------

/* Инициализация регистров перед декодированием.

Загрузка начала сжатого сообщения*/

void start_decoding ()

{

int i;

int a;

value = 0L;

// Воод бит для заполнения значения кода

for (i = 1; i <= bits_in_register; i++)

{

a = input_bit();

value = 2 * value + a;

}

// Текущий интервал равен исходному

low = 0L;

high = top_value;

}

//------------------------------------------------------------

// Кодирование очередного символа

public void encode_symbol(int symbol)

{

// Ширина текущего кодового интервала

long range;

range = (long)(high - low) + 1;

// Пересчет значений границ

high = low + (range*cum_freq[symbol - 1]) / cum_freq[0] - 1;

low = low + (range*cum_freq[symbol]) / cum_freq[0];

// Вывод битов

for ( ; ; )

{

// Если в нижней половине

if (high < half)

output_bit_plus_follow(0);

// Если в верхней половине

else if (low >= half)

{

output_bit_plus_follow(1);

low -= half;

high -= half;

}

/* Если текущий интервал содержит середину, то вывод еще одного обратного бита позже */

else if (low >= first_qtr && high < third_qtr)

{

bits_to_follow += 1;

low -= first_qtr;

high -= first_qtr;

}

else

break;

// Расширить текущий рабочий кодовый интервал

low = 2 * low;

high = 2 * high + 1;

}

}

//------------------------------------------------------------

// Декодирование очередного символа

int decode_symbol ()

{

// Ширина интервала

long range;

// Накопленная частота

int cum;

// Декодируемый символ

int symbol;

int a;

// Определение текущего масштаба частот

range = (long) (high - low) + 1;

// Hахождение значения накопленной частоты для value

cum=(int)((((long)(value-low)+1)*cum_freq[0]-1)/ range);

// Поиск соответствующего символа в таблице частот

for (symbol = 1; cum_freq [symbol] > cum; symbol++);

// Пересчет границ

high = low + (range*cum_freq[symbol - 1]) / cum_freq[0] - 1;

low = low + (range * cum_freq [symbol]) / cum_freq [0];

// Удаление очередного символа из входного потока

for (;;)

{

// Расширение нижней половины

if (high < half)

{

}

// Расширение верхней половины

else if (low >= half)

{

value -= half;

low -= half;

high -= half;

}

// Расширение середины

else if (low >= first_qtr && high < third_qtr)

{

value -= first_qtr;

low -= first_qtr;

high -= first_qtr;

}

else

break;

// Увеличение масштаба интервала

low = 2 * low;

high = 2 * high + 1;

// Добавить новый бит

a = input_bit();

value = 2 * value + a;

}

return symbol;

}

//--------------------------------------------------------------

// Собственно адаптивное арифметическое кодирование

public void encode(string infile, string outfile)

{

int ch, symbol;

try

{

dataout = new FileStream(outfile, FileMode.Create);

}

catch (IOException exc)

{

return;

}

try

{

datain = new FileStream(infile, FileMode.Open);

}

catch (FileNotFoundException exc)

{

return;

}

start_model();

start_outputing_bits();

start_encoding();

// Цикл обработки символов

for ( ; ; )

{

try

{

// Чтение исходного символа

ch = datain.ReadByte();

}

catch (Exception exc)

{

return;

}

// Выход при достижении конца файла

if (ch == -1)

break;

// Найти рабочий символ

symbol = char_to_index[ch];

// Закодировать символ

encode_symbol(symbol);

// Обновить модель

update_model(symbol);

}

// Закодировать символ конца файла

encode_symbol(eof_symbol);

// Завершение кодирования

done_encoding();

done_outputing_bits();

dataout.Close();

datain.Close();

}

//------------------------------------------------------------

// Собственно адаптивное арифметическое декодирование

void decode(string infile, string outfile)

{

int ch, symbol;

try

{

dataout = new FileStream(outfile, FileMode.Create);

}

catch (IOException exc)

{

return;

}

try

{

datain = new FileStream(infile, FileMode.Open);

}

catch (FileNotFoundException exc)

{

return;

}

start_model ();

start_inputing_bits ();

start_decoding ();

// Цикл обработки сиволов

for (;;)

{

// Получаем индекс символа

symbol = decode_symbol ();

if (symbol == eof_symbol)

break;

// Получаем декодированный символ

ch = index_to_char [symbol];

// Записываем в выходной файл

dataout.WriteByte((byte)ch);

// Обновляем модель

update_model (symbol);

}

dataout.Close();

datain.Close();

}

Приложение 2. Интерфейс программы

Примечание. Для работы программы необходим Microsoft .NET Framework 2.0.

Страницы: 1, 2, 3, 4



© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент.