Выше уже
было сказано, что одиннадцатый аргумент функции
StretchBlt() - это код растровой операции. Другими
словами, это код, который определяет, как при
операции будут взаимодействовать биты,
определяющие заливку и изображение совместимого
контекста с изображением на действительном
контексте. Комбинируются биты на основе
логических операций над ними. По укоренившейся в
книге по программированию для Windows традиции, эти
операции записываются в обратной польской
нотации (не путать с венгерской, автор польской
нотации не имеет к Microsoft ни малейшего отношения).
По той же традиции, биты, определяющие
bitmap совместимого контекста, обозначают буквой S
(source - источник, исходный), биты заливки - буквой P
(pattern - образец), а биты, на которых будет
прорисовываться изображение - буквой D (destination -
назначение, место назначения). Операции
обозначаются следующим образом: a - побитовое И
(AND), n - побитовое НЕТ (NO), o - побитовое ИЛИ (OR), x -
побитовое исключающее ИЛИ (XOR).
Несколько слов о польской нотации. В ней
операции записываются слева направо. Знак
операции следует за операндами. Появление знака
операции означает, что нужно произвести
следующие действия:
- взять два последних операнда
- произвести с ними требующуюся операцию
- записать результат на место последних
двух операндов.
Фактически польская нотация описывает
действия таким образом, словно операнды и
операции находятся в стеке, для чего, собственно,
эта польская нотация и была изобретена.
Обозначив знак операции как Op, в
польской нотации действия с битами можно
записать таким образом:
PSOp
Это говорит о необходимости взять
пиксель патерны и прорисоваемого bitmap'а и
произвести над ним операцию. Если в операции
участвуют три операнда, то получим:
DPSOp1Op2
Что мы должны сделать в этом случае?
Правильно, сначала произвести действие,
определяемое Op1, с битами патерны и
прорисовываемым bitmap'ом, после этого произвести Op2
с полученным результатом и битами
действительного контекста. Ничего сложного
здесь нет.
Каждый код растровой операции
представляется 32-битным целым. Старшее слово
кода представляет собой индекс битовой операции,
младшее - код операции. Как определяется индекс
операции?
Давайте представим, что нам необходимо
определить индекс растровой операции,
определяемой в польской нотации записью DPSxx.
Попутно можно определить и индекс операции PSx.
Запишем друг под другом ОПРЕДЕЛЕННЫЕ значения P,S
и D, а под ними - результаты побитовых операций PSx и
DPSxx:
P |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
S |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
D |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
PSx |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
DPSxx |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
0 |
Итак, индекс операции PSx - 0x3C, а индекс
операции DPSxx - 0x96.
Уважаемый читатель, я прошу обратить внимание на
то, что друг под другом записываются не
произвольные, а строго определенные значения.
Эти значения позволяют перебрать все возможные
комбинации патерны, исходного и целевого bitmap'ов.
Теперь, когда все стало ясно, вы можете
попробовать попрактиковаться в определении
индексов дюбых операций. Несмотря на то, что
существуют 256 индексов растровых операций, на
практике используются только некоторые из них. В
файле wingdi.h для наиболее часто используемых
растровых операций определены идентификаторы,
которые приведены в таблице:
Краткое описание кодов растровых
операций
Наименование |
Индекс
операции |
Польская
запись |
Эффект |
BLACKNESS |
0x00 |
0 |
Заполнение действительного контекста черным
цветом |
NOTSRCERASE |
0x11 |
DSon |
|
NOTSRCCOPY |
0x33 |
Sn |
Прорисовываемый bitmap отображается в негативном
виде |
DSTINVERT |
0x55 |
Dn |
Изображение действительного контекста
проявляется негативным |
PATINVERT |
0x5A |
DPx |
|
SRCINVERT |
0x66 |
DSx |
|
SRCAND |
0x88 |
DSa |
|
MERGEPAINT |
0xBB |
DSno |
|
MERGECOPY |
0xC0 |
PSa |
|
SRCCOPY |
0xCC |
S |
Копирование прорисовываемого bitmap'а на
действительный контекст |
SCRPAINT |
0xEE |
DSo |
|
PATCOPY |
0xF0 |
P |
Копирование патерны на действительный
контекст |
PATPAINT |
0xFB |
DPSnoo |
|
WHITENESS |
0xFF |
1 |
Заполнение действительного контекста белым
цветом |
На основании данных таблицы я
затрудняюсь объяснить, как изменяется
изображение при использовании разных растровых
операций. Рекомендую читателю запустить
приведенную выше программу несколько раз, и
каждый раз в функции StretchBlt() указывать новую
растровую операцию.
Теперь и одиннадцатый аргумент PatBlt()
стал ясным и понятным - я просто копирую bitmap в
окно. Только и всего. Кстати, понимание логики
работы с растровыми операциями может позволить
избежать трудоемких преобразований bitmap'ов перед
копированием. |