Рассылка закрыта
При закрытии подписчики были переданы в рассылку "О карьере и профессиональном развитии IT-специалистов" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
← Октябрь 2003 → | ||||||
1
|
2
|
3
|
4
|
5
|
||
---|---|---|---|---|---|---|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
14
|
15
|
16
|
18
|
19
|
|
20
|
21
|
22
|
23
|
24
|
26
|
|
27
|
28
|
30
|
31
|
Статистика
+11 за неделю
Низкоуровневое программирование для дZeнствующих # 43
Информационный Канал Subscribe.Ru |
|
0 | r | r | r | r | r | g | g | g | g | g | b | b | b | b | b |
Для того чтобы корректно выполнить сдвиговые операции, которые на самом деле являются простым делением, нам необходимо сначала прочистить данное слово маской, а потом выполнить сдвиг всего слова целиком. После чего мы можем выполнить оставшиеся операции сложения и вычитания целиком для всего слова, так как полученные значения гарантировано не выйдут за пределы значений, отданных на одну цветовую компоненту и, таким образом, не смогут испортить данные в соседних битах. На рис. 2 представлена ситуация для 15-ти битного режима и альфа-ключа равного шести.
|
||||||||||||||||
AND alphaMask | ||||||||||||||||
|
||||||||||||||||
= | ||||||||||||||||
|
||||||||||||||||
>> (сдвиг на alphaShift) | ||||||||||||||||
|
А в коде это будет выглядеть следующем образом.
unsigned long a1 = getPixel(1, 0, 0); unsigned long a2 = getPixel(2, 0, 0); a1 &= m_uAlphaMask; a1>>=m_uAlphaShift; a1 += a2 - ((a2&alpha&alphaMask)>>alphaShift); setPixel(1, 0, 0, a1);
Где alphaMask является маской, которой необходимо прочистить двойное слово перед сдвигом, а alphaShift – собственно величиной сдвига. Собственно, реализация MMX использует тот же принцип, только по восемь байт за раз, а не по четыре.
Что ещё можно упростить? Можно разделить собственно альфа-блитинг и альфа-заполнение. Для альфа-заполнения можно ещё существеннее поднять скорость, так как мы избежим лишнего обращения к поверхности s2, плюс уменьшим количество вычислений. Или, более конкретно (предполагается, что fillColor задаётся в формате поверхности, которую будут заполнять).
s1[x][y][ck] = a*s1[x][y][ck] + nfillColor,
где nfillColor = s2[x][y][ck] – а*s2[x][y][ck] и вычисляется за циклом. Или
unsigned long a1 = getPixel(1, 0, 0); unsigned long nfillColor = fillColor - ((fillColor&alpha&alphaMask)>>alphaShift); a1 &= m_uAlphaMask; a1>>=m_uAlphaShift; a1 += nfillColor; setPixel(1, 0, 0, a1);
Те, кто любит изобретать велосипед, уже могут запускать свой любимый компилятор, ну а для остальных приведу несколько функций из моей графической библиотеки, которая, кроме всего прочего, занимается ещё и альфа-блитингом.
Прежде чем привести необходимый код, дам несколько пояснений относительно встречающихся там классов, исходный код которых не был включён в статью, так как к альфа-блитингу он никакого отношения не имеет. TVideoCard – основной класс видеокарты, который устанавливает необходимый видеорежим и, что более важно для нас, хранит данные о текущем формате пикселей, который можно получить с помощью метода TVideoCard::PixelFormat(). Что касается TPixelFormat, то там должно быть всё понятно из имён его полей. Дальше, TSurface, предоставляет следующие необходимые методы: Lock()/Unlock() для блокирования поверхности с целью получения прямого доступа к её данным и разблокирования соответственно, DataPtr() возвращает указатель на начало данных поверхности, FullRowLen() – полную длину одной строки поверхности, она может быть больше, чем длина умноженная на количество байт на один пиксел. Класс TRect – описывает прямоугольную область с помощью задания левой верхней точки (методы X(), Y()) и длины с шириной (методы W(), H()). В приложении 1 находиться С++ реализация данного алгоритма, а в приложении 2 – ассемблерная (следует учесть, что ассемблерная реализация использует переменные, объявленные в С++ реализации, а разделение сделано только для наглядности). Есть правда два "но". Первое: я использую портированный gcc в качестве компилятора, поэтому ассемблерный код написан с использованием синтаксиса AT&T. Второе: никаких проверок функции не делают, всё что выходит за пределы четырёх (для С++ реализации) или восьми (для MMX реализации) байт просто игнорируют. Вот и всё, дальше – rtfs.
# Эпилог
Ну что ж, хорошего понемножку. Нужно что-то оставить на следующие выпуски. Отстаётся добавить – отныне как партнёр argc&argv, WASM.RU будет ждать от вас статьи, посвященные не только Assembler, но и другим тематикам программирования. Пишите Edmond@wasm.ru, да опубликованы будете :)). Удачи вам! Edmond / HI-TECH |
###########################################################################
всТупление
|
Edmond
/ HI-TECH
|
|
------------- |
###########################################################################
Рассылка составлена HI-TECH GROUP 17 октября 2003 года. |
(c) HI-TECH 2000 - 2003
http://subscribe.ru/
E-mail: ask@subscribe.ru |
Отписаться
Убрать рекламу |
В избранное | ||