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

         

Манипуляции с палитрой

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

Палитра применяется в тех случаях, когда цвет не указан в коде точки (biBitcnt = 1, 4 или 8), она содержит описание используемых в рисунке цветов и состоит из строк, количество которых изменяется от 2 до 256. Строка содержит полный код цвета и занимает 3 (формат OS/2) или 4 (формат Windows) байта. Базовые цвета расположены в строке в следующем порядке: синий, зеленый, красный, в формате Windows к ним добавлен пустой байт, т. е. строки хранятся в форматах bgr или bgr0.

Характеристики палитры

Для работы с палитрой надо вычислить значения трех величин, которые мы обозначим как paddr — адрес начала палитры в буфере обмена, pniine — количество строк (цветов) в палитре и pbpi — количество байтов в строке палитры. Они определяются так:



Шаг 8. Вычисляем адрес начала палитры (paddr) как сумму значения поля isize и смещения этого поля (оно равно о Eh). Размер палитры в байтах вычисляется как разность содержимого поля bfOffBits (его смещение одь) и paddr. В зависимости от формата заголовка (Windows или OS/2) присваиваем переменной pbpi значение 4 или 3. Для определения формата заголовка проверяем значение paddr, если оно равно 36h, то это формат Windows, в противном случае — OS/2. Вычисляем pniine = paddr/pbpl.
Вычисление характеристик палитры показано в примере А.6.

Пример А.6. Определение характеристик палитры

mov di, fs: [si+OEh] di = размер Bitmap info
add di, OEh di = di + OEh, di содержит paddr
mov ax, fs: [si+OAh] ax = адрес начала образа рисунка
sub ax, di ах = размер палитры в байтах
mov bx, 04 полагаем pbpl = 4
cmp di, 36h заголовок формата Windows ?
jz @F -> да
dec Ы pbpl = 3
@ : xor dx, dx перед делением очищаем dx
div bx ах = количество строк в палитре
mov paddr, di ! ! сохраняем paddr (не обязательно)
mov pnline, ax !! сохраняем pnline (не обязательно)
mov pbpl, bx ! ! сохраняем pbpl (не обязательно)

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

После выполнения примера А.6 из заголовка получена информация, необходимая для построения рисунка и работы с палитрой. Если вы не планируете включить установку или преобразование палитры в описываемую десь подпрограмму, то в конец текста примера А.б добавьте команду ret.

Дальнейшие манипуляции с палитрой зависят от установленного задачей видеорежима. Если это один их режимов PPG, то ее надо установить, а если это один из режимов direct color, то преобразовать в таблицу цветов, кото-рая нужна для построения рисунка.

Установка палитры заключается в записи перечисленных в ней цветов в регистры цвета видеокарты (DAC-регистры). Эти регистры доступны только При работе в видеорежимах PPG. При простой установке в регистры записываются коды всех цветов без их предварительного анализа. Недостаток та-кого способа в том, что в результате установки палитры добавляемого рисунка небольшого размера могут измениться цвета точек основного изобра-жения, находящегося на экране. Для более рационального использования регистров видеокарты перед установкой палитры могут выполняться анализ и преобразование добавляемых цветов. Эти вопросы подробно обсуждались в разделе, разделе и разделе основной части книги. Здесь мы ограничимся простым примером.

В разделе описан способ простой установки палитры, хранящейся в файлах формата PCX. Рассмотрим аналогичные действия для вмр-файлов.

Напомним, что для записи кодов базовых цветов в регистры цвета видеокарты используется одна из функций прерывания int 10h. Существуют две ее разновидности — для записи кода в один регистр и для записи кодов в группу регистров. Нас будет интересовать последняя, поскольку она позволяет установить всю палитру за одно обращение к BIOS.

Подробное описание функций BIOS приведено в разделе. Нужная нам функция имеет код 12h. Перед ее вызовом надо подготовить палитру так, чтобы в каждой ее строке было записано по 3 байта, содержащих базовые цвета, расположенные в порядке rgb, причем коды цветов должны быть сокращены до шести разрядов (два старших разряда кода BIOS игнорирует).

Программная реализация преобразования и простой установки палитры показана в примере А.7, который является продолжением примера А.6.

Пример А.7. Преобразование и установка палитры

convert : mov ex, ax ex = количество строк в палитре
mov si, di si = di адрес начала палитры
push es сохраняем содержимое es
mov es, SwpSeg es = сегмент буфера обмена
push di сохраняем адрес начала палитры
push ex сохраняем количество строк
s Ip : mov al, fs: [si] al = код синего цвета
xchg al, fs: [si+2] перестановка кодов красного и синего
shr al, 02 сокращаем код красного до 6 разрядов
stosb es:di = al, di = di + 1
mov ax, fs: [si+1] ax = коды зеленого и синего цвета
shr ax, 02 сокращаем коды до 6 разрядов
and al, 3Fh очищаем в al 2 старших разряда
stosw es:di = ax, di = di + 2
add si, bx si = si + pbpl (pbpl = 3 или 4)
loop S_lp управление повторами цикла
setpal : pop ex восстанавливаем количество строк
pop dx восстанавливаем адрес палитры
xor bx, bx номер первого DAC-регистра
mov ax, 1012h ах = код запрашиваемой функции
int lOh BIOS устанавливает палитру
pop es восстанавливаем содержимое es
ret возврат из подпрограммы

