如何在C#UWP中使用原始像素数据合并图层?
问题描述:
由于通用Windows平台默认不支持平面化位图“图层”,因此我一直在创建算法(基于发现的一个算法here)以获取每个图层的每个单独像素,并将它们叠加在另一个上。问题是,因为我使用Alpha来允许图像具有透明像素,所以我不确定如何正确地合并像素,使其看起来好像一个位于另一个之上。如何在C#UWP中使用原始像素数据合并图层?
这是到目前为止我的代码:
private unsafe SoftwareBitmap CompileImage()
{
SoftwareBitmap softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, Width, Height);
using (BitmapBuffer buffer = softwareBitmap.LockBuffer(BitmapBufferAccessMode.Write))
{
using (var reference = buffer.CreateReference())
{
byte* dataInBytes;
uint capacity;
((IMemoryBufferByteAccess)reference).GetBuffer(out dataInBytes, out capacity);
BitmapPlaneDescription bufferLayout = buffer.GetPlaneDescription(0);
for (int index = 0; index < layers.Length; index++)
{
for (int i = 0; i < bufferLayout.Height; i++)
{
for (int j = 0; j < bufferLayout.Width; j++)
{
if(index == 0)
{
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0] =
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0]; //B
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1] =
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1]; //G
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2] =
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2]; //R
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3] =
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3]; //A
}
else if(index > 0)
{
//Attempts to "Average" pixel data
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0] =
(byte)(dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0] *
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0]/2);
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1] =
(byte)(dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1] *
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1]/2);
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2] =
(byte)(dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2] *
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2]/2);
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3] =
(byte)(dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3] *
layers[index].pixelData[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3]/2);
}
}
}
}
}
}
return softwareBitmap;
}
目前的算法将每个像素的平均BGRA值在每一层,并返回结果。这不是我打算做的。我如何去纠正它?在此先感谢
答
要应用一个alpha混合你乘以逆alpha和当前颜色的alpha,当然你应该做一个0-1的规模(这就是为什么图形卡与浮动颜色)。
每例如,假设有三个层,A,B和C中,使用A作为碱,然后将其与乙混合:(伪码)
//bAlpha is thge alpha value of the current pixel from B in byte value
var alpha = bAlpha/255.0f;
var invAlpha = 1.0f - alpha;
//aRGB is the RGB value of the pixel on the layer A
//bRGB is the RGB value of the pixel on the layer B
var abRGB = aRGB * invAlpha + bRGB * alpha;
现在应用的第三层:
//cAlpha is thge alpha value of the current pixel from C in byte value
alpha = cAlpha/255.0f;
invAlpha = 1.0f - alpha;
//abRGB is the RGB value of the previously mixed layers
//cRGB is the RGB value of the pixel on the layer C
var abcRGB = abRGB * invAlpha + cRGB * alpha;
当然,所有这一切都是在ARGB模式,这里还有pARGB其中颜色已经预乘,所以你只需要乘以先前的颜色由逆α和添加当前颜色。
//bAlpha is the alpha value of the current pixel from B in byte value
var invAlpha = 1.0f - (bAlpha/255.0f);
//aRGB is the RGB value of the pixel on the layer A
//bRGB is the RGB value of the pixel on the layer B
var abRGB = aRGB * invAlpha + bRGB;
invAlpha = 1.0f - (cAlpha/255.0f);
//abRGB is the RGB value of the previously mixed layers
//cRGB is the RGB value of the pixel on the layer C
var abcRGB = abRGB * invAlpha + cRGB;
我仍然试图了解我在做什么我的帖子错了。很显然,如果我继续得到如此多的降薪,尽管按照规则建议我对待我的问题所做的一切,我正在做一些错误-_- – Dylanrules22