Иллюстрированный самоучитель по SVGA

Построение рисунка снизу вверх

При работе с BMP-файлами произвольного размера основным способом является построение изображения снизу вверх. В таком случае строки образа рисунка считываются в порядке их расположения в файле, а выводятся на экран начиная с последней строки рисунка.

Такой способ уже использовался для построения полноцветных рисунков формата BMP, он описан в соответствующем разделе, а текст соответствующей подпрограммы показан в примере 7.25. Отличие рассматриваемого здесь случая только в том, образ рисунка использует палитру, а коды его точек могут занимать 1, 4 или 8 разрядов.

Описание предварительных действий

Перед началом построения рисунка подпрограмма вычисляет адрес начала последней строки в видеопамяти, размер считываемой из файла порции данных в байтах, количество содержащихся в ней строк образа рисунка и значение константы для переадресации строк видеопамяти. Опишем, как это делается.

Адрес начала последней строки рисунка в видеопамяти вычисляется следующим способом. Расстояние между первой и последней строкой равно (iheight -i)*bperiine байтов. В общем случае произведение занимает два слова. Содержимое младшего слова прибавляется к адресу начала первой строки. Содержимое старшего слова преобразуется в номер окна, который прибавляется к номеру окна, в котором находится первая строка. Вычисленное значение окна надо установить.

Количество строк в порции считываемых данных (part) вычисляется как частное от деления числа 65 535 на размер строки в файле (fwidth). Умножив part на fwidth, получим размер порции для чтения в байтах.

Замечание
Вместо умножения можно вычесть остаток от деления из числа 65 535
.

Константа переадресации строк, видеопамяти.
После записи кодов точек текущей строки в видеопамять определяется адрес начала предыдущей. Для этого текущий адрес видеопамяти уменьшается на величину, вычисляемую по формуле (iwidth + horsize) *bytppnt. Если при вычитании вырабатывается признак переноса, то устанавливается предыдущее окно видеопамяти, в противном случае текущее окно не изменяется.

Подпрограмма BigBmp

Текст подпрограммы, выполняющей построение рисунка описанным способом, приведен в примере А.10. Перед ее вызовом адрес левого верхнего угла рисунка помещается в регистр di и устанавливается окно видеопамяти, которому принадлежит этот адрес. Регистр ез должен содержать код видеосегмента. Если в тексте вместо call drawiine записана команда call bx, то в регистре bх указывается адрес подпрограммы построения строки.

Пример А.10. Построение рисунка формата BMP снизу вверх.

BigBmp: pusha сохранение "всех" регистров
PushReg <gs,fs,Cur w in>; сохранение gs, fs и Cur win
mov ax, iheight ax = iheight, количество строк в рисунке
mov remline, ax remline = ах, количество строк в рисунке
dec ax учет нумерации строк с нуля
mul bperline dx:ax = (iheight – l)*bperline
add di, ax di = адрес последней строки рисунка
adc dx, 00 учитываем возможный перенос
mov ax, GrUnit ах = GrUnit (единица измерения окон)
mul dl вычисляем добавку к номеру окна
add Cur win, ax номер окна для последней строки
call Setwin установка вычисленного окна
mov ax, – 1 ах = 65535
xor dx, dx очистка старшей части делимого
div fwidth ах = 65535 / fwidth (частное от деления)
mov part, ax part = число строк в порции для чтения
mul fwidth ах = ах* fwidth
mov numbyte, ax размер порции считываемой в байтах
mov ax, iwidth ах = iwidth
add ax, horsize ах = iwidth + horsize
mul bytppnt ах = (iwidth + horsize) *bytppnt, dx = 0
mov dx, ax сохраняем для коррекции адресов
mov fs, SwpSeg fs = сегмент буфера обмена
mov SwpOffs, 0 очистка смещения в сегменте
mov gs, GenSeg!! gs = сегмент таблицы цветов
NewPart: mov ex, numbyte сх = количество считываемых байтов
call Readf чтение порции в буфер обмена
jnc sr › чтение прошло без ошибок
; Здесь должны выполниться действия при ошибке чтения
sr: mov ex, part сх = кол-во строк в полной порции
cmp remline, ex считана полная порция данных?
jae @F › да, обходим следующую команду
mov ex, remline нет, сх = оставшееся число строк
@@: sub remline, ex уменьшаем значение счетчика строк
xor si, si si = начало буфера обмена
drwout: push зх сохраняем значение счетчика строк
mov ex, iwidth ex = размер строки (в точках)
call drawline!! или call bx – построение строки
pop ex восстанавливаем счетчик строк
add si, rmndr корректируем адрес в буфере обмена
sub di, dx di = адрес начала предыдущей строки
jnc @F › адрес в пределах текущего окна
call PrevWin установка предыдущего окна
@@: loop drwout управление циклом построения строк
cmp remline, 0 остались не обработанные строки?
jne NewPart › да, на чтение следующей порции
PopReg <Cur_win,fs,gs>; восстановление Cur_win, fs и gs
рора восстановление "всех" регистров
call Setwin восстановление исходного окна
ret возврат из подпрограммы

Выполнение подпрограммы примера А.10. начинается с подготовительных действий, смысл и назначения которых описаны выше. Основной цикл имеет метку NewPart. Если вы сравните его с одноименным циклом примера 7.25, то убедитесь в их полном совпадении, поэтому мы не будем повторять описание выполняемых действий.

Таким образом, основной цикл построения ВМР-файлов произвольного размера не зависит от того, как подготовлен образ исходного рисунка, – с использованием или без использования палитры цветов. От этого зависят только подпрограммы drawline, вызываемые для построения строк рисунков.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.