Напомним, что после выполнения примера А.6 в регистрах находятся следующие величины: ах — количество строк в палитре, bх — размер строки в байтах, di — адрес начала палитры. Выполнение примера А.7 начинается с формирования содержимого регистров, используемых при преобразовании палитры. Для этого в сх копируется содержимое ах, а в si — содержимое di. Исходное содержимое es сохраняется и в него записывается код сегмента буфера обмена. Адрес и количество строк будут нужны при установке палитры, поэтому содержимое регистров сх и di сохраняется в стеке.

Цикл преобразования имеет метку s_ip. В нем производятся перестановка красного и синего и сокращение кодов базовых цветов до 6-ти разрядов. Первая команда цикла считывает код синего базового цвета в регистр ai, a вторая команда переставляет содержимое регистра ai и байта со смещением 2. В результате в ai оказывается код красного цвета, а в байте со смещением 2 — код синего цвета. Содержимое регистра ai сдвигается на 2 разряда вправо (сокращается до 6-ти разрядов) и записывается в буфер обмена. Зеленый и синий цвета обрабатываются совместно. Их коды считываются в регистр ах, его содержимое сдвигается на 2 разряда вправо, и очищаются два старших разряда ai. Результат записывается в буфер обмена. Описанные действия повторяются для каждой строки палитры.

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

После цикла преобразования, начиная с команды, имеющей метку setpai, выполняется установка палитры. Размер палитры вйталкивается из стека в регистр сх, а адрес ее начала в dx. Для записи, начиная с нулевого DAc-регистра, bx очищается. В регистр ах помещается код запроса и происходит обращение к BIOS для установки палитры. После возврата из BIOS из стека восстанавливается исходное значение es и подпрограмма BitMap завершается, поскольку она выполнила все предусмотренные действия.

Построение таблицы цветов

Если задача работает в одном из режимов direct color, то регистры цвета видеокарты не используются. В таких случаях исходная палитра преобразуется в таблицу, содержащую коды базовых цветов точек в формате, соответствующем установленному видеорежиму. Другими словами, надо преобразовать строки исходной палитры, упаковав базовые цвета в 16-разрядное слово для режимов Hi-Color или в 32-разрядное слово для режимов True color. Таблица цветов используется для преобразования кодов точек при построении рисунка.

Способы построения таблицы цветов описаны в разделe (для режимов Hi-color) и разделe (для режимов True color). Здесь мы ограничимся примерами ДЛЯ реЖИМОВ True Color.

В указанных разделах предполагалось, что таблица цветов размещается в буфере общего назначения. Код сегмента, содержащего этот буфер, хранится в переменной GenSeg, а адрес свободного пространства в нем находится в переменной Genoffs. Таким образом, пара переменных GenSeg и GenOffs задает полный адрес начала таблицы цветов в оперативной памяти.

Если заголовок файла соответствует формату Windows, то исходная палитра просто копируется в буфер общего назначения. А если заголовок файла соответствует формату OS/2, то при копировании палитры к базовым цветам каждой строки надо добавить пустой байт.

Программная реализация построения таблицы цветов показана в примере А.8, который является продолжением примера А.6. Предполагается, что в регистрах находятся следующие данные: ах — количество строк в палитре, bx — размер строки в байтах, di — адрес начала палитры.

Пример А.8. Построение таблицы цветов для режимов True Color

TabCol: mov si, di si = адрес начала палитры
push es сохраняем содержимое es
les di, dword ptr GenOffs; es:di = адрес таблицы цветов
sub bx, 03 уменьшаем содержимое bx на 3
mov ex, ax ex = количество строк в палитре
modcol: movs word ptr [di], fs [si]; копируем 2 младших байта
lods byte ptr fs:[si] читаем в регистр al третий байт
xor ah, ah очищаем старший байт регистра ах
stosw записываем 2 старших байта
add si, bx корректируем адрес для чтения
loop modcol управление повторами цикла
pop es восстановление содержимого es
ret возврат из подпрограммы BitMap

Пример А.8 является несколько измененным вариантом примера 7.19. При выполнении подготовительных действий добавлено формирование содержимого регистров bx, сх и si, а в цикл построения таблицы включена команда add si, bx для пропуска пустого байта, если заголовок соответствует формату Windows.

Если ваша задача устанавливает один из режимов Hi-color, то возьмите за основу пример 7.18 и внесите в него аналогичные изменения.

Заключение.
Основные действия, выполняемые при обработке заголовка файла, описаны в примерах А.2—А.4 и А.6. Если манипуляции с палитрой будет выполнять специализированная подпрограмма, то после выполнения примера А.6 надо завершить выполнение подпрограммы BitMap. Если же BitMap устанавливает палитру или формирует таблицу цветов, а это желательно, то она завершается после выполнения соответствующих действий. В таком случае при выходе из BitMap использованы все данные, находящиеся в буфере обмена, и его содержимое больше не нужно.


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