Code: Select all
// the unsigned char alpha parameter would be a value from 0 to 255
void Graphics::DrawSpriteTransparent( int x, int y, RectI srcRect, const RectI& clip, const Surface& s, unsigned char alpha, Color chroma )
{
...
for(int sy = srcRect.top; sy < srcRect.bottom; ++sy)
{
for(int sx = srcRect.left; sx < srcRect.right; ++sx)
{
// Cache destination so as not to recalculate each loop
int dstX = x + (sx - srcRect.left);
int dstY = y + (sy - srcRect.top);
// Get the source and destination pixels
const Color dst = getPixel(dstX,dstY);
const Color src = surf.GetPixel(sx,sy);
// invAlpha is inverse alpha, which is the max value minus the current value
const int invAlpha = 255 - alpha;
// Linear interpolation from source to destination.
// Let's say your alpha is 64 and your Red channels are 255 for the src and 24 for the dst.
// 64 * 255 = 16320
// (255 - 64) * 24 = 4584
// 16,320 + 4,584 = 20,904
// Obviously, 20,904 is too large to fit in an unsigned char ( max value is 255 ) so divide by 255
// 20,904 / 256 = 81 ( 81.65625, but no decimals in integers )
// Let's compare:
// 64 is about 1/4 of 255 so a quarter of the src ( 255 / 4 ) = 63
// The remainder of the color comes from 3/4 of dst ( 24 / 4 * 3 ) = 18
// 63 + 18 = 81
const unsigned char r = unsigned char( ( (src.GetR() * alpha) + (dst.GetR() * invAlpha) ) / 255 );
const unsigned char g = unsigned char( ( (src.GetG() * alpha) + (dst.GetG() * invAlpha) ) / 255 );
const unsigned char b = unsigned char( ( (src.GetB() * alpha) + (dst.GetB() * invAlpha) ) / 255 );
PutPixel( dstX, dstY, { r, g, b } );
}
}
}
// Another form of linear interpolation is c = a + ( ( b - a ) * t )
// a = 24
// b = 255
// t = 64
// c = 24 + ( ( ( 255 - 24 ) * 64 ) / 255 );
// Reversing the order of a and b would yield a value approaching 24 as opposed to 255
// Still have to divide by 255 so the value is in the range of 0 to 255 before adding 24.