C++ 由于alpha值,将一个图像混合到另一个图像上会产生错误的图像

C++ 由于alpha值,将一个图像混合到另一个图像上会产生错误的图像,c++,image-processing,C++,Image Processing,因此,我有一个问题,混合两个图像一起处理透明度。我在这里使用freetype来生成glyph。我有一个相当大的代码库,所以我选择了混合过程中涉及的主要代码部分 这是我正在使用的代码: void TopDown(FT_Bitmap *bitmap, ... ) { ..... ..... for (int srcY=0; srcY < bitmap->rows; srcY++, destLine += textureWidth, src

因此,我有一个问题,混合两个图像一起处理透明度。我在这里使用freetype来生成glyph。我有一个相当大的代码库,所以我选择了混合过程中涉及的主要代码部分

这是我正在使用的代码:

void TopDown(FT_Bitmap *bitmap, ... )
{
        .....
        .....

        for (int srcY=0; srcY < bitmap->rows; srcY++, destLine += textureWidth, srcLine += bitmap->pitch)
        {
            unsigned char *currSrc = srcLine;
            unsigned int *currDest = destLine;
            for (int srcX=0; srcX < bitmap->width; srcX++, currSrc++)
            {
                unsigned char alpha = *currSrc * textA / 255;
                if (currDest >= dest && currDest < destMax)
                {
                    unsigned int destR = (textR * alpha + bgR * (255-alpha))/255;
                    unsigned int destG = (textG * alpha + bgG * (255-alpha))/255;
                    unsigned int destB = (textB * alpha + bgB * (255-alpha))/255;

                    unsigned int as = alpha;
                    *currDest = makeColor(destR, destG, destB, alpha);
                }
                currDest++;
            }
        }
}
void top-down(FT_位图*位图,…)
{
.....
.....
对于(int srcY=0;srcYrows;srcY++,destLine+=textureWidth,srcLine+=bitmap->pitch)
{
无符号字符*currSrc=srcLine;
无符号int*currDest=destLine;
对于(int-srcX=0;srcXwidth;srcX++,currSrc++)
{
无符号字符alpha=*currSrc*textA/255;
如果(currDest>=dest&&currDest
让我们将这一行
无符号字符alpha=*currSrc*textA/255
分成两行:

unsigned char alpha = *currSrc;
alpha = alpha * textA / 255;
这实际上是红色分量。您必须跳过3个字节才能获得alpha值:

unsigned char alpha = *currSrc + 3;
alpha = alpha * textA / 255;
不过你并不真的需要这个。只需找到所有黑色像素并将其alpha值设置为零。确保文本颜色不是黑色。您可以对文本颜色使用
0x00000001
,这将使其与黑色背景区分开来

void TopDown(...)
{
    ...
    for(...)
    {
        ...
        for(...)
        {
            ...
            unsigned char r = *currSrc + 0;
            unsigned char g = *currSrc + 1;
            unsigned char b = *currSrc + 2;
            unsigned char alpha = 128; //or 255 or whatever
            if(currDest >= dest && currDest < destMax)
            {
                if(r || g || b)
                {
                    //non-black pixels get alpha value
                    *currDest = makeColor(r, g, b, alpha);
                }
                else
                {
                    //black pixels get zero alpha
                    *currDest = 0;
                }
            }
            currDest++;
        }
    }
}
void自上而下(…)
{
...
对于(…)
{
...
对于(…)
{
...
无符号字符r=*currSrc+0;
无符号字符g=*currSrc+1;
无符号字符b=*currSrc+2;
无符号字符alpha=128;//或255或其他
如果(currDest>=dest&&currDest
现在您只需在背景位图上绘制。如果使用了正确的绘制功能,则无需混合。背景将显示为透明。要手动混合颜色,请执行以下操作:

unsigned char blend2(unsigned char m, unsigned char n, unsigned char alpha)
{
    float i = (float)n;
    float j = (float)m;
    float a = (float)alpha;

    j *= a / 255.0f; //you can skip this step

    int color = (int)((i + j)/2);
    return (unsigned char)color;
}

void blendBitmap(...)
{
    ...
    for (int line=0; line < copyHeight; line++)
    {
        T *destPtr = destBitmap->line(line+destRow) + 4*destCol;
        unsigned char *sourcePtr = sourceBitmap->line(line+srcRow) + 4*srcCol;
        if(destPtr && sourcePtr)
        {
            for (int col=0; col < copyWidth; col++, destPtr += 4, sourcePtr += 4)
            {
                unsigned char alpha = sourcePtr[3];
                destPtr[0] = blend2(destPtr[0], sourcePtr[0], alpha);
                destPtr[1] = blend2(destPtr[1], sourcePtr[1], alpha);
                destPtr[2] = blend2(destPtr[2], sourcePtr[2], alpha);
            }
        }
    }
}
unsigned char blend2(unsigned char m,unsigned char n,unsigned char alpha)
{
浮点数i=(浮点数)n;
浮动j=(浮动)m;
浮点a=(浮点)α;
j*=a/255.0f;//您可以跳过此步骤
int颜色=(int)((i+j)/2);
返回(无符号字符)颜色;
}
void blendBitmap(…)
{
...
用于(int line=0;lineline(line+destRow)+4*destCol;
无符号字符*sourcePtr=sourceBitmap->line(line+srcRow)+4*srcCol;
if(destPtr&&sourcePtr)
{
for(int col=0;col
“但是角色周围的块是完全透明的(您可以透过它们看到),为什么会发生这种情况?”因为纹理的alpha通道在该部分为0.0?尝试类似于
textA=255-textA
textA=(texA==0)的方法?255:textA
用于调试原因。@Rabbid76。我在
unsigned int textA=(textColor&0xff000000)>>24之后添加了
textA=255-textA
这就是你的意思吗?@rabbi76这样做,文本的透明度会丢失,看起来像这样@Scheff,以防万一你可以打开这个链接,图像看起来像这样。在这种情况下,文本的透明度会丢失,这是不正确的。除此之外,块的背景仍然是透明的。没有任何改变,只是文本的不透明度丢失。您确定“Hello”图像是正确的吗?看起来角色外部没有透明度。在这种情况下,混合实际上是正常的。