I have a pointer to an 32bit argb image's pixel data and a 32bit xrgb 开发者_如何转开发image's pixel data. How can I composite the argb on top of xrgb image while making use of the alpha component?
Visual Studio 2008 C++
Edit:
Is there a quicker (faster processing) way to do the compositing than this:
float alpha = (float)Overlay[3] / 255;
float oneLessAlpha = 1 - alpha;
Destination[2] = (Overlay[2] * alpha + Background[2] * oneLessAlpha);
Destination[1] = (Overlay[1] * alpha + Background[1] * oneLessAlpha);
Destination[0] = (Overlay[0] * alpha + Background[0] * oneLessAlpha);
This depends on what you are trying to achieve. You can assume your second image to have an alpha of 255 everywhere, then compose each pixel by linear interpolation / alpha blending (assuming float values in [0,1], adjust accordingly):
out(x,y) = argb(x,y).rgb * argb(x,y).a + xrgb(x,y).rgb * (1.-argb(x.y).a)
This way, all pixel with no transparency from your argb image will be always displayed "atop", while pixels with full transparency are invisible and replaced by those from the xrgb pixels. All pixels inbetween are linearly blended.
Presumably by XRGB
you mean a bitmap with four bytes per pixel, but what would be the alpha channel left at some constant value.
An obvious starting point would be to draw the XRGB bitmap first, and the RGBA bitmap second. When you draw the second, enable blending (glEnable(GL_BLEND);
) and set your blend function with glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
. This way the blending depends only on the alpha channel in the source (the RGBA) and ignores any in the destination (the XRGB bitmap that's already been drawn).
Edit: Oops -- somehow I thought I saw some reference to OpenGL, but rereading (and noting the comment) no such thing is there. Doing the job without OpenGL isn't terribly difficult, just generally slower. Let's call the pixels from the two input bitmaps S and D, and the corresponding pixel in the result C. In this case we can compute each pixel in C as:
Cr = Sr * Sa + Dr * (1-Sa)
Cg = Sg * Sa + Dg * (1-Sa)
Cb = Sb * Sa + Db * (1-Sa)
This assumes that you normalize (at least) the A channel to the range of 0..1, and that the ARGB bitmap is S and the XRGB is D.
Here's some code that should work more or less (didn't test it, no compiler on this machine...).
DWORD* pSrc; // Pointer to current row of ARGB bitmap
DWORD* pDst; // Pointer to current row of XRGB bitmap
...
BYTE* src_r = GetRValue(*pSrc);
BYTE* src_g = GetGValue(*pSrc);
BYTE* src_b = GetBvalue(*pSrc);
BYTE* src_a = *pSrc >> 24;
BYTE* dst_r = GetRValue(*pDst);
BYTE* dst_g = GetGValue(*pDst);
BYTE* dst_b = GetBvalue(*pDst);
BYTE* dst_a = 255 - src_a;
*pDst = RGB(((src_r * src_a) + (dst_r * dst_a)) >> 8,
((src_g * src_a) + (dst_g * dst_a)) >> 8,
((src_b * src_a) + (dst_b * dst_a)) >> 8);
精彩评论