Здравствуйте, muradm, Вы писали:
M>Когда мы используем цвет с альфой, то есть RGBA
M>И делаем SetPixel точки такого цвета на некоторую другую точку, то в итоге получаем точку некоторого 3-го цвета.
M>Как я понимаю в конечном итоге монитор показывает эту точку в формате RGB, то есть без альфы.
M>Так вот: как получить эти окончательные RGB, имея цвет исходного пикселяи и цвет нового пикселя?
Ты имеешь в виду, как наложить один RGBA цвет на другой? Я делал так:
// Шаблон для наложения цвета colorOver на фон (bg).
template< bool t_bUseR // Накладывать красную компоненту
, bool t_bUseG // Накладывать зелёную компоненту
, bool t_bUseB // Накладывать синюю компоненту
, bool t_bUseA // Изменять значение альфаканала
, bool t_bBgIsOpaque // полагать, что bg.A() == 255
, bool t_bUseScale // домножать colorOver.A() на scale
>
inline void blendColors_T( const Color& bg, const Color& colorOver, Color& dst, byte scale = 255 )
{
uint topA = colorOver.A();
if( t_bUseScale )
{
topA *= scale;
topA /= 255;
}
const uint err = 255/2;
switch( topA )
{
case 255:
dst = colorOver; return;
case 0:
dst = bg; return;
default:
uint a3, a4;
if( t_bBgIsOpaque )
{
a3 = uint(255) - topA;
a4 = topA;
}
else
{
uint k = ( uint( uint(255)-topA ) * bg.A() + err ) / 255;
uint a2 = (topA + k);
a3 = (k*uint(255))/a2;
a4 = uint(255)-a3;
if( t_bUseA ) dst.A() = a2;
}
if( t_bUseR ) dst.R() = (bg.R()*a3 + colorOver.R()*a4 + err) / 255;
if( t_bUseG ) dst.G() = (bg.G()*a3 + colorOver.G()*a4 + err) / 255;
if( t_bUseB ) dst.B() = (bg.B()*a3 + colorOver.B()*a4 + err) / 255;
return;
}
}
}
Здесь используется математически правильная формула, сделав небольшое допущение можно ускорить код примерно в два раза -- для этого нужно заменить "/ 255" на ">> 8", ещё можно отказаться от округления в ближайшую сторону отбросив "+ err".
Собственно о параметрах: t_bUseR, t_bUseG, t_bUseB -- какие каналы изображения накладывать, от такой гибкости можно и отказаться, впрочем, на производительность она никак не влияет.
t_bUseA -- после наложения цветов альфаканал меняется, если вдруг не хочется перезаписывать альфаканал, то нужно установить этот параметр в false.
t_bBgIsOpaque -- предпологать что прозрачность фонового цвета равна 255, в этом случае вычисления значительно упрощаются.
t_bUseScale -- домножать прозрачность накладываемого цвета на коэфициент (scale/255), полезно, если хочется на лету делать накладываемый цвет полупрозрачным.
Color& bg -- фоновый цвет;
Color& colorOver -- накладываемый цвет;
Color& dst -- цвет, куда сохраняется результат, может совпадать с bg;
Теперь, допустим у тебя есть два цвета bg = RGBA(100,100,100,100) и colorOver = RGBA(200,200,200,200), после их наложения результирующий цвет тоже будет полупрозрачным (только если альфа bg не равна 255), т.е., в общем случае придётся наложить полученный цвет на цвет, который считается фоновым, например цвет диалога. Но если цвет bg заведомо непрозрачен, то можно обойтись только одним наложением (лучше с флагом t_bBgIsOpaque).