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

         

Преобразование палитры в форматы Hi-Color

Для того чтобы с палитрой можно было работать, ее надо прочитать из файла, содержащего образ рисунка, в оперативную память. Расположение палитры в файле и ее размеры зависят от стандарта хранения графических данных, которому соответствует выбранный вами файл. Никакого единообразия тут нет, но всегда остается возможность преобразовать файл в тот стандарт, с которым вы предпочитаете работать. Большинство графических редакторов позволяют сделать такое преобразование.

Способы чтения палитры файлов стандартов BMP и PCX описаны, соответственно, в приложении А и в разделе. В обоих случаях мы советовали размешать прочитанную палитру в буфере обмена, сегмент которого хранится в переменной swpseg, расположенной в разделе данных задачи.

Независимо от стандарта, для определения размера и местонахождения палитры в файле надо, прежде всего, прочитать и проанализировать его заголовок. При чтении заголовок помещается в буфер обмена, поэтому к моменту начала обработки палитры в регистре fs находится код сегмента (копия переменной Swpseg), а в si — адрес начала палитры в памяти.



При анализе заголовка файла определяются две важные величины — количество строк (цветов) в палитре и ее размер. Напомним, что он в три или в четыре раза больше количества строк. Размер нужен при чтении палитры, а количество строк — при ее преобразовании в таблицу цветов. Перед вызовом описываемых ниже подпрограмм количество строк указывается в регистре сх.

После чтения палитры вызываются описываемые ниже подпрограммы. Они формируют таблицу (одномерный массив), содержащую коды цветов, формат которых соответствует установленному видеорежиму. Для хранения таблицы надо выделить пространство оперативной памяти. Учитывая, что количество цветов в исходной палитре не больше 256-ти, в режимах Hi-Color размер указанного пространства памяти составляет 256 слов (512 байтов).

Расположение таблицы цветов

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

Напомним, смещение и сегмент буфера общего назначения хранятся в следующих переменных, которые должны быть описаны в разделе данных:

GenOffs dw 0 ; адрес (смещение) в буфере общего назначения
GenSeg dw 0 ; сегмент, содержащий буфер общего назначения

Способы выделения пространства для размещения буфера описаны в приложении Б данной книги. После его выделения становится известным значение сегмента, которое задача должна сохранить в GenSeg. Исходное значение Genoffs равно нулю, а текущее значение зависит от того, какая часть буфера используется в данный момент времени.
Все приведенные ниже подпрограммы используют следующие входные параметры:

  • адрес начала преобразуемой палитры указан в регистрах fs:si;
  • размер палитры (в виде количества строк) в регистре сх;
  • адрес начала формируемой таблицы цветов указывают переменные Genseg и GenOffs;
  • результат преобразований помещается в таблицу цветов.

Теперь о преобразованиях. Формируемый код цвета зависит от установленного видеорежима Hi-Color. Существует две разновидности этих режимов. В одном случае код цвета занимает 15, а в другом 16 разрядов, расположение базовых цветов для обоих случаев показано в табл. 7.1. Мы рассмотрим два варианта подпрограмм, формирующих 15-разрядный код цвета, и обсудим, как сформировать 16-разрядный код цвета.

Палитра формата rgb

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

Пример 7.17. Преобразование палитры rgb в 15-разрядный код

cnvpal: PushReg <ax,bx,cx,di,si,es>; сохранение содержимого регистров
les di, dword ptr GenOffs; es:di = адрес таблицы цветов
modcol: mov al, fs:[si] ; читаем код красного цвета в al
shr al, 03 ; сокращаем его до 5-ти разрядов
mov bh, fs:[si+1] ; читаем код зеленого цвета в bh
shld ax, fax, 05 ; !! или shld ax, bx, 06
mov bh, fs: [si-t-2] читаем код синего цвета в bh
shld ax, bx, 05 сдвигаем и дополняем код в ах
add si, 03 адрес следующей строки палитры
stosw записываем новый код цвета
loop modcol управление повторами цикла
PopReg <es,si,di,cx,bx,ax> ; восстановление регистров
ret возврат из подпрограммы

В примере 7.17 основную роль играет команда shld, напомним ее особенности. При выполнении команды содержимое первых двух операндов, в данном случае это регистры ах и bx, сдвигается как одно 32-разрядное слово, но записывается только старшая часть результата в первый операнд, а содержимое второго операнда не изменяется. Таким образом, в примере 7.17 команда shld сдвигает содержимое регистра ах на пять разрядов влево и записывает в освободившееся место пять старших разрядов регистра bх.

В зависимости от установленного видеорежима код зеленого цвета может занимать 5 или 6 разрядов. В комментарии показано, как изменится одна из команд shld в случае формирования 16-разрядного кода цвета.

Устаревший формат палитры PCX. В разделе 4.4 говорилось о том, что существует устаревший формат 256-цветной палитры, поддерживаемый версией стандарта PCX, разработанной фирмой Genius. Если вам надо работать с файлом, соответствующим этому стандарту, то проще всего преобразовать его в основной стандарт фирмы ZSoft. Это можно сделать, например, с помощью графического редактора Photofinish фирмы ZSoft.

Палитры формата bgr и bgr0

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

Пример 7.18. Преобразование палитры bgr в 15-разрядный код

cnvpal: PushReg < ax,b x, ex, di , si,es>; сохранение содержимого регистров
les di, dwo :d ptr ( 5enOffs; es:di = адрес таблицы цветов
modcol : mov al, fs: [si+2] читаем код красного цвета в al
shr al, 03 сокращаем его до 5-ти разрядов
mov bh, fs: [si+1] читаем код зеленого цвета в bh
shld ax, bx, 05 ! ! или shld ax, bx, 06
mov bh, fs: [si] читаем код синего цвета в bh
shld ax, bx, 05 сдвигаем и дополняем код в ах
add si, 03 ! ! для формата "bgrO" — add si, 04
stosw записываем новый код цвета
loop modcol управление повторами цикла
PopReg <es,si ,di, ex, зх,ах> ; восстановление регистров
ret возврат из подпрограммы

Если вы сравните тексты примеров 7.17 и 7.18, то обнаружите, что в них различаются только индексные выражения у первой и третьей команд пересылки. За счет такого трюка мы считывает базовые цвета в том порядке, в котором они должны располагаться в формируемом коде.

В примере 7.18 появилась вторая переменная команда, выполняющая переадресацию строк палитры. При работе с форматом bgr значение адреса увеличивается на 3, а с форматом bgr0 — на 4. На практике нет никакой необходимости работать с переменной командой, ее второй операнд просто не должен зависеть от размера строки палитры.
Палитры форматов bgr и bgr0 используются в двух разных версиях стандарта BMP.

Заголовки файлов обрабатываются по единой схеме, не зависящей от версии (см. приложение А данной книги). При обработке заголовка обязательно определяется размер строки палитры т. к. он нужен при всех манипуляциях с палитрой. Поэтому вторым операндом команды add si, оз должно быть не значение константы, а имя регистра или переменной, в котором (в которой) хранится размер строки палитры.

Универсальный вариант подпрограммы

В обоих приведенных примерах от установленного режима Hi-Color зависит третий операнд одной из команд shid. От переменной команды можно избавиться следующим способом.

При выполнении задачей подготовительных действий обязательно считывается массив info, содержащий наиболее важные характеристики установленного видеорежима. В частности, в байте этого массива со смещением 2in указан размер кода зеленого цвета. В режимах Hi-color там находится число 5 или 6. Это число надо сохранить в специально выделенном байте, присвоив ему удобное для вас имя, например gcoisize, и использовать в подпрограммах примеров 7.17 и 7.18 при обработке зеленого цвета.
Причем величина сдвига может быть либо явно указана в записи команды, либо помещена в регистр el, который применяется в качестве первого операнда команды. В примерах 7.17 и 7.18 регистр сх используется в качестве счетчика, поэтому понадобятся две дополнительные команды для сохранения и восстановления его содержимого. Таким образом", одна переменная команда shid может быть заменена следующей группой команд:

push сх ; сохраняем счетчик повторов цикла
mov cl, gcoisize ; cl = величина сдвига (5 или 6)
shid ах, bx, cl ; сдвиг на величину, указанную в cl
pop сх ; восстанавливаем счетчик повтором цикла

Учитывая, что цикл преобразований повторяется не более 256-ти раз, дополнительные потери времени будут не столь велики, зато подпрограмма окажется применимой во всех видеорежимах Hi-Color.


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