Манипуляции с палитрой цветов
При разработке графических программ сравнительно часто приходится решать следующую задачу. На экране находится исходное изображение, при построении которого использованы некоторые регистры цвета видеокарты. К нему добавляется новый рисунок, закрывающий только часть исходной картинки. Цвета не затронутой новым рисунком части экрана должны сохраниться. Поэтому при установке палитры добавляемого рисунка нельзя изменять содержимое уже используемых регистров цвета видеокарты.
В данном разделе будет показан способ записи новых цветов в свободные регистры видеокарты с исключением повторения одинаковых цветов. Он может быть полезен, например, при оформлении "рабочего стола", когда задача выводит на экран заставку, различные рамки, линейки, элементы меню, значки ярлыков и прочие оформительские атрибуты. Необходимые для этого рисунки обычно используют общую палитру, содержащую ограниченное количество цветов. Например, для Windows 3.X и ее. приложений создано много рисунков различных значков, хранящихся в виде BMP-файлов и пиктограмм, использующих стандартную (для Windows) 16-цветную палитру.
Системная палитра
Для того чтобы каждый раз при добавлении нового рисунка не считывать в оперативную память текущее содержимое регистров цвета видеокарты, имеет смысл постоянно хранить в оперативной памяти копию их текущего состояния. Эту копию мы будем называть системной палитрой.
При установке палитры добавляемого рисунка предпринимается попытка разместить ее в системной палитре и если она окажется успешной, то дополненная системная палитра, или только ее дополнение, копируется в регистры цвета видеокарты.
Для размещения точной копии содержимого регистров цвета требуется 768 байтов (3 256). При работе с системной палитрой использовать трехбайтовый код цвета неудобно, поэтому к трем байтам каждого цвета лучше добавить четвертый пустой байт. Это увеличит размер занимаемой памяти до 1024 байтов, но существенно упростит работу с палитрой.
Большинство вспомогательных рисунков, применяемых для оформления рабочей области экрана, хранится в файлах форматов BMP и ico. Поэтому мы выберем следующее расположение кодов базовых цветов в каждой строке системной палитры: синий, зеленый, красный, пустой байт (формат b, g, r, 0). Такой вариант системной палитры не является точной копией содержимого регистров цвета видеокарты. Однако хранящиеся в ней коды цветов строго соответствуют кодам, находящимся в регистрах видеокарты.
Учитывая достаточно большой размер палитры, ее не целесообразно хранить в разделе данных задачи. Лучше выделить отдельный сегмент, а в разделе данных зарезервировать следующие два слова:
Syspal dw 0; смещение палитры от начала сегмента (обычно 0) dw 0; код сегмента памяти, в котором хранится палитра
Если память распределяет программист при подготовке исходного текста задачи, то место размещения палитры описывается в тексте программы и нули заменяются конкретными значениями. Если же память распределяется динамически, т. е. пространство для размещения палитры выделяется в процессе выполнения задачи, то нужные значения записываются в syspai и Syspai+2 после того, как будет определен код сегмента для хранения палитры.
В разделе данных задачи надо зарезервировать еще одну переменную, исходное значение которой устанавливается при инициализации палитры:
numcol dw 0; количество цветов, хранящихся в системной палитре
Инициализация системной палитры
После выделения пространства для системной палитры в ее строки и в регистры цвета видеокарты надо записать коды цветов, которые не будут изменяться во время выполнения задачи. В Windows 3X таких цветов 20, они называются "статическими" и применяются для оформления окон (цвета рамок, фона, текста и пр.). Прикладные задачи могут использовать, но не могут изменять эти цвета.
Мы ограничимся двумя статическими цветами – черным и белым. Код черного цвета (0, 0, 0, 0) надо записать в нулевую, а код белого (3F, 3F, 3F, 0) в последнюю (255-ю) строку syspai. Инициализация палитры производится в той части программы, где выполняются подготовительные действия. Туда надо вставить следующую группу команд:
Igs di, dword ptr Syspal gs:di = адрес Syspal в памяти xor eax, eax eax = код черного цвета mov gs:[di], eax запись кода в начало Syspal mov eax, 003F3F3Fh eax = код белого цвета mov gs:[di+1020], eax запись кода в конец Syspal mov numcol, 01 количество цветов в палитре ; Сюда надо вставить команды из примера 4.2
В большинстве случаев нулевой регистр цвета видеокарты уже содержит код черного цвета (его байты очищены). Если это не так, то к перечисленным командам надо добавить очистку нулевого регистра цвета. Содержимое остальных регистров цвета не имеет значения, они считаются свободными, поскольку задача работает только с системной палитрой.
Внимание!
В системную палитру записано 2 цвета, а переменной numcol присвоено значение 1. Это сделано потому, что код белого цвета будет обрабатываться нестандартно. По мере заполнения палитры предельно допустимым значением rjumcoi является 255, а не 256, т. к. последняя строка палитры занята кодом белого цвета.