Title: Set the pixels in a WPF bitmap in C#
This example shows how you can manipulate the pixels in a WPF bitmap.
One of the things I like least about WPF is the way Microsoft threw away everything we had learned over years of working with Visual Studio. Yes, it's okay to start moving in a new direction, but there's no reason to ignore lessons learned through years of hard experience. Working with bitmapped images is one of the areas where WPF did just that. The .NET tools aren't great for manipulating the pixels in an image, but they're better than the one (note I don't say "ones") provided by WPF.
Anyway, to create a bitmapped image in WPF, you build a WriteableBitmap object. You then create a one-dimensional array holding the raw pixel information for the image, and you use the bitmap's WritePixels method to copy the pixel data into the image. The following code shows how this program does it.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
const int width = 240;
const int height = 240;
WriteableBitmap wbitmap = new WriteableBitmap(
width, height, 96, 96, PixelFormats.Bgra32, null);
byte[, ,] pixels = new byte[height, width, 4];
// Clear to black.
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
for (int i = 0; i < 3; i++)
pixels[row, col, i] = 0;
pixels[row, col, 3] = 255;
}
}
// Blue.
for (int row = 0; row < 80; row++)
{
for (int col = 0; col <= row; col++)
{
pixels[row, col, 0] = 255;
}
}
// Green.
for (int row = 80; row < 160; row++)
{
for (int col = 0; col < 80; col++)
{
pixels[row, col, 1] = 255;
}
}
// Red.
for (int row = 160; row < 240; row++)
{
for (int col = 0; col < 80; col++)
{
pixels[row, col, 2] = 255;
}
}
// Copy the data into a one-dimensional array.
byte[] pixels1d = new byte[height * width * 4];
int index = 0;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
for (int i = 0; i < 4; i++)
pixels1d[index++]= pixels[row, col, i];
}
}
// Update writeable bitmap with the colorArray to the image.
Int32Rect rect = new Int32Rect(0, 0, width, height);
int stride = 4 * width;
wbitmap.WritePixels(rect, pixels1d, stride, 0);
// Create an Image to display the bitmap.
Image image = new Image();
image.Stretch = Stretch.None;
image.Margin = new Thickness(0);
grdMain.Children.Add(image);
//Set the Image source.
image.Source = wbitmap;
}
The code starts by creating the WriteableBitmap. It sets the bitmap's resolution to 96 pixels per inch and uses the Bgra32 format so the bitmap uses 32 bits per pixel to represent blue, green, red, and alpha (opacity) information.
Note the order: blue, green, red, alpha. That's the order in which the data is stored for each pixel. It's probably not the order you would expect.
Next, to make working with the pixel data easier, the program makes a three-dimensional array of bytes. Each pixel's row and column contains 4 bytes in the array to hold its blue, green, red, and alpha components.
The code then uses several loops to set the pixel byte data. It first sets each pixel's color components to 0 and its alpha components to 255 (opaque). It then uses three loops to create areas of blue, green, and red.
The bitmap's WritePixels method expects a one-dimensional array as a parameter, so the code copies the three-dimensional data into a one-dimensional array.
Next the program calls the bitmap's WritePixels method to copy the pixel data into the bitmap. The rectangle indicates the part of the bitmap to update. The stride parameter tells the WritePixels method how many bytes of data there are per row in the bitmap. This is simply the bitmap's width in pixels times the number of bytes per pixel. The final parameter is the offset in the array to the spot where the data to be copied begins.
At this point, the bitmap is ready to use. The program creates an Image control to display it, adds the Image to the program's main Grid control, and displays the bitmap in the Image control's Source property.
The process is cumbersome and non-intuitive, but manageable once you know the steps. It shouldn't be too hard to copy and paste this code to manipulate bitmaps in the future.
Download the example to experiment with it and to see additional details.
|