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

         

Построение полноцветного рисунка формата BMP



Пример 7.25. Построение полноцветного рисунка формата BMP

BigBmp : pusha сохранение "всех" регистров
PushReg <fs,Cur win> сохранение fs и Cur win
mov fs, SwpSeg fs = сегмент буфера обмена
mov SwpOffs, 0 очистка смещения в сегменте
mov dx, iwidth dx = количество точек в строке
neg dx dx = — iwidth
call calloffs bx = (horsize + iwidth) *bytppnt
mov ax, 03 ax = 3
mul iwidth ax = 3*iwidth, утроенный размер строки
mov dx , ax сохраняем его в dx
add ax, 03 с помощью. двух команд округляем
and al, OFCh размер строки до значения, кратного 4


mov f width, ax fwidth = размер строки в файле
sub ax, dx вычисляем добавку к адресу
mov rmndr, ax и сохраняем ее в rmndr
mov ax, -1 ах = 65535
mov numbyte, ax numbyte = 65535
xor dx, dx очистка старшей части делимого
div fwidth ах = 65535 / fwidth (частное от деления)
mov part, ax part = число строк в порции для чтения
sub numbyte, dx numbyte = numbyte — ах
mov ax, iheight ах = количество строк в рисунке
mov remline, ax remline — счетчик числа строк
dec ax ах = номер последней строки
mul bperline ах = (iheight — l)*bperline
add di, ax di = адрес последней строки рисунка
adc dx, 00 учитываем возможный перенос
mov ax, GrUnit ах = GrUnit (единица измерения окон)
mul dl вычисляем добавку к номеру окна
add Cur win, ax номер окна для последней строки
call Setwin установка окна
NewPart mov ex, numbyte сх = количество считываемых байтов
call Readf чтение порции в буфер обмена
jnc sucread -> чтение прошло без ошибок
/ Здесь должны выполнять ся действия в 'случае ошибки при чтении
sue re ad mov ex, part сх = кол-во строк в полной порции
cmp remline, ex считана полная порция данных ?
jae @F -> да, обходим следующую команду
mov ex, remline нет, сх = оставшееся число строк
@@: sub remline, ex уменьшаем значение счетчика строк
xor si, si si = начало буфера обмена
drwout : push ex сохраняем\ значение счетчика строк
mov ex, iwidth сх = размер строки- (в точках)
call drawline построение очередной строки
pop ex восстанавливаем счетчик строк
add s i , rmndr корректируем адрес в буфере обмена
sub di, bx di = адрес начала предыдущей строки
jnc @F -> адрес в пределах текущего окна
call PrevWin установка предыдущего окна
@@: loop drwout управление циклом построения строк
cir.p remline, 0 остались не обработанные строки ?
jne NewPart -> да, на чтение следующей порции
PopReg <Cur win, f s> восстановление Cur win и fs
popa восстановление "всех" регистров
call Setwin восстановление исходного окна
ret возврат из подпрограммы

Выполнение примера 7.25 начинается с сохранения в стеке содержимого "всех" регистров. Команда pusha не сохраняет сегментные регистры, поэтому содержимое fs и переменной cur_win сохраняет макровызов pushReg.

Для чтения данных вызывается подпрограмма Readf, текст которой приведен в примере 3.23. Она размещает данные в буфере обмена, начиная с адреса, указанного в swpoffs. Для максимального использования пространства буфера эта переменная предварительно очищается, а в регистр fs записывается сегмент буфера обмена из SwpSeg.

После этого выполняются подготовительные действия, смысл и назначение которых описаны выше. Три первые команды вычисляют константу для коррекции адресов строк, ее значение помещается в регистр bx и используется в основном цикле. Следующие восемь команд формируют значения переменных fwidth и rmndr. Затем шесть команд вычисляют значения переменных part и numbyte. Последние десять команд формируют адрес начала последней строки рисунка в видеопамяти и устанавливают окно, которому он принадлежит.

Основной цикл имеет метку NewPart. Он практически совпадает с одноименным циклом примера 7.24. Отличие заключается в следующем. При переадресации строк видеопамяти вычисляется адрес начала предыдущей строки, поэтому содержимое регистра bx вычитается из содержимого регистра di, а в случае переполнения результата вычитания устанавливается предыдущее окно видеопамяти. Кроме того, для исключения "лишних" точек адрес буфера обмена, хранящийся в регистре si, увеличивается на величину rmndr. Ну и, конечно же, имя drawiine соответствует разным подпрограммам.



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