To answer your question, you can get more direct access to the recorded bitmap image data using the Lock , write, Unlock pattern, as shown below, but this is usually not required if you do not base your drawing on the image content. Typically, you can simply create a new buffer and make it a bitmap, and not vice versa.
In WPF, there are many extensibility points for performing an innovative drawing without resorting to pixel manipulation. For most controls, the existing WPF primitives (Border, Line, Rectangle, Image, etc.) are more than sufficient - you do not need to be interested in using many of them, they are quite cheap to use. For complex controls, you can use DrawingContext to draw D3D primitives. For image effects, you can implement GPU-enabled shaders using the Effect class or use the built-in effects (Blur and Shadow).
But if your situation requires direct access to pixels, select a pixel format and start writing. I suggest BGRA32 because it is easy to understand and probably the most common one to be discussed.
BGRA32 means that the pixel data is stored in memory as 4 bytes representing the blue, green, red and alpha channels of the image in that order. This is convenient because each pixel ends at a border of 4 bytes, providing it for storage in a 32-bit integer. When dealing with a 32-bit integer, keep in mind that the order will be reversed on most platforms (check BitConverter.IsLittleEndian to determine the correct byte order at run time if you need to support multiple platforms, x86 and x86_64 are both not numerous)
Image data is stored in horizontal stride widths that make up one line of image width. The stride width is always greater than or equal to the width of the image pixel multiplied by the number of bytes per pixel in the selected format. Some situations may cause the step to be larger than the width * bytesPerPixel , which are specific to some architectural objects, so you should use the step width to calculate the beginning of the line, rather than multiplying the width. Since we are using a 4 byte width format, our step has a value of width * 4 , but you should not rely on it.
As already mentioned, the only case I would suggest using WritableBitmap is accessing an existing image, so this is an example below:
Before after:

// must be compiled with /UNSAFE // get an image to draw on and convert it to our chosen format BitmapSource srcImage = JpegBitmapDecoder.Create(File.Open("img13.jpg", FileMode.Open), BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames[0]; if (srcImage.Format != PixelFormats.Bgra32) srcImage = new FormatConvertedBitmap(srcImage, PixelFormats.Bgra32, null, 0); // get a writable bitmap of that image var wbitmap = new WriteableBitmap(srcImage); int width = wbitmap.PixelWidth; int height = wbitmap.PixelHeight; int stride = wbitmap.BackBufferStride; int bytesPerPixel = (wbitmap.Format.BitsPerPixel + 7) / 8; wbitmap.Lock(); byte* pImgData = (byte*)wbitmap.BackBuffer; // set alpha to transparent for any pixel with red < 0x88 and invert others int cRowStart = 0; int cColStart = 0; for (int row = 0; row < height; row++) { cColStart = cRowStart; for (int col = 0; col < width; col++) { byte* bPixel = pImgData + cColStart; UInt32* iPixel = (UInt32*)bPixel; if (bPixel[2 /* bgRa */] < 0x44) { // set to 50% transparent bPixel[3 /* bgrA */] = 0x7f; } else { // invert but maintain alpha *iPixel = *iPixel ^ 0x00ffffff; } cColStart += bytesPerPixel; } cRowStart += stride; } wbitmap.Unlock(); // if you are going across threads, you will need to additionally freeze the source wbitmap.Freeze();
However, this is not necessary if you are not modifying an existing image. For example, you can draw a checkerboard pattern with all the safe code:
Output:

// draw rectangles int width = 640, height = 480, bytesperpixel = 4; int stride = width * bytesperpixel; byte[] imgdata = new byte[width * height * bytesperpixel]; int rectDim = 40; UInt32 darkcolorPixel = 0xffaaaaaa; UInt32 lightColorPixel = 0xffeeeeee; UInt32[] intPixelData = new UInt32[width * height]; for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { intPixelData[row * width + col] = ((col / rectDim) % 2) != ((row / rectDim) % 2) ? lightColorPixel : darkcolorPixel; } } Buffer.BlockCopy(intPixelData, 0, imgdata, 0, imgdata.Length); // compose the BitmapImage var bsCheckerboard = BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgra32, null, imgdata, stride);
And you donβt even need an Int32 intermediate processor if you are directly writing an array of bytes.
Output:

// draw using byte array int width = 640, height = 480, bytesperpixel = 4; int stride = width * bytesperpixel; byte[] imgdata = new byte[width * height * bytesperpixel]; // draw a gradient from red to green from top to bottom (R00 -> ff; Gff -> 00) // draw a gradient of alpha from left to right // Blue constant at 00 for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { // BGRA imgdata[row * stride + col * 4 + 0] = 0; imgdata[row * stride + col * 4 + 1] = Convert.ToByte((1 - (col / (float)width)) * 0xff); imgdata[row * stride + col * 4 + 2] = Convert.ToByte((col / (float)width) * 0xff); imgdata[row * stride + col * 4 + 3] = Convert.ToByte((row / (float)height) * 0xff); } } var gradient = BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgra32, null, imgdata, stride);
Edit: Apparently you are trying to use WPF to create some kind of image editor. Anyway, I will use WPF primitives for shapes and source bitmaps, and then implement translation, scaling, rotation as RenderTransform , bitmap effects as Effect and save everything within the WPF model. But, if this does not work for you, we have many other options.
You can use WPF primitives to render the RenderTargetBitmap , which has the selected PixelFormat for use with WritableBitmap , as shown below:
Canvas cvRoot = new Canvas(); // position primitives on canvas var rtb = new RenderTargetBitmap(width, height, dpix, dpiy, PixelFormats.Bgra32); var wb = new WritableBitmap(rtb);
You can use WPF DrawingVisual to issue GDI style commands, and then render the bitmap as shown in the sample on the RenderTargetBitmap page.
You can use GDI using the InteropBitmap created using System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap from HBITMAP extracted from the Bitmap.GetHBitmap method. Make sure you do not miss HBITMAP .