Простая установка палитры
При подготовке образов точечных, или как их еще называют "растровых",
рисунков либо используется палитра, либо цвет указывается непосредственно
в коде каждой точки. В режимах PPG можно работать только с рисунками,
подготовленными с применением палитры.
Коды точек образа рисунка, использующего палитру, являются порядковыми
номерами содержащихся в ней цветов. Поэтому палитра должна быть установлена
(записана в регистры цвета видеокарты) до построения рисунка на экране.
Если этого не сделать, то цвета точек построенного рисунка будут соответствовать
тем, которые находятся в регистрах цвета видеокарты, и вы можете увидеть
совсем не ту картинку, которая должна быть.
Формат и место палитры в файле
Папитра или таблица цветов содержит коды цветов, использованных при создании
рисунка. В большинстве стандартов код цвета занимает 3 байта, в которых
указана интенсивность базовых цветов — красного, зеленого и синего. Если
базовые цвета перечислены именно в такой последовательности, то мы будем
говорить, что палитра имеет формат г, а, ь. Если в такой палитре описано
N цветов, то она занимает в файле зы байтов. Исключением является стандарт
BMP (см. приложение А). В этом случае строка
может содержать три или четыре байта, а палитра занимает в файле соответственно
SN или 4N байтов. В трех первых байтах хранятся коды синего, зеленого
и красного цветов. Если в строке есть четвертый байт, то он очищен. В
таких случаях мы будем говорить, что палитра имеет формат b, g, r или
b, g, r, 0.
Как правило, код базового цвета содержит восемь разрядов и заполняет
весь байт. В технической документации принято говорить, что при таком
размере кода цвет хранится в формате, независящем от устройства.
Местонахождение и размер палитры также зависит от стандарта, которому
соответствует файл. Палитра может предшествовать образу рисунка или находиться
после него. Ее размер может быть фиксированным (максимально возможным)
или сокращенным за счет включения только тех цветов, которые реально использованы
в рисунке.
Мы опишем установку палитры при работе с файлами, соответствующими стандарту
PCX, аналогичные действия при работе с файлами стандарта BMP описаны в
приложении А данной книги.
Расположение и варианты палитры PCX
Стандарт PCX создавался в то время, когда ПК поддерживали видеорежимы
CGA и EGA. Поэтому в заголовке файла, начиная с адреса 10h, было зарезервировано
48 байтов, что позволяет разместить 16-цветную палитру. С появлением видеорежима
VGA возникла необходимость изменения или доработки стандарта PCX, поскольку
размер заголовка не позволял разместить 256-цветную палитру. Для сохранения
совместимости с уже существующими файлами было решено оставить без изменения
все, что касаюсь режимов CGA и EGA, и расположить 256-цветную палитру
в конце файла, после образа рисунка. В этом случае место, занимаемое палитрой
EGA, не используется.
Первой это сделала фирма Genius Microprogramming в 1988 году. В соответствии
с ее версией стандарта PCX сразу после образа рисунка располагается байт,
содержащий код ОА, а после него следует палитра формата r, g, b. Коды
базовых цветов сокращены до 6-ти разрядов, т. е. формат палитры полностью
соответствует стандарту VGA IBM и она может быть установлена с помощью
уже описанного запроса 1012h прерывания int 10h.
В том же году разработчик стандарта PCX фирма ZSoft приняла аналогичные
дополнения. Однако, в отличие от версии Genius, байт, расположенный перед
палитрой, содержит код ос, а коды базовых цветов содержат 8 разрядов (независящие
от устройства коды). Такая палитра не полностью соответствует стандарту
VGA IBM — перед ее установкой все байты надо сдвинуть на 2 разряда вправо.
Таким образом, на сегодняшний день существуют, по крайней мере, два
способа хранения 256-цветной палитры в стандарте PCX. Различить их можно
по коду, находящемуся в байте, расположенному после образа рисунка.
Как получить доступ к палитре
Для доступа к палитре файл надо открыть, прочитать его заголовок (первые
80h байтов) и извлечь оттуда данные о размерах рисунка и кода точки. Если
последний равен восьми, то палитра находится в конце файла после образа
рисунка.
Расположение нужных величин в заголовке файла формата PCX описано в разделе.
Перед чтением палитры в оперативную память файл надо принудительно позиционировать
так, чтобы сохраняемый DOS указатель находился на расстоянии 769 байтов
от конца файла. Затем надо прочитать 769 байтов в буфер обмена. После
чтения нулевой байт буфера обмена должен содержать код ОА или OC, в противном
случае произошла ошибка, которая означает, что файл не соответствует стандарту
PCX, или был неверно позиционирован.
Если нулевой байт буфера обмена содержит код ос, то перед установкой
палитры надо сдвинуть содержимое ее байтов на два разряда вправо. В противном
случае (если буфер обмена содержит код ОА) сдвиг не требуется. Теперь
формат палитры, находящейся в буфере обмена, соответствует стандарту VGA
IBM и ее можно устанавливать (копировать в регистры цвета).
Позиционирование файла
В процессе построения рисунка формата PCX приходится дважды принудительно
изменять текущую позицию файла. Рассмотрим, как это делается.
При открытии файла по указанному имени DOS в своем разделе данных создает
специальную структуру (или таблицу), в которой хранятся величины, необходимые
для доступа к файлу. Порядковый номер этой структуры называется file handle
(или просто ссылка), при успешном открытии файла DOS возвращает значение
ссылки в регистре ах. Задача должна сохранить ссылку, например, в переменной
Handler, и указывать ее при всех последующих обращениях к файлу.
В созданной DOS структуре, помимо прочих величин, хранится указатель
позиции, в которой находится файл, сразу после открытия это число 0. При
каждом чтении или записи значение указателя увеличивается на количество
прочитанных или записанных байтов. Поэтому если вы последовательно читаете
или записываете данные, то дополнительные действия по изменению позиции
файла не требуются. Однако в некоторых случаях может понадобиться принудительное
изменение позиции (значения указателя) без чтения или записи данных. Для
выполнения таких действий предназначена специальная функция DOS, которая
называется Lseek.
Все функции DOS вызываются через прерывания int 2ih, а код функции указывается
в регистре ah. Код функции Lseek равен 42h. В регистре al указывается
точка, относительно которой выбирается новая позиция, это числа 0, 1 или
2. Соответственно эти числам точкой отсчета является начало, текущая позиция,
или конец файла. В паре регистров cx:dx задается 32-разрядное число, для
получения новой позиции, его значение прибавляется к точке отсчета. При
работе с файлами в регистр bx всегда записывается ссылка (file handle).
После выполнения функции DOS возвращает в паре регистров dx:ax новое значение
указателя, если эта величина используется в задаче, то ее надо сохранить.
Подпрограмма установки палитры PCX
В примере 4.6 приведен текст подпрограммы, выполняющей простую установку
палитры из файла формата PCX. Предполагается, что файл был открыт, и его
заголовок обработан. После возврата из подпрограммы задача должна проверить
состояние С-раз-ряда. Если он очищен, то палитра успешно установлена.
В противном случае подпрограмма обнаружила ошибку при позиционировании
или в структуре файла.
Пример 4.6. Установка 256-цветной палитры из файла PCX
SetPpal : pusha сохранение содержимого регистров
; Позиционирование на коне! i файла PCX
mov ax, 4202h код запроса позиционирования файла
mov bx, Handler указываем ссылку на файл
mov ex, -I старшая часть числа -769
mov dx, -T69 младшая часть числа -769
int 21h обращение к функциям DOS
j с spexit -> ошибка позиционирования
/ Чтение палитры в буфер и проверка признака
mov ex, T 69 размер считываемой порции данных
call readf чтение данных в буфер обмена
xor si, si нулевой адрес в буфере обмена
lods byte ptr f s : [si] чтение в al нулевого байта
cmp al, OAh в байте находится код ОА ?
je spal -> да, исключаем масштабирование
cmp al, OCh в байте находится код ОС ?
je @F -> да, выполняем масштабирование
stc установка признака ошибкиjmp short spexit ;
-> на завершение подпрограммы
Масштабирование (сдвиг ее держимого байтов) палитры
@@: mov ex, 768 ; указываем размер палитры
rapal: shr byte ptr fs:[si], 0 2 сдвиг очередного байта
inc si адрес следующего байта
loop ir.pal управление повторами цикла
; Установка палитры (копире вание в регистры цвета видеокарты)
spal : push es сохраняем содержимое es
push fs сохраняем содержимое fs
pop es выталкиваем его в es
mov dx, 01 адрес начала палитры
xor bx, bx номер первого регистра цвета
mov ex, 256 кол-во устанавливаемых регистров
mov ax, 1012h код запроса на установку палитры
int lOh обращение к функции BIOS
pop es восстанавливаем содержимое es
; Позиционирование файла на начало рисунка
mov ax, 4200h код запроса позиционирования файла
mov bx, Handler указываем ссылку на файл
xor ex, ex старшая часть величины смещения
mov dx, 8 Oh младшая часть величины смещения
int 21h обращение к функциям DOS
spexit : popa восстановление регистров
ret возврат из подпрограммы
Основные фрагменты подпрограммы отделены друг от друга комментарием.
В примере 4.6 используются все регистры общего назначения, поэтому первая
команда pusha сохраняет их содержимое в стеке. Следующие четыре команды
формируют данные для запроса на позиционирование файла. В регистр ai записывается
код 2, являющийся признаком перемещения указателя в заданную позицию,
а в пару регистров cx:dx — смещение этой позиции от конца файла (отрицательное
число 769). Затем происходит обращение к DOS (int 2ih) для исполнения
запроса. Если при позиционировании зафиксирована ошибка, то команда jc
spexit выполнит переход на метку spexit для завершения подпрограммы с
установленным С-разрядом.
В случае успешного позиционирования в буфер обмена считываются 769 байтов,
содержащих признак ось или ОАП и собственно палитру. Для чтения используется
подпрограмма readf, текст которой был приведен в примере 3.23. После чтения
нулевой байт буфера обмена содержит код типа палитры. Он помещается в
регистр ai и аначизируется. Если код равен OAh, то масштабирование исключается.
Если код равен ось, то нужно выполнить масштабирование палитры. Если код
отличается от ОАП и och, то устанавливается С-разряд и происходит возврат
из подпрограммы.
Для масштабирования палитры в регистр сх записывается ее размер и выполняется
цикл сдвигов содержимого каждого байта на 2 разряда вправо.
Начиная с команды, имеющей метку spal, формируются исходные данные для
функции BIOS, устанавливающей палитру. В регистр es надо записать значение
сегмента буфера обмена (содержимое регистра fs), а в регистр dx — адрес
начала палитры в этом сегменте (1). Номер первого устанавливаемого DAC-регистра
равен нулю, а количество устанавливаемых одс-ре-гистров равно 256. В регистр
ах помещается код запроса (ioi2h) и происходит обращение к BIOS (int 10h).
После возвращения из BIOS надо восстановить исходное содержимое регистра
es, сохраненное в стеке.
Палитра установлена и подпрограмму можно было бы завершить. Однако в
процессе ее выполнения изменилась исходная позиция файла, и ее надо восстановить.
В противном случае перед построением рисунка потребуются лишние действия,
связанные с определением и изменением текущей позиции файла.
Образ рисунка отстоит на 80h байтов от начала файла. Поэтому в примере
в регистры ai и сх записывается 0, а в регистр dx код 80h. После позиционирования
восстанавливается содержимое регистров (команда рора) и происходит возврат
из подпрограммы. Если при позиционировании возникнет ошибка, то произойдет
возврат с установленным С-разрядом.
При выходе из описанной подпрограммы С-разряд будет установлен не только
при ошибках позиционирования файла, но и при отсутствии кодов OAh или
ось перед палитрой. В основной программе уже невозможно определить причину
ошибки. Если она важна, то в подпрограмме можно сформировать дополнительные
признаки, уточняющие характер ошибки.
После успешной установки палитры можно приступать к построению рисунка
на экране. Выбор способа построения зависит от содержимого байта 2 заголовка
файла. Если он очищен, то образ рисунка не сжат и для вывода на экран
используется подпрограмма BigDraw (см. пример 3.22). Если же байт 2 заголовка
содержит единицу, то образ рисунка упакован и для распаковки при выводе
на экран применяется подпрограмма PackDrw (см. пример 3.26).
Таким образом, к этому моменту вы располагаете всей информацией, необходимой
для работы с файлами стандарта PCX, содержащими рисунки, использующие
палитру. О работе с файлами этого же стандарта, но не использующими палитру,
мы поговорим в главе 7 (см. раздел).
Замечание
При установке палитры описанным способом она просто копируется в регистры
цвета видеокарты. Это допустимо в тех случаях, когда на экране будет находиться
только тот рисунок, для которого предназначена установленная палитра.
Если же рисунок добавляется к уже существующим, то при смене палитры,
почти наверняка, изменятся цвета той части изображения, которая не занята
новым рисунком. Поэтому, в общем случае, описанная процедура недопустима
и при установке палитры должны быть приняты меры для сохранения исходной
картинки, находящейся на экране.
|