在C / C ++中从左到右应用透明渐变

时间:2014-11-13 21:36:38

标签: c++ c bitmap gradient transparent

我试图在C / C ++中创建一个算法,它从左到右应用一个统一的透明渐变到像素缓冲区。如下图所示:

enter image description here

接下来是我的实施。但是结果图像甚至不能达到我需要达到的水平。任何人都可以发现我做错了什么?感谢

void alphaGradient(uint32_t* pixelsBuffer, const int width, const int height)
{
    const short OPAQUE = 255;
    int pixelOffsetY, pixelIndex;
    short A, R, G, B;

    for (int y = 0; y < height; y++)
    {
        A = OPAQUE;

        pixelOffsetY = y * height;

        for (int x = 0; x < width; x++)
        {
            pixelIndex = pixelOffsetY + x;

            A = (int)(OPAQUE - ((OPAQUE * x) / width));
            R = (pixelsBuffer[pixelIndex] & 0x00FF0000) >> 16;
            G = (pixelsBuffer[pixelIndex] & 0x0000FF00) >> 8;
            B = (pixelsBuffer[pixelIndex] & 0x000000FF);

            pixelsBuffer[pixelIndex] = (A << 24) + (R << 16) + (G << 8) + B;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我没有尝试过这个代码,但是这样的东西应该可行:

void alphaGradient(uint32_t* pixelBuffer, const int width, const int height)
{
for (int i = 0; i < width; i++)
{
    for (int j = 0; j < height; j++)
    {
        const DWORD src = pixelBuffer[i + j * width];
        const DWORD dst = MYBACKGROUNDCOLOR;

        const unsigned char src_A = (width - i) * 255 / width;
        const unsigned char src_R = (src & 0x00FF0000) >> 16;
        const unsigned char src_G = (src & 0x0000FF00) >> 8;
        const unsigned char src_B = (src & 0x000000FF);

        //const unsigned char dst_Alpha = (src & 0xFF000000) >> 24;
        const unsigned char dst_R = (dst & 0x00FF0000) >> 16;
        const unsigned char dst_G = (dst & 0x0000FF00) >> 8;
        const unsigned char dst_B = (dst & 0x000000FF);

        const unsigned char rlt_R = (src_R * src_A + dst_R * (255 - src_A)) / 255;
        const unsigned char rlt_G = (src_G * src_A + dst_G * (255 - src_A)) / 255;
        const unsigned char rlt_B = (src_B * src_A + dst_B * (255 - src_A)) / 255;
        //pixelBuffer[i + j*width] = (DWORD)(((255) << 24) | (((rlt_R)& 0xff) << 16) | (((rlt_G)& 0xff) << 8) | ((rlt_B)& 0xff));
        // or if you want to save the transparancy then 
        //pixelBuffer[i + j*width] = (DWORD)(((src_A) << 24) | (((src_R)& 0xff) << 16) | (((src_G)& 0xff) << 8) | ((src_B)& 0xff));
    }

}
}

但就个人而言,我会尝试使用DirectX或OpenGL来编写一个好的PixelShader。它会使这个ALOT更快。

答案 1 :(得分:0)

作为建议,由于您只想修改Alpha通道,因此无需对颜色执行任何操作。所以以下内容也会起作用:

char *b((char *) pixelBuffer);
for(int j = 0; j < height; ++j)
{
    for(int i = 0; i < width; ++i, b += 4)
    {
        *b = (width - i) * 255 / width;
    }
}

就是这样。您还可以通过复制以下行中第一行的数据来消除每行的计算:

// WARNING: code expects height > 0!
char *b((char *) pixelBuffer);
for(int i = 0; i < width; ++i, b += 4)
{
    *b = (width - i) * 255 / width;
}
int offset = width * -4;
for(int j = 1; j < height; ++j)
{
    for(int i = 0; i < width; ++i, b += 4)
    {
        *b = b[offset];
    }
}

我将作为练习留下来在一个for()循环中更改这个双for()循环,这会使它更快一点(因为你有一个单一的计数器(变量) b)而不是三)。


请注意,我不明白Mikael的答案是如何起作用的,因为他在计算alpha通道时在错误的位置使用了* 255。使用整数运算,这非常重要。所以这应该返回0或255:

(width - i) / width * 255

因为value < width然后是value / width == 0(width - i)width或小于width ...

的值