由于alpha值的原因,将一个图像混合到另一个图像会产生不正确的图像
Blending one image onto another gives incorrect image because of alpha value
所以我遇到了将两个图像混合在一起处理透明度的问题。我在这里使用freetype来生成字形。我有一个相当大的代码库,所以我挑选了混合过程中涉及的代码的主要部分。
这是我正在使用的代码:
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++;
}
}
}
让我们把这条线unsigned char 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++;
}
}
}
现在您只需要在背景位图上绘制即可。如果使用了正确的绘制功能,则不需要进行混合。背景将显示为透明。手动混合颜色:
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);
}
}
}
}
相关文章:
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 平均图像时图像损坏
- 混合组合和继承的C++问题
- 在混合代码库中将C转换为C++时出现许多包含错误
- 在C++中使用GDAL可以将图像的像素坐标转换为lat,long吗
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- Vulkan验证层不断在VkQueuePresentKHR()上抛出图像布局错误
- 使用FFMPEG将RGB图像序列保存到.mp4时出现问题
- 由于alpha值的原因,将一个图像混合到另一个图像会产生不正确的图像
- 我们可以用不混合而缝制图像
- 使用图像混合器-OpenCV
- 使用opencv复制/混合不同大小的图像
- 在OpenCV 2中混合彩色图像和灰度图像
- 从混合数据文件中读取图像
- Photoshop如何将两个图像混合在一起
- 阿尔法混合未产生所需的图像
- 如何在c++程序中用pgm格式混合/合并两个图像