我试图在C / C ++中创建一个算法,它从左到右应用一个统一的透明渐变到像素缓冲区。如下图所示:
接下来是我的实施。但是结果图像甚至不能达到我需要达到的水平。任何人都可以发现我做错了什么?感谢
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;
}
}
}
答案 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
...