72941-1 (665032), страница 2
Текст из файла (страница 2)
Если Счетчик = 0 тогда Выходной_поток = Текущий_байт
Счетчик = Счетчик + 1
Если Счетчик = 255 тогда
Выходной_поток = Счетчик – 1
Счетчик = 0
Конец если
Иначе
Если Счетчик > 0 тогда Выходной_поток = Счетчик – 1
Выходной_поток = Текущий_байт
Предыдущий_байт = Текущий_байт
Счетчик = 0
Конец если
Конец цикла
Как работает декодер
Здесь алгоритм еще проще. При декодировании бывший выходной поток является уже входным потоком, а получающийся выходной поток – это декодированная информация. Так вот, извлекая из входного потока байт, сразу же выбрасываем его в выходной поток. Далее сравниваем текущий байт с предыдущим байтом. Как только они одинаковы, извлекаем из входного потока байт, который является счетчиком повторов. Именно столько раз в выходной поток копируем текущий байт (что был перед счетчиком).
Предыдущий_байт = Взять_байт_из_входного_потока
Выходной_поток = Предыдущий_байт
Бесконечный цикл
Текущий_байт = Взять_байт_из_входного_потока
Выходной_поток = Текущий_байт
Если Текущий_байт = Предыдущий_байт тогда
Счетчик = Взять_байт_из_входного_потока
Цикл Счетчик раз Выходной_поток = Текущий_байт
Конец если
Предыдущий_байт = Текущий_байт
Конец цикла
И на всякий случай привожу ассемблерный код алгоритма декодирования. Код, естественно, рассчитан опять под аппаратное устройство, то есть дешевую плату с микропроцессором (нет памяти, используются три регистра, работа через порты ввода-вывода), которое находится на противоположной стороне транспортной магистрали и занимается банальным декодированием приходящего из транспортной магистрали потока. Тут входной порт микропроцессора подключен к транспортной магистрали, а выходной порт - к чему-нибудь еще, куда затем направляется раскодированный поток.
Decode_Unbuffred_RLE: // -----------------------
//
in al, Number_of_InputPort // AL = первый байт из входного потока
out Number_of_OutputPort, al // записать байт в выходной поток
mov ah, al // этот байт теперь становится предыдущим
//
Get_from_InputStream: // -----------------------
//
in al, Number_of_InputPort // AL = следующий байт из входного потока
out Number_of_OutputPort, al // записать байт в выходной поток
cmp al, ah // равен ли он предыдущему байту?
mov ah, al // этот байт теперь становится предыдущим
jnz Get_from_InputStream // если байты не одинаковы, взять следующий байт
//
in al, Number_of_InputPort // AL = следующий байт из входного потока
mov bl, al // BL = счетчик повторов
mov al, ah // восстановить в AL текущий байт
//
Copy_Byte: //------------------------
//
cmp bl, 0 // есть ли еще повторы байта?
jz Get_from_InputStream // если нет, взять следующий байт
out Number_of_OutputPort, al // записать байт в выходной поток
dec bl // BL = еще один байт скопировали
jmp Copy_Byte // копировать байт дальше
Все, рассказ закончен. Будем полагать, вы осведомлены теперь, а значит подготовлены. Возникни у вас похожая задача, решение готово. Напомню только, что алгоритм эффективен с позиций строгих ограничений, накладываемых на исполняющие аппаратные устройства. Никаких привилегий в степени сжатия он не дает, ибо это всего лишь собрат RLE, который используют ту же самую методику сжатия. Если в RLE за счет принудительного введения поля счетчика оказывается по одному лишнему байту на каждую "запись" для разнобоев, то в Unbuffered RLE этот байт не затрачивается ввиду отсутствия "записей" для разнобоев, но зато каждая "запись" для повторов теперь занимает по 3 байта, и вот здесь затрачивается один лишний байт.
Список литературы
Для подготовки данной работы были использованы материалы с сайта http://www.sciteclibrary.ru