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

         

Наложение строки тумана заданного цвета



Пример 7.32. Наложение строки тумана заданного цвета

Foglin: PushReg <bx, dx> ; сохранение регистров bx, dx
f og_l : push ex ; сохранение счетчика повторов
lods byte ptr f s : [si] ; al = alpha [i]
mov byte ptr falpha, al ; falpha = al запоминаем alpha [i]
push si сохраняем содержимое si
lea si, fogcol si = адрес переменной fogcol
mov ex, 03 для обработки трех базовых цветов
f og_2 : lodsb al = базовый цвет тумана (F[j])
mov Ы, es: [di] Ы = базовый цвет точки (Y[i,j]>
xor ah, ah преобразуем байт в слово
xor bh, bh преобразуем байт в слово
sub ax, bx ах = F[j] — Y[i,j]
imul falpha ах = ах * alpha [i]; dx = 0
xchg al, ah al = ax/256
add al, Ы al = al + Y[i,j]


stosb сохраняем результат в видеопамяти
loop fog 2 трехкратное повторение цикла
inc di пропуск резервного байта
jne @F -> адрес в пределах текущего окна
call NxtWin установка следующего окна
@@: Pop si восстановление адреса в si
pop ex восстановление счетчика повторов
loop fog 1 управление повторами цикла
PopReg <dx, bx> восстановление регистров dx, bx
ret возврат из подпрограммы

Значения alpha изменяются от 0 до 255, для сокращения размера файла их лучше хранить в виде байтов, но при умножении коэффициент alpha должен иметь размер слова. Поэтому в примере 7.32 введена специальная переменная falpha, имеющая размер слова. Ее надо описать в разделе данных задачи, присвоив нулевое значение.
Во внешнем цикле примера 7.32, по сравнению с примером 7.31, появились три новые команды. Первая из них считывает очередное значение alpha [i] в регистр al (и увеличивает содержимое si на 1). Вторая копирует содержимое ai в младший байт переменной faipha, а третья сохраняет в стеке адрес, находящийся в регистре si. Таким образом, в результате выполнения этих трех команд получено очередное значение alpha и освобожден регистр si. Теперь в него можно записать адрес переменной, содержащей цвет тумана, для использования во внутреннем цикле, это же делалось и в примере 7.31.

После выхода из внутреннего цикла восстанавливается находившийся в si адрес, и при повторе внешнего цикла будет выбрано следующее значение alpha из буфера обмена.
Для использования описанной подпрограммы надо подготовить файл, содержащий значения коэффициентов alpha. От их расположения в файле зависит способ построения рисунка, поэтому первыми должны располагаться коэффициенты для его верхней, а последними — для нижней строки. В таком случае построение будет производиться в направлении слева направо и сверху вниз, т. е. по наиболее простой схеме. Способ чтения файла в буфер обмена зависит от количества значений alpha. Например, для затягивания туманом всего изображения при разрешении 640x480 точек файл будет содержать 307 200 байтов и его придется считывать по частям.

Следовательно, перед построением риcунка надо вычислить размер считываемой порции данных (количество строк и байтов в порции). Мы это делали неоднократно.
Вычисление значений alpha. Вам понадобится специальная программа, формирующая файл, содержащий значения alpha для каждой точки затуманиваемого изображения. Значения alpha зависят от расстояния (r[i]) между текущей точкой (i) и точкой принятой за начало отсчета (точкой наблюдения). В линейном двухмерном дискретном пространстве это расстояние вычисляется как квадратный корень из суммы квадратов приращений значений координат:

r[i] = sqrt { (x[i] - х[0])**2 + (y[i] - у[0])**2}

Здесь ** обозначают степень, sqrt — квадратный корень, х[0] и у [0] — значения координат в точке наблюдения, x[i] и y[i] — текущие значения координат.

В общем случае значения alpha описываются некоторой функцией (F), зависящей от расстояния, т.е. alpha [i] = F(r[i]). Независимо от природы функции F значения alpha равны нулю в точке наблюдения и увеличиваются по мере удаления от точки наблюдения, не превышая при этом значение 255 (которое принято за 1).

Советуем вам начать с простого случая, когда F является нормированной чинейной функцией, у которой за норму принято значение г в максимально /деленной точке, т. е. alpha [i] = <r[i] / max) *255. В. результате получится }>айл, содержащий значения коэффициентов для тумана, плотность которого возрастает пропорционально расстоянию. Эксперименты с файлом позволят вам оценить степень соответствия линейной модели ожидаемым результатам.

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

alpha[i] = exp (-k*r[i]> или alpha[i] = exp {-(k*r[i])**2)

Замечание 1
Замечание 1

Программировать вычисление значений alpha на языке ассемблера вовсе не обязательно. Можно использовать любой удобный для вас язык. Главное, чтобы файл имел нужную структуру и содержание.

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



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