Универсальная процедура построения рисунка
В данном разделе описана универсальная процедура построения рисунка формата 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.
Замечание
Напомним, что дополнительная коррекция и проверка значения счетчика повторов цикла (сх) нужна потому, что при нечетном количестве точек в рисунке последний байт содержит код только одной точки (младшую тетраду выводить на экран нельзя).