3.14. Компрессия экрана.
Если Ваша программа содержит большое количество графичес-
ких изображений, причем они не исполняются самой программой, а
подготовлены ранее, например в графическом редакторе, то возни-
кает вопрос о необходимости каким-либо образом компрессировать
изображения, обеспечив возможности хранения максимума экранов в
ограниченном объеме памяти.
Все методы компрессии данных строятся на том, что надо
выявить повторяющиеся последовательности и заменить их на код,
который содержит указание на то, что это за последовательность
и каков при этом коэффициент повторения. На сегодняшний день
известны самые разнообразные приемы, например основанные на
том, что наиболее часто повторяющиеся символы, такие как "A"
кодируются не кодом ASCII (который равен 65), а своим каким-то
кодом, например 01, соответственно символ "E" например кодом 02
и т.п. В результате получается, что битовая конструкция симво-
лов содержит много нулей, которые можно "ужать", т.е. на символ
в среднем расходуется не 8 битов, как обычно, а в среднем 4-5
(до 6). Такой метод применим при компрессии текстовых блоков
общего назначения.
Если текст имеет специфику, например это текст адвентюрной
программы, в которой часто повторяются определенные слова и
словосочетания, то компрессия может основываться на создании
резидентного словаря на 256 позиций и замене этих слов или
словосочетаний по тексту на их порядковый номер. Излишне
говорить о том, что и генерацию такого словаря и кодирование
текста выполняют не вручную, а написав для этого служебную
процедуру.
В нашем случае речь идет о компрессии графики, а она
обладает той спецификой, что здесь особенно часто встречаются
повторяющиеся символы. Так, например, сплошная горизонтальная
линия через весь экран представляет из себя 32 следующих подряд
байта, каждый из которых равен 255. Этим обычно и пользуются
при компрессии графики. Мы должны отметить, что алгоритмов
компрессии графики может быть бесконечно много и ни один из них
не является абсолютным. То есть для каждого алгоритма можно
подобрать такую раскладку экрана, при которой он будет выпол-
нять максимальное сжатие, но для каждого же можно подобрать и
такие условия, при которых компрессированный файл окажется
больше исходного по величине. В свое время этот вопрос получил
некоторое обсуждение на страницах "ZX-РЕВЮ" (N1, 1991,с. 6,
N2, 1991,с. 24).
Процедура компрессии "снимает" изображение с экрана, ком-
прессирует его и отправляет на хранение в выделенную для этого
область оперативной памяти компьютера, после чего готова к
приему нового экрана. Компрессированные изображения сохраняются
в оперативной памяти последовательно и могут быть восстановлены
оттуда с помощью декомпрессирующей программы.
Назовем процедуру компрессии FN n(h,l), где:
h - старший байт адреса, с которого начинается область,
отведенная для компрессированных изображений;
l - младший байт этого адреса.
h,l < 255.
Задание процедуры: DEF FN n(h,l) = USR 56600
Вызов процедуры : RANDOMIZE FN n(h,l)
10 REM *** Загрузчик машинного кода
20 LET adr=56600: LET long=60: LET z=0
30 FOR i=0 TO long-1: READ a
40 POKE (adr+i),a: LET z=z+a
50 NEXT i
60 LET z=INT (((z/long)-INT (z/long))*long)
70 READ a
80 IF a<>z THEN PRINT "??": STOP
500 REM ***Данные для машинного кода
510 DATA 42, 11, 92, 1, 4
520 DATA 0, 9, 86, 14, 8
530 DATA 9, 94, 237, 83, 82
540 DATA 221, 33, 0, 64, 6
550 DATA 1, 126, 44, 32, 8
560 DATA 36, 245, 124, 254, 91
570 DATA 40, 16, 241, 78, 185
580 DATA 32, 4, 4, 32, 238
590 DATA 5, 18, 19, 120, 18
600 DATA 19, 24, 227, 241, 18
610 DATA 19, 120, 18, 237, 83
620 DATA 22, 221, 201, 0, 0
630 DATA 56, 0, 0, 0, 0
Дисассемблер программы:
56598 NEXT_S DEFW ;В эту программную пере-
;менную заносится адрес, с
;которого может быть нача-
;то хранение очередного
;экрана после того, как
;данная процедура отрабо-
;тает.
56600 2A0B5C LD HL,(5C0BH) ;См. с. 109...111
56603 010400 LD BC,0004 ;Сдвиг от DEFADD на 4 бай-
56606 09 ADD HL,BC ;та (см. c.109...111).
56607 56 LD D,(HL) ;Параметр h.
56608 0E08 LD C,08 ;Сдвиг на
56610 09 ADD HL,BC ;восемь байтов.
56611 5E LD E,(HL) ;Параметр l.
56612 ED5352DD LD(ADDR),DE ;Запомнили h и l в прог-
;раммной переменной по ад-
;ресу 56658.
56616 210040 LD HL,4000 ;Адрес начала дисплейного
;файла.
56619 0601 RETURN LD B,01 ;Инициализация счетчика
;повторяющихся байтов.
56621 7E LD A,(HL) ;Приняли текущий байт.
56622 2C AGAIN INC L ;И перешли к следующему.
56623 2008 JR NZ,PASS ;Если регистр L еще не пе-
;реполнен, то обход.
56625 24 INC H ;В противном случае нара-
;щиваем старший регистр H.
56626 F5 PUSH AF ;Проверка
56627 7C LD A,H ;на конец
56628 FE5B CP 5B ;экранной области.
56630 2810 JR Z,END ;Переход на завершение ра-
;боты, если экран исчерпан
56632 F1 POP AF
56633 4E PASS LD C,(HL) ;Очередной байт приняли в
;регистр C и сравнили его
56634 B9 CP C ;с предыдущим в A.
56635 2004 JR NZ,PASS_1 ;Если нет повтора, то об-
;ход на PASS_1.
56637 04 INC B ;Если есть повтор, то на-
;ращиваем счетчик повтора
56638 20EE JR NZ,AGAIN ;и переходим на AGAIN для
;проверки очередного байта
;экрана.
56640 05 DEC B ;Если счетчик обнулился,
;т.е. переполнился, умень-
;шаем его на единицу и пе-
;рестаем наращивать.
56641 12 PASS_1 LD (DE),A ;Перенесли байт из экрана
;в буфер и указатель в бу-
56642 13 INC DE ;фере переставили вверх.
56643 78 LD A,B ;Ввели коэффициент повтора
56644 12 LD (DE),A ;и заслали его в буфер.
56645 13 INC DE ;Переставили указатель в
;буфере вверх.
56646 18E3 JR RETURN ;Возврат для обработки
;очередного байта.
56648 F1 END POP AF ;Восстановление стека.
56649 12 LD (DE),A ;Последний байт выдается
;в буфер
56650 13 INC DE ;Туда же выдается его
56651 78 LD A,B ;коэффициент повтора
56652 12 LD (DE),A ;из регистра B.
56653 ED5316DD LD (NEXT_S),DE ;Адрес конца буфера фикси-
;руется в переменной.
;Он может быть использован
;например для того, чтобы
;знать где можно начинать
;сохранение следующего эк-
;рана.
56657 C9 RET
56658 ADDR DEFW ;Адрес, с которого начи-
;нается в ОЗУ область хра-
;нения нашего скомпресси-
;рованного экрана.
3.15. Декомпрессия экрана.
Файлы скомпрессированных экранов можно восстановить из
ОЗУ и снова поместить на экран. Для этого служит декомпресси-
рующая программа FN o(h,l). Здесь:
h - старший байт адреса, начиная с которого хранится Ваше
компрессированное изображение;
l - младший байт этого адреса.
h,l < 255.
Задание процедуры: DEF FN o(h,l) = USR 56500
Вызов процедуры : RANDOMIZE FN o(h,l)
10 REM *** Загрузчик машинного кода
20 LET adr=56500: LET long=35: LET z=0
30 FOR i=0 TO long-1: READ a
40 POKE (adr+i),a: LET z=z+a
50 NEXT i
60 LET z=INT (((z/long)-INT (z/long))*long)
70 READ a
80 IF a<>z THEN PRINT "??": STOP
500 REM ***Данные для машинного кода
510 DATA 42, 11, 92, 1, 4
520 DATA 0, 9, 86, 14, 8
530 DATA 9, 94, 33, 0, 64
540 DATA 26, 245, 19, 26, 19
550 DATA 71, 241, 119, 35, 16
560 DATA 252, 124, 254, 91, 32
570 DATA 240, 201, 0, 0, 0
580 DATA 28, 0, 0, 0, 0
В результате работы компрессирующей программы сжатое
изображение хранится в оперативной памяти и имеет следующий
формат:
----T---T---T---T----------------T---T---T------¬
¦ B1¦ K1¦ B2¦ K2¦ ........... ¦Bi ¦ Ki¦..... ¦
L---+---+---+---+----------------+---+---+-------
Здесь Bi - i-ый байт изображения, а Ki - коэффициент его
повтора (от 0 до 255). Процедура декомпрессии предельно проста.
Байты из памяти берутся парами. Коэффициент повтора становится
параметром цикла и в этом цикле байт изображения помещается на
экран (на адрес в экранной области указывает регистровая пара
HL). Сигналом к окончанию работы является момент выхода H за
пределы, отведенные для экранной области.
Дисассемблер программы:
56500 2A0B5C LD HL,(5C0BH) ;См. с. 109...111.
56503 010400 LD BC,0004 ;Сдвиг от DEFADD на 4 бай-
56506 09 ADD HL,BC ;та (см. c. 109...111).
56507 56 LD D,(HL) ;Параметр h.
56508 0E08 LD C,08 ;Сдвиг на
56510 09 ADD HL,BC ;восемь байтов.
56511 5E LD E,(HL) ;Параметр l.
56512 210040 LD HL,4000 ;Начало дисплейного файла.
56515 1A AGAIN LD A,(DE) ;Приняли байт из оператив-
;ной памяти.
56516 F5 PUSH AF ;Запомнили его на стеке.
56517 13 INC DE ;Переход к новому байту.
56518 1A LD A,(DE) ;Приняли очередной байт
;(это коэффициент повтора)
56519 13 INC DE ;Переход к новому байту.
56520 47 LD B,A ;В регистре B организуется
;счетчик повторов.
56521 F1 POP AF ;Восстановили байт экрана.
56522 77 LOOP LD (HL),A ;И поместили его на экран.
56523 23 INC HL ;Следующий байт экрана.
56524 10FC DJNZ LOOP ;Повторяем цикл от LOOP
;столько раз, каков коэф-
;фициент повтора.
56526 7C LD A,H ;Проверяем на окончание
56527 FE5B CP 5BH ;экранную область памяти.
56529 20F0 JR NZ,AGAIN ;Если еще не конец, то
;продолжаем работу.
56531 C9 RET ;Возврат.
Уважаемый читатель!
Скоро исполнится десять лет со дня выхода на широкую
арену первого "Спектрума". По нашим данным первую партию
компьютеров этой серии сэр К.Синклер продемонстрировал на
предновогодней выставке-продаже в декабре 1982 года.
За это время в мире накоплен огромный теоретический и
практический опыт работы с этой самой массовой и доступной
машиной. Самый большой пласт открытий и достижений находится в
тех тысячах высококачественных программ, которые доступны Вам
для работы, отдыхы, развлечения и, самое главное - обучения.
Компьютерная программа - не книжка с картинками, в которой
все просто и понятно, но это, тем не менее, все-таки учебник
для того, кто любит исследовательскую работу. Трудно работать с
учебником, в котором все непонятно и здесь мы видим свою
главную задачу - дать основные понятия, показать наезженные и
освоенные приемы и подходы. Если теперь разбираясь с машинным
кодом фирменной программы Вы хоть чуть-чуть почувствуете
ощущение, что где-то я это видел и это мне знакомо, значит наша
цель наполовину достигнута.
Конечно, мы затронули только самый край всего того, что
накоплено в области компьютерной графики. Но, во первых, мы с
Вами не прощаемся и готовим новые книги, а во-вторых, мы
надеемся, что Вы начнете самостоятельное планомерное исследо-
вание.
Пройдут годы, сменятся модели компьютеров и языки
программирования, но опыт, который Вы сейчас приобретаете с
маленьким "Спектрумом", останется точно так же, как останутся
основные алгоритмы и приемы, а самое главное - останется и
закрепится особый алгоритмический образ мышления, который
поможет Вам легко освоить любую технику и любые языки
программирования.
С уважением. "ИНФОРКОМ"