如何将位/像素设置为WriteableBitmap(使用BlackWhite格式(1bpp))

时间:2011-03-19 01:20:19

标签: c# wpf

我正在尝试使用WriteableBitmap类在C#/ WPF中创建二进制图像,BlackWhite格式为每像素1位。

但是,完成时我的图像似乎非常扭曲。使用不同的格式(如brg32)工作正常。像素数据存储在BitArray中。图像从1000x1000到3000x3000像素不等。

以下是我目前使用的代码:

unsafe
            {
                int colorOffset = 0;
                int pixelOffset = 0;
                byte color = 0;
                int pBackBuffer = (int)_image.BackBuffer;

                for (int y = 0; y < mapData.Height; y++)
                {
                    for (int x = 0; x < mapData.Width; x++)
                    {

                        if (mapData.Data[y * mapData.Height + x])
                        {
                            //Set the pixel to white
                            color += 1;
                        }

                        //Shift the pixel position by 1
                        color = (byte)(color << 1);

                        //If 8 pixels have been written, write it to the backbuffer
                        if (++colorOffset == 8)
                        {
                            pixelOffset = ((y * mapData.Height) + x) / 8;
                            *(byte*)(pBackBuffer + pixelOffset) = color;
                            color = 0;
                            colorOffset = 0;
                        }

                    }
                }
                //Update the image
                _image.AddDirtyRect(new Int32Rect(0, 0, mapData.Width, mapData.Height));
            }

如您所见,我正在写入8像素/位,然后将其复制到后台缓冲区。也许对这个主题有更多了解的人可以提供帮助。我也试过直接将BitArray复制到一个字节数组,然后将字节数组复制到backbuffer(并使用WritePixels函数),这两个都没有帮助。

此致 丹

1 个答案:

答案 0 :(得分:1)

您似乎没有使用BackBufferStride属性来计算下一行像素的地址。另请注意,如果地图宽度不是8的倍数,则会丢失一些像素。我没有测试代码,但我会这样写:

unsafe
{
    int colorOffset = 0;
    int pixelOffset = 0;
    byte color = 0;
    byte* pBackBuffer = (byte*)_image.BackBuffer;
    for(int y = 0; y < mapData.Height; y++)
    {
        // get a pointer to first pixel in a line y
        byte* pixLine = pBackBuffer;
        for(int x = 0; x < mapData.Width; x++)
        {

            // fix #1: offset = y * width + x, not y * height + x
            var mapOffset = y * mapData.Width + x;

            if (mapData.Data[mapOffset])
            {
                //Set the pixel to white
                color += 1;
            }

            //Shift the pixel position by 1
            color = (byte)(color << 1);

            //If 8 pixels have been written, write it to the backbuffer
            if(++colorOffset == 8)
            {
                *pixLine++ = color;
                color = 0;
                colorOffset = 0;
            }

        }
        // fix #2: copy any pixels left
        if(colorOffset != 0)
        {
            *pixLine++ = color;
            colorOffset = 0;
            color = 0;
        }

        // fix #3: next line offset = previous line + stride, they are aligned
        pBackBuffer += _image.BackBufferStride;
    }
    //Update the image
    _image.AddDirtyRect(new Int32Rect(0, 0, mapData.Width, mapData.Height));
}