views:

10057

answers:

4

How to manipulate images at pixel level in C#?

I need to be able to read/modify each bitmap pixel RGB values separately.

Code sample appreciated.

Thanks in advance!

+12  A: 

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.

Marc Gravell
nice. I had never bothered looking into going beyond set/get pixel. Thanks for the links.
mattlant
What 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 :)
OregonGhost
+3  A: 

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.

Grank
+1  A: 

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;

}

EDIT: Marc's post above 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!

mattlant
+2  A: 

If performance is critical, another alternative to LockBits is managed DirectX.

See the earlier StackOverflow 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.

Ash