Алгоритм RLE
1. Описание алгоритма
RLE - алгоритм сжатия данных, который оперирует сериями данных, то есть последовательностями, в которых один и тот же символ встречается несколько раз подряд. При кодировании строка одинаковых символов, составляющих серию, заменяется строкой, которая содержит сам повторяющийся символ и количество его повторов.
Очевидно, что такое кодирование эффективно для данных, содержащих большое количество серий, например, для простых графических изображений, таких как иконки и графические рисунки. Однако это кодирование плохо подходит для изображений с плавным переходом тонов, таких как фотографии.
Псевдокод сжатия:
1.Пока не конец Входного потока
.1.Читать Символ
.2.Текущий символ равно Символ
.3.Длина цепочки равна 1
1.4.Пока Текущий символ равен Символ И не конец Входного потока
.4.1.Читать Текущий символ
1.4.2.Если Текущий символ равен Символ, то
.4.2.1.Увеличить Длину цепочки
.5.Символ равно Текущий символ
1.6.Если Длина цепочки больше 1, то
.6.1.Записать в Выходной поток: Признак повторения, Длину цепочки и Символ
1.7.Иначе
.7.1.Вынести Символ в Выходной поток
Псевдокод декодирования:
1.Пока не конец Входного потока
.1.Читать Символ
.2.Если Символ равен Признаку повторения, то
.2.1.Развернуть цепочку в Выходной поток
.3.Иначе
1.3.1.Вывести в Выходной поток Символ
2. Пример и описание реализации
Пример:
Символ повторения:!
Входной поток: AAAAABBBBACCCC
Выходной поток:! 5A! 4B A! 4C
В моей реализации я не кодирую символы, если длина последовательности меньше 3. Так как при последовательности: AABB; мы получим:! 2A! 2B. А это на 33% больше исходного потока. Также при обнаружении, при сжатии, во входном потоке символа обозначающий признак повторения, то он кодируется как Признак_повторенияNПризнак_повторения. Причем N будет находиться в значении от 1. Например: A! B; кодируется как: A! 1! B.
3. Анализ эффективности
Теоретическая оценка
При кодировании с помощью алгоритма RLE, длина выходного потока может оказаться больше входного, если в нём часто встречается признак повторения в последовательности меньше 3 символов, и редко встречаются другие последовательности длиной больше 3 символов.
В итоге мы можем получить следующие степени сжатия при условии что число вариантов символа равно максимальному числу повторения:
·Максимальная степень сжатия: , где N - это число вариантов одного символа; практически возможно только в том случае, если все символы во входном потоке встречаются только в последовательности длина которой равна максимальному числу повторений.
·Минимальная степень сжатия: , но такой вариант возможен только при наличии во входном потоке только 1 символа, который является признаком повторения, что практически не встречается
·Средняя же оценка сильно зависит от входного потока, а именно от типа сжимаемого файла
4. Экспериментальная оценка
Для анализа эффективности были выбраны файлы различного типа и разного размера. Полученные результаты представлены в следующих таблицах:
Тип файлаРазмер исходного файла (байт)Размер сжатого файла (байт)Степень сжатия111.txt2 4492 449100%222.jpg43 81644 026100,48%333.docx125 124123 71998,88%444.doc168 960151 23189,51%555.bmp747 57434 5854,64%666.exe3 941 3123 962 809100,55%777.avi733 470 870738 582 664100,7%
Визуальная эффективность сжатия показана на следующей диаграмме:
Из полученных результатов можно сделать вывод о том, что степень сжатия зависит от типа файла. Файлы JPEG, DOCX, AVI, DOC являются уже сжатыми и поэтому практически не поддаются сжатию используя алгоритм RLE, либо вообще получаем отрицательный эффект. Файлы TEXT и EXE сильно зависят от содержания поэтому тут возможно различные варианты. А файлы BMP являются несжатыми и в большинстве случаев сжатие происходит с хорошим коэффициентом.
5. Исходный код
.cs:
using System;System. Collections. Generic;System. ComponentModel;System. Data;System. Drawing;System. Linq;System. Text;System. Windows. Forms;System.IO;RLE
{partial class Form1: Form
{File;FileCode;FileDecode;RLE;Form1 ()
{();= new RLE();. Percent += new IntHandler (RLE_PercentChanged);
}RLE_PercentChanged (int t) {ProgressBar. Value = t;}void Packed (object sender, EventArgs e)
{(! RLE. IsBusy)
{. FileName = «»;. Filter = «»;(sender == null || OpenDialog. ShowDialog() == DialogResult.OK)
{(sender == null) OpenDialog. FileName = File;. FileName = OpenDialog. FileName +».rle»;. Filter = «Файлы RLE|*.rle»;. AddExtension = true;. CreatePrompt = false;(SaveDialog. ShowDialog() == DialogResult.OK)
{(SaveDialog. FileName == OpenDialog. FileName)
{.IO. File. Move (OpenDialog. FileName, OpenDialog. FileName +».bak»);= OpenDialog. FileName +».bak»;
}
{= OpenDialog. FileName;
}= SaveDialog. FileName;. Code (File, FileCode);
}
}
}. Show («Дождитесь окончания процесса!», «Сообщение», MessageBoxButtons.OK, MessageBoxIcon. Information);
}void UnPacked (object sender, EventArgs e)
{(! RLE. IsBusy)
{. FileName = «»;. Filter = «Файлы RLE|*.rle|Все файлы|*.*»;(sender == null || OpenDialog. ShowDialog() == DialogResult.OK)
{(sender == null) OpenDialog. FileName = FileCode;rle =».rle»;isNorm = true;(int i = 0; i < 4 && isNorm; i++)(OpenDialog. FileName [OpenDialog. FileName. Length - 4 + i]!= rle[i])= false;(isNorm). FileName = OpenDialog. FileName. Remove (OpenDialog. FileName. Length - 4, 4);. FileName = OpenDialog. FileName;. CreatePrompt = false;(SaveDialog. ShowDialog() == DialogResult.OK)
{(SaveDialog. FileName == OpenDialog. FileName)
{.IO. File. Move (OpenDialog. FileName, OpenDialog. FileName +».bak»);= OpenDialog. FileName +».bak»;
}
{= OpenDialog. FileName;
}= SaveDialog. FileName;. Decode (FileCode, FileDecode);
}
}
}. Show («Дождитесь окончания процесса!»);
}void Form1_FormClosing (object sender, FormClosingEventArgs e)
{(RLE. IsBusy)
{(MessageBox. Show («Вы уверены что хотите прервать процесс?», «Выход», MessageBoxButtons. YesNo) == DialogResult. Yes)
{. Stop(true);. Cancel = false;
}. Cancel = true;
}
}void Packed_DragDrop (object sender, DragEventArgs e)
{[] s = (string[]) e. Data. GetData (DataFormats. FileDrop, false);(s!= null)(s. Length == 1)
{= s[0];(null, null);
}. Show («Копируйте по одному файлу!», «Сообщение», MessageBoxButtons.OK, MessageBoxIcon. Information);
}void UnPacked_DragDrop (object sender, DragEventArgs e)
{[] s = (string[]) e. Data. GetData (DataFormats. FileDrop, false);(s!= null)(s. Length == 1)
{= s[0];(null, null);
}. Show («Копируйте по одному файлу!», «Сообщение», MessageBoxButtons.OK, MessageBoxIcon. Information);
}void DragEnter (object sender, DragEventArgs e)
{(e. Data. GetDataPresent (DataFormats. FileDrop)). Effect = DragDropEffects. Move;. Effect = DragDropEffects. None;
}
}
}
RLE.cs:
using System;System. Collections. Generic;System. Linq;System. Text;System.IO;System. Windows. Forms;System. ComponentModel;RLE
{void IntHandler (int t);RLE
{enum Pack {Packed, Unpacked};Str
{Pack PK;string Input;string Output;
}BW;event IntHandler Percent;byte UN = 66;Pred, Tek, Count;Reader;Writer;RLE()
{= new BackgroundWorker();. DoWork += new DoWorkEventHandler (BW_DoWork);. RunWorkerCompleted += new RunWorkerCompletedEventHandler (BW_RunWorkerCompleted);. ProgressChanged += new ProgressChangedEventHandler (BW_ProgressChanged);. WorkerReportsProgress = true;. WorkerSupportsCancellation = true;
}void Stop (bool isForce)
{. CancelAsync();(Percent!= null) Percent(0);(! isForce) MessageBox. Show («Отменено»);
}BW_ProgressChanged (object sender, ProgressChangedEventArgs e)
{(Percent!= null) Percent (e. ProgressPercentage);
}BW_RunWorkerCompleted (object sender, RunWorkerCompletedEventArgs e)
{(! e. Cancelled)
{(Percent!= null) Percent(100);(e. Result!= null)
{(e. Result. GetType() == typeof(string)). Show((string) e. Result);. Show («Выполнено», «Сообщение», MessageBoxButtons.OK, MessageBoxIcon. Information);
}. Show («Выполнено», «Сообщение», MessageBoxButtons.OK, MessageBoxIcon. Information);
}
}BW_DoWork (object sender, DoWorkEventArgs e)
{File, FileCode, FileDecode;Proc;((e. Argument as Str).PK == Pack. Packed)
{. ReportProgress(0);= 0;= (e. Argument as Str).Input;= (e. Argument as Str).Output;= new BinaryReader (new FileStream (File, FileMode. Open));= new BinaryWriter (new FileStream (FileCode, FileMode. Create));L = 0;= -1; Tek = -1; Count = 0;
{= Reader. ReadByte();++;
{(BW. CancellationPending)new ApplicationException();(Proc!= (int) (L * 100 / AllByte))
{= (int) (L * 100 / AllByte);. ReportProgress((int) (L * 100 / AllByte));
}(Tek!= Pred)
{();= 1;
}//Tek == Pred
{(Count == 255)
{();= 1;
}++;
}= Tek;= Reader. ReadByte();++;
} while (true);
}(EndOfStreamException)
{(Tek == -1). Show («Файл пуст»);
{();. Close();ResLen = (new FileInfo(FileCode)).Length;. Result = «Сжатие выполнено успешно!\nРазмер Исходного файла:» + string. Format(«{0:0,0.###}», (double) AllByte / 1024.0) +
«KB\nРазмер Сжатого файла:» + string. Format(«{0:0,0.###}», (double) ResLen / 1024.0) +
«KB\nСтепень сжатия:» + string. Format(«{0:F2}», (double) ResLen / (double) AllByte * 100.0) + «%»;
}. Close();. Close();
}(ApplicationException)
{. Close();. Close();.IO. File. Delete(FileCode);
}
}
///////////////////////////////////////////////////// ((e. Argument as Str).PK == Pack. Unpacked)
{. ReportProgress(0);= 0;= (e. Argument as Str).Input;= (e. Argument as Str).Output;= new BinaryReader (new FileStream (FileCode, FileMode. Open));= new BinaryWriter (new FileStream (FileDecode, FileMode. Create));L = 0;
{
{(BW. CancellationPending)new ApplicationException();= Reader. ReadByte();++;
// Proc = (int) (L * 100 / AllByte);(Proc!= (int) (L * 100 / AllByte))
{= (int) (L * 100 / AllByte);. ReportProgress((int) (L * 100 / AllByte));
}(Tek!= UN)
{. Write((byte) Tek);
}
{= Reader. ReadByte();= Reader. ReadByte();+= 2;(Count = 0; Count < Pred; Count++). Write((byte) Tek);
}
} while (true);
}(EndOfStreamException)
{. Close();. Close();
}(ApplicationException)
{. Close();. Close();.IO. File. Delete(FileDecode);
}
}
}InputUN()
{. Write(UN);. Write((byte) 1);. Write(UN);
}InputPred()
{(Count > 0)
{
/*if (Pred == UN)();*/(Count > 1)
{(Count == 2 && Pred!= UN)
{. Write((byte) Pred);. Write((byte) Pred);
}
{. Write(UN);. Write((byte) Count);. Write((byte) Pred);
}
}if (Count == 1)
{(Pred == UN)();. Write((byte) Pred);
}
}
}AllByte;
void Code (string File, string FileCode)
{(! BW. IsBusy)
{info = new FileInfo(File);= (long) info. Length;. RunWorkerAsync (new Str {PK = Pack. Packed, Input = File, Output = FileCode});
}
{. Show («Дождитесь окончания процесса!»);
}
}
bool IsBusy {get {return BW. IsBusy;}}
void Decode (string FileCode, string FileDecode)
{(! BW. IsBusy)
{info = new FileInfo(FileCode);= (long) info. Length;. RunWorkerAsync (new Str {PK = Pack. Unpacked, Input = FileCode, Output = FileDecode});
}
{. Show («Дождитесь окончания процесса!»);
}
}
}
}
Список литературы
алгоритм программа сжатие файл
1.«Структуры данных и алгоритмы сжатия информации без потерь» - Методическое пособие, Пантеллев Е.Р. - Иваново 2001 г.
2. http://ru.wikipedia.org/wiki/RLE
Больше работ по теме:
Предмет: Информационное обеспечение, программирование
Тип работы: Контрольная работа
Новости образования
КОНТАКТНЫЙ EMAIL: [email protected]
Скачать реферат © 2017 | Пользовательское соглашение
ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