There are a lot of answers here, but they're all pretty awful :(
The absolute best method is to create a bitmap and pass it an intptr (pointer) to an existing array. This allows the array and the bitmap data to share the same memory ... no need to 'Bitmap.lockbits'/'Bitmap.unlockbits' (slow).
Here's the broad outline...
- Mark your function 'unsafe' and set your projects build settings to allow 'unsafe' code! (c# pointers)
- Create your array[,]. Either using Uint32's, Bytes or a Struct that permits access to by both Uint32 OR individual Uint8's (By using explicit field offsets)
- Use "System.Runtime.InteropServices.Marshal.UnsaveAddrOfPinnedArrayElement" to obtain the Intptr to the start of the array.
- Create the Bitmap using the constructor that takes an Intptr and Stride. This will overlap the new bitmap with the existing array data.
You now have permanent direct access to the pixel data!
The underlying array
The underlying array would likely be a 2D array of a user-struct 'Pixel'. Why? Well... Structs can allow multiple member variables to share the same space by using explicit fixed offsets! This means that the struct can have 4 single-bytes members (.R, .G, .B and .A), and 3 overlapping Uint16's (.AR, .RG and ,GB) ... and a single Uint32 (.ARGB) ... this can make colour-plane manipulations MUCH faster.
As R,G,B, AR,RG,GB and ARGB all access different parts of the same 32-bit pixel you can manipulate pixels in a highly flexible way!
Because the array of Pixel[,] shares the same memory as the Bitmap itself, Graphics operations immediately update the Pixel array - and Pixel[,] operations on the array immediately update the bitmap! You now have multiple ways of manipulating the bitmap ;)
Flexible AND fast ;)
Remember, by using this technique you do NOT need to use 'lockbits' to marshal the bitmap data in and out of a buffer... which is good, because lockbits is very VERY slow.
You also don't need to use a brush and call complex framework code capable of drawing patterned, scalable, rotatable, translatable, aliasable, rectangles... just to write a single pixel Trust me - all that flexibility in the Graphics class makes drawing a single pixel using 'Graphics.FillRect' a very slow process.
Other benefits...
Super-smooth scrolling! Your Pixel buffer can be larger than your canvas/bitmap, in both height and width! This enables efficient scrolling!!!!
How?
Well, when you create a Bitmap from the array you can point the bitmaps upper-left coordinate at some arbitrary [y,x] coordinate by taking the IntPtr of that Pixel[,].
Then, by deliberately setting the Bitmaps 'stride' to match width of the array (not the width of the bitmap) you can render a predefined subset rectangle of the larger array... whilst drawing (ahead of time) into the unseen margins! This is the principle of "offscreen drawing" in smooth scrollers.
Finally
You REALLY should wrap the Bitmap and Array into a FastBitmap class. This will help you control the lifetime of the array/bitmap pair. Obviously, if the array goes out of scope or is destroyed - the bitmap will be left pointing at an illegal memory address. By wrapping them up in a FastBitmap class you can ensure this can't happen...
... it's also a really handy place to put the various utilities you'll inevitably want to add... such as scrolling, fading, working with colour planes, etc.
Remember:
- Creating Bitmaps from a MemoryStream is very slow
- Using Graphics.FillRect to draw pixels is painfully inefficient
- Accessing underlying bitmap data with lockpixels/unlockpixels is very slow
- And, if you're using 'System.Runtime.InteropServices.Marshal.Copy', just stop!
Mapping the Bitmap onto some existing array memory is the way to go. Do it right, and you'll never need/want to use a framework Bitmap again :)
You're welcome ;)