How to set the bits/pixels to a WriteableBitmap (with BlackWhite format (1bpp))
I am trying to create a binary image in C#/WPF using the WriteableBitmap class, with the BlackWhite Format which is 1 bit per pixel.
However, it seems the my image is very distorted when finished. Using different formats (such as brg32) works just fine. The pixel data is stored in a BitArray. The images vary from 1000x1000 to 3000x3000 pixels.
Here is the code I am current using:
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;
开发者_C百科 *(byte*)(pBackBuffer + pixelOffset) = color;
color = 0;
colorOffset = 0;
}
}
}
//Update the image
_image.AddDirtyRect(new Int32Rect(0, 0, mapData.Width, mapData.Height));
}
As you can see, I am writing 8 pixels / bits , and then copying it to the back buffer. Perhaps someone who has a bit more knowledge in this topic could help. I've also tried directly copying the BitArray to a byte array, then copy the byte array to the backbuffer (and using the WritePixels function as well), both of which have not helped.
Regards, Dan
It seems like you are not using BackBufferStride
property to compute address of the next line of pixels. Also note that you are missing some pixels if map width is not a multiple of 8. I didn't test the code, but i would have written it like this:
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));
}
精彩评论