I used to manipulate bitmaps in memory directly. When I first needed to do it in C#, I was forced to use unsafe code. Not that bad, considering that I worked for years with C++, but the fact that I needed to switch to unsafe code was the problem, specially because the code may not be trusted. I don't have a real solution for the trust problem, except for the fact that only a very small DLL must be able to use unsafe code, and return everything as managed objects.
What is a Bitmap and How Managed Bitmaps Work?
A bitmap is basically a one-dimensional array that uses some calculation to be seen as a two-dimensional array. The values in such array could be color indexes (when using color palettes) or the RGB values directly, using some type of encoding. The managed bitmaps are simple classes that have a
PixelArray, which is an array of bytes, for
int (System.Int32) for
ArgbBitmap and of
ColorBitmap. They also have a
Width to know to calculate a X/Y coordinate. The height value is then calculated as a division of the
PixelArray length by its
Width. They, of course, have some additional methods. They can be converted to and from each other and
System.Drawing.Bitmaps, and also can copy only "blocks" from one to another.
This approach has three main problems:
- I can't simply map a
System.Drawing.Bitmap data as a C# array or draw managed bitmaps directly to the screen, so copying is needed. This is still faster than using
SetPixel when many pixels must be changed, but a real problem if you only need to change some pixels.
FROM system bitmaps process will still be unsafe. Someone using the classes will never need to use unsafe code, but the DLL containing the classes will be marked as unsafe, having all the "untrusted problems" if not registered properly.
- None of the GDI methods can be used on them. Some may easily be recreated, but the hardware acceleration will never be used.
So, What are the Advantages?
When creating painting programs, for example, a lot of algorithms don't use hardware acceleration, counting only on pixel information and custom made algorithms. For such algorithms, using a managed bitmap instead of a lot of pointers simplifies everything. In my case, I am working on creating some web-cam image processing by hand and I really don't want such processing to be unsafe.
Decisions Regarding the Classes
The classes are there to guarantee that its users are capable of reading or editing bitmaps at a fast speed without using unsafe code. So, to make the classes fast, the right datatypes must be used. This was one of the big challenges. Grayscale bitmaps are really easy. Its color indexes, or brightness, are simply bytes, so array of bytes are ok. But the
Int32 are not the same type in .NET, as it happens to be in 32-bit C++. Which one is better? Using an array of
int to represent the pixels, or an array of colors? Simple. In my opinion, there is no better one. There are personal preferences and different advantages and disadvantages in each one and, so, one class that works with array of
int as a 32-bit
Argb and one class that works with an array of
Colors was created. Three classes, but two of them are, in fact, different views of the same result. Also, one important decision is the indexer. The X and Y indexer does not do bound-checking. If you pass invalid X and Y coordinates, you can change the wrong pixel. Why I don't do bound-checking if this is a managed code? Because doing bound-checking has dramatically downgraded performance and, the real error that is accessing invalid memory areas is already checked by the .NET array. So, you are capable of affecting the wrong line giving an invalid X value, but you will never corrupt the entire application memory.
Oh, There are Three Classes. Are they Compatible?
Yes, via interfaces. Each class is sealed, so any virtual call is avoided and max speed is obtained, but they implement a common interface, named
IBitmap, so one can be used in place of another. Not that it is really useful, as this will probably kill the performance and the purpose of the classes, but there is such option.
The Public Members
The most important
public members are defined in the
IBitmap interface and they allow the access of the
Height properties, access to the pixel as a x/y coordinate pair and have many functions to copy from one bitmap to another and to create bitmap in the other formats (from one managed bitmap to another or even to a system bitmap). There is, of course, a constructor to create any of the managed bitmaps empty, with the specified size. That's all that's needed and any method that receives or returns a
System.Drawing.Bitmap needs to use unsafe code.
Explaining all the classes is unnecessary, as I think explaining all methods, but I will explain the key methods, those that use unsafe code to the users of such methods don't need to use them:
CopyBlockTo accepting a
System.Drawing.Bitmap from the
The methods are unsafe but are, in fact, very small. The most bizarre aspects of the method are the calls to the
AbortSafe.Run method. This method is an evolution of the pattern I presented in my article "
using keyword can cause bugs". But, in fact, there is no
using clause in this method, only the unabortable pattern when locking and unlocking bits.
Using the Code
There is no purpose in creating managed bitmaps if we don't use them. So, I added a sample that allows to manipulate increase or decrease RGB values of entire images. The sample can use
System.Drawing.Bitmap, unsafe code and these classes. The unsafe code is certainly faster, but look at the difference from the code that uses the managed bitmaps:
Color sourcePixels = fOriginalBitmap.PixelArray;
Color destPixels = fManagedBitmap.PixelArray;
int count = sourcePixels.Length;
for (int i=0; i<count; i++)
Color color = sourcePixels[i];
int r = p_Calculate(color.R, trackBarRedValue);
int g = p_Calculate(color.G, trackBarGreenValue);
int b = p_Calculate(color.B, trackBarBlueValue);
destPixels[i] = Color.FromArgb(r, g, b);
To the code that uses unsafe code:
BitmapData sourceData = null;
BitmapData destData = null;
sourceData = fOriginalSystemBitmap.LockBits
(new Rectangle(new Point(), fOriginalSystemBitmap.Size),
destData = fSystemBitmap.LockBits(new Rectangle(new Point(),
Size size = fOriginalSystemBitmap.Size;
byte *sourceScanlineBytes = (byte *)sourceData.Scan0;
byte *destScanlineBytes = (byte *)destData.Scan0;
for(int y=0; y<size.Height; y++)
int *sourceScanline = (int *)sourceScanlineBytes;
int *destScanline = (int *)destScanlineBytes;
for(int x=0; x<size.Width; x++)
int color = sourceScanline[x];
int r = p_Calculate
((color>>16) & 0xFF, trackBarRedValue);
int g = p_Calculate
((color>>8) & 0xFF, trackBarGreenValue);
int b = p_Calculate
(color & 0xFF, trackBarBlueValue);
color = (0xFF<<24) |
(r <<16) | (g<<8) | b;
destScanline[x] = color;
sourceScanlineBytes += sourceData.Stride;
destScanlineBytes += destData.Stride;
if (sourceData != null)
if (destData != null)
So, I hope these classes help anyone wanting to manipulate graphics without using unsafe code.
- 22nd January, 2010: Initial version