Графические устройства

         

Универсальная процедура построения рисунка

В данном разделе описана универсальная процедура построения рисунка формата BMP, использующего палитру цветов. Двухцветные и 16-цветные рисунки хранятся в упакованном виде, поэтому процедура выбирает нужную подпрограмму для их распаковки. Будем так же считать, что в зависимости от размера файла выбираются подпрограммы из примеров А.9 или А10.

Текст процедуры приведен в примере А. 11, программы описаны ниже.

Пример А.11. Начало построения рисунка формата BMP

BmpShow: lea bx, mode_8 ; bx = адрес подпрограммы mode_8
cmp bitcnt, 08 ; bitcnt = 8 ?
je @F ; -> да, переход на локальную метку
lea bx, mode_4 bx = адрес подпрограммы mode_4
cmp bitcnt, 04 bitcnt = 4 ?
je @F -> да, переход на локальную метку
lea bx, mode__2 bx = адрес подпрограммы mode_2
@@: mov ax, fwidth ax = fwidth, размер строки в файле


mul iheight dx:ax = fwidth*iheight
or dx, dx образ рисунка помещается в сегменте ?
jne @F -> нет, файл большого размера
mov si, ax si = размер образа рисунка
jmp Smlbmp переход на Smlbmp
@@: jmp BigBmp переход на BigBmp

Для того чтобы выполняемые в примере А. 11 действия имели смысл, в текстах примеров А.9 и А.10 надо заменить call drawiine на call bx, как указано в комментарии. Первые 7 команд примера А. 11 формируют в bх адрес подпрограммы обработки строки (примеры А.12—А.14), в зависимости от размера кода точки образа рисунка. После этого вычисляется размер образа рисунка, и если он помещается в одном сегменте (dx=o), то выбирается подпрограмма Smlbmp, в противном случае BigBmp.

Таким образом, для построения рисунка формата BMP задача должна обращаться к процедуре BmpShow, как к подпрограмме. Перед ее вызовом в регистре di указывается адрес левого верхнего угла рисунка в видеопамяти и устанавливается окно, которому принадлежит этот адрес. Регистр es должен содержать код видеосегмента (хранящийся в vbuff).

Подпрограммы обработки строк

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

В примере А.12 приведена подпрограмма, выполняющая построение строки рисунка, у которого код точки занимает 1 байт. Ее отличие от описанных ранее вариантов только в том, что для записи кода точки вызывается вспомогательная подпрограмма outpnt.

Пример А.12. Вывод строки формата 8 бит на точку (256 цветов)

mode_8: lods byte ptr f s:[si] ; al = код очередной точки
call outpnt ; обращение к подпрограмме записи
loop mode_8 ; управление повторами цикла
ret ; возврат из подпрограммы
В примере А. 13 приведен текст подпрограммы, выполняющей распаковку точек 16-цветного рисунка в процессе построения строки.

Пример А.13. Вывод строки формата 4 бита на точку (16 цветов)

mode 4 : lods byte ptr fs: [si] al = код очередных 2-х точек
push ax сохраняем содержимое ах
shr al, 04 выделяем код старшей тетрады
call outpnt обращение к подпрограмме записи
pop ax. восстанавливаем содержимое ах
dec ex сх = сх — 1, счетчик точек в строке
je @F -> все точки выведены
and al, OFh выделяем код младшей тетрады
call outpnt обращение к подпрограмме записи
loop mode 4 управление повторами цикла
§@: ret возврат из подпрограммы

Сравните текст примера А.13 с текстом подпрограммы drwiin4 (см. пример 3.17). В данном случае он упростился за счет использования вспомогательной подпрограммы outpnt.

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

В примере А. 14 приведен текст подпрограммы, выполняющей распаковку 2-цветных рисунков в процессе построения строки.

Пример А.14. Вывод строки формата 1 бита на точку (2 цвета)

mode 2 : lods byte ptr fs: [si] al = код очередных восьми точек
mov ah, 80h ah = константа для выделения разряда
md 21: push ax сохраняем содержимое ах
and al, ah выделяем текущий разряд
je md_22 если нуль, то обходим одну команду
mov al, 01 иначе записываем в al единицу
md 22: call outpnt обращение к подпрограмме записи
pop ax восстанавливаем содержимое ах
dec ex сх = сх — 1, счетчик точек в строке
je md_23 -> все точки выведены
shr ah, 01 изменяем константу выделения
jne md_21 -> если обработаны не все точки
jmp short mode 2 -> если обработано 8 точек
md 23: ret возврат из подпрограммы

Сравните текст примера А. 14 с текстом подпрограммы drwiinl (см. пример 3.18).

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

Подпрограммы записи кодов точек существенно зависят от видеорежима. Если задача установила один из видеорежимов PPG, то в самом простом случае выполняются действия, показанные в примере А. 15.

Пример А.15. Простой вывод точки в режимах PPG

outpnt: stosb ; запись кода точки в видеопамять
or di, di ; адрес ь пределах сегмента?
jne @F ; -> да
call NxtWin ; нет, установка следующего окна
@@: ret ; возврат из подпрограммы

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

При работе в режимах PPG палитра может быть установлена с изменением исходного расположения базовых цветов. В разделе мы подробно обсуждали, в каких случаях и почему используется такая установка палитры. При любом изменении расположения цветов, описанных в палитре, требуется изменение кодов точек при их записи в видеопамять. Один из вариантов перекодировки был показан в примере 4.8.

При работе в режимах direct color перекодировка производится в тех случаях, когда используется таблица цветов. Вариант подготовки такой таблицы показан в примере А.8. Размер строки таблицы, а следовательно, и действия, выполняемые при перекодировке, зависят от установленного видеорежима. При режимах Hi-Color строка таблицы занимает 2 байта, а при режимах True color — 4 байта. В примере А. 16 приведена подпрограмма, выполняющая перед записью в видеопамять перекодировку точек по таблице цветов.

Пример А.16. Перекодировка точек в режимах direct color

outpnt : push eax ; сохранение содержимого еах
and eax, OFFh ; очистка старших разрядов еах shl ax, wrdppnt ; учет размера строки таблицы
add e.x, GenOffs ; ax = смещение начала таблицы
mov ax, qs:[eax] ; !! или mov eax, gs:[eax] для True Color
stosw ; !! или stosd для режимов True Color
pop eax ; восстановление содержимого eax
ret ; возврат из подпрограммы

Текст примера А. 16 является простым повторением текста примера 7.22. Дополнительные подробности вы найдете в разделе.

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


Содержание раздела