wpf 可写位图与背景网格奇怪地混合

hfyxw5xn  于 2023-08-07  发布在  其他
关注(0)|答案(1)|浏览(103)

我正在尝试绘制WPF中分配给Image控件的WriteableBitmap,我发现即使Alpha值设置为0,颜色值也会与背景颜色混合。
我有以下主窗口

<Window x:Class="WriteableBitmapTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Test" Height="450" Width="800">
    <Grid Background="#999">
        <Image x:Name="testImage"/>
    </Grid>
</Window>

字符串
我用下面的代码填充图像控件--期望将alpha字节设置为0将产生任何可见的内容。

public partial class MainWindow : Window
    {
        const int Size = 300;

        public MainWindow()
        {
            InitializeComponent();
            this.testImage.Source = CreateBitmap();
        }

        private ImageSource CreateBitmap()
        {
            var bitmap = new WriteableBitmap(
                Size,
                Size,
                96,
                96,
                PixelFormats.Pbgra32,
                null);

            bitmap.Lock();
            FillBitmap(bitmap);
            bitmap.Unlock();

            return bitmap;
        }

        private void FillBitmap(WriteableBitmap writableBitmap)
        {
            var stride = writableBitmap.BackBufferStride;
            var bytesPerPixel = writableBitmap.Format.BitsPerPixel / 8;
            var pixelRows = Size;
            var pixels = new byte[pixelRows * stride * bytesPerPixel];

            for (int i = 0; i < pixels.Length; i += bytesPerPixel)
            {
                pixels[i + 0] = 0x00;  // B
                pixels[i + 1] = 0x00;  // G
                pixels[i + 2] = 0xff;  // R
                pixels[i + 3] = 0x00;  // A <--- expect the R value to be ignored when rendered.
            }

            var rect = new Int32Rect(0, 0, Size, Size);
            writableBitmap.WritePixels(rect, pixels, stride, 0);
        }
    }


相反,我看到一个红色的方块,似乎已经与背景颜色(我设置为灰色)混合。
x1c 0d1x的数据
我想知道是否有什么诀窍来控制这种混合行为?或者如果我像这样直接写入像素数据,我是否需要考虑背景颜色。
欣赏任何见解!

b1uwtaje

b1uwtaje1#

使用PixelFormats.Bgra32而不是PixelFormats.Pbgra32,这将需要0的预乘R值。
online documentation
获取Pbgra 32像素格式。Pbgra 32是每像素32位(BPP)的sRGB格式。每个通道(蓝色、绿色、红色和alpha)分配有8位/像素(BPP)。每个颜色通道都预先乘以alpha值
除此之外,你的缓冲区太大了。bitmap.PixelHeight * stride是足够的大小,即行数乘以每行的字节数。
WritePixels也不需要bitmap.Lock()bitmap.Unlock()
最后,在写入包含连续像素序列的像素缓冲区时,不应使用BackBufferStride。出于性能原因,BackBufferStride的值可能与源缓冲区的实际步幅不同。

private ImageSource CreateBitmap()
{
    var bitmap = new WriteableBitmap(
        300,
        300,
        96,
        96,
        PixelFormats.Bgra32,
        null);

    FillBitmap(bitmap);
    return bitmap;
}

private void FillBitmap(WriteableBitmap bitmap)
{
    var bytesPerPixel = 4; // required for code below
    var stride = bitmap.PixelWidth * bytesPerPixel;
    var pixels = new byte[bitmap.PixelHeight * stride];

    for (int i = 0; i < pixels.Length; i += bytesPerPixel)
    {
        pixels[i + 0] = 0x00; // B
        pixels[i + 1] = 0x00; // G
        pixels[i + 2] = 0xFF; // R
        pixels[i + 3] = 0x00; // A
    }

    var rect = new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight);
    bitmap.WritePixels(rect, pixels, stride, 0);
}

字符串

相关问题