How to manipulate images at the pixel level in C#
Solution 1
If you want speed, then LockBits. See here for a good walkthrough by Bob Powell. If you just want to edit a few, then GetPixel/SetPixel should do what you want.
Solution 2
A sample code routine (I use this for simple merge and compare functionality. It takes two images and produces a third greyscale image showing the differences between the two images as a greyscale tone level. The darker it is, the more the diff.):
public static Bitmap Diff(Bitmap src1, Bitmap src2, int x1, int y1, int x2, int y2, int width, int height)
{
Bitmap diffBM = new Bitmap(width, height, PixelFormat.Format24bppRgb);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//Get Both Colours at the pixel point
Color col1 = src1.GetPixel(x1 + x, y1 + y);
Color col2 = src2.GetPixel(x2 + x, y2 + y);
// Get the difference RGB
int r = 0, g = 0, b = 0;
r = Math.Abs(col1.R - col2.R);
g = Math.Abs(col1.G - col2.G);
b = Math.Abs(col1.B - col2.B);
// Invert the difference average
int dif = 255 - ((r+g+b) / 3);
// Create new grayscale RGB colour
Color newcol = Color.FromArgb(dif, dif, dif);
diffBM.SetPixel(x, y, newcol);
}
}
return diffBM;
}
Marc's post notes LockBits and using that to modify the image directly in memory. I would suggest looking at that rather than what I have posted if performance is a concern. Thanks Marc!
Solution 3
System.Drawing.Bitmap has a GetPixel(int x, int y) public method that returns a System.Drawing.Color structure. That struct has byte members R, G, B, and A, which you can modify directly, and then call SetPixel(Color) on your Bitmap again.
Unfortunately, that's going to be relatively slow, but it's by the easiest way to do it in C#. If you are working with individual pixels a lot and find the performance is lacking, and you need something faster, you can use LockBits... It's a lot more complicated though, as you need to understand the bit structure for that color depth and type, and work with the bitmap's stride and what not... so if you find it's necessary, make sure you find a good tutorial! There are several out there on the web, Googling "C# LockBits" will get you a half dozen that are worth a read.
Solution 4
If performance is critical, another alternative to LockBits is managed DirectX.
See the earlier Stack Overflow question Rendering graphics in C# for more information.
Like Lockbits you will need to use the unsafe keyword/compiler switch, but you get high performance pixel level access.
You also get higher performance screen rendering via DirectX backbuffering, when compared with using the normal Bitmap class and PictureBox control.
Related videos on Youtube
codeisforeva
Updated on August 26, 2020Comments
-
codeisforeva over 3 years
How do I manipulate images at the pixel level in C#?
I need to be able to read/modify each bitmap pixel RGB values separately.
A code sample would be appreciated.
-
mattlant over 15 yearsnice. I had never bothered looking into going beyond set/get pixel. Thanks for the links.
-
OregonGhost over 15 yearsWhat Bob Powell doesn't tell you is that you don't actually need to deal with pointers in C#. Have a look at LockBits in the MSDN library, there's a sample that copies the memory to a managed array where the method is not marked as unsafe, and therefore the application does not have to be unsafe :)
-
Engineer about 13 yearsXNA users beware, the XBox360 .NET CF does not support the System.Drawing library, which is where LockBits resides. So managed DirectX is likely your only option (thanks Ash).
-
sourcenouveau about 13 yearsManaged DirectX is now deprecated.
-
Tedd Hansen about 9 yearsSite linked to as "here" is down.
-
Beeeaaar over 6 yearsThe site linked in "here" is now a message box pop virus scam.
-
Nyerguds over 6 yearsAs was probably already mentioned multiple times, though,
GetPixel
andSetPixel
are notoriously slow.Bitmap.LockBits
in combination withMarshal.Copy
can achieve the same thing, but gets the data out in bulk rather than pixel per pixel, which makes it loads faster.