0

I am trying to do some assignment for my course and i am having issues with the SetPixel method on the Bitmap object.

            // Retrieve the image.
            image = new Bitmap(FileLocation);
            SobelImage = image;

            int x, y;

            // Loop through the images pixels to reset color.
            for (x = 0; x < image.Width; x++)
            {
                for (y = 0; y < image.Height; y++)
                {

                    Console.WriteLine(String.Format("At {0} : {1}, Brightness : {2}", x, y, image.GetPixel(x, y).GetBrightness()));


                    Pixel pixel = new Pixel(image.GetPixel(x, y).GetBrightness());

                    SobelImage.SetPixel(x, y, Color.FromArgb(image.GetPixel(x, y).R, 0, 0)); 
                 }
             }

Any help please, this is the exception : An unhandled exception of type 'System.InvalidOperationException' occurred in System.Drawing.dll

Additional information: SetPixel is not supported for images with indexed pixel formats.

RobouteGuiliman
  • 191
  • 3
  • 3
  • 11
  • As a side-note: If you want decent performance, don't use `GetPixel` and `SetPixel`. They're *very* slow. See [SetPixel is too slow. Is there a faster way to draw to bitmap?](http://stackoverflow.com/questions/7768711/setpixel-is-too-slow-is-there-a-faster-way-to-draw-to-bitmap) – CodesInChaos Oct 14 '15 at 17:00
  • Note that most lockbits implementation will not use indexed formats. For these you may need to analyze and change the palette in addition to the pixel indices.. – TaW Oct 14 '15 at 17:27

2 Answers2

1

As the error message says the SetPixel method is not supported for that kind of image.

You have an image format with indexed colors, for example a GIF or an 8-bit PNG, where the color of each pixel is an index into a color palette. You can't change the color of a pixel, because the color is not actually stored in the pixel.

To use the SetPixel method you can create a new empty bitmap, which will be in 32-bit argb format, and draw the image on it:

Bitmap newImage = new Bitmap(image.Width, image.Height);
using (Graphics graphics = Graphics.FromImage(newImage)) {
  graphics.DrawImage(image, 0, 0);
}

The new image will support SetPixel. Note that the image format will be different when you save it.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Ah Thanks, got it working. Where then is the colour stored? As you can ask for the R, B and G value with no issues? – RobouteGuiliman Oct 14 '15 at 17:04
  • The colors are in a color palette, and each pixel contains a color index in the palette. When the color is read the index in the pixel is used to get the color from the palette. – Guffa Oct 14 '15 at 17:16
0

You can not set individual pixels in an indexed bitmap because the of the way data stored. For an indexed bitmap the RGB values are coming from a table by index, but it is a one way operation - you can't just get an index from RGB value because the table could not have a suitable value by the time of a PutPixel operation. A new table could be created from all the RGB values in an RGB bitmap, while processing the entire picture and this is quite expensive operation.

You need to create a new Bitmap in an RGB format, and put pixels there.

Bitmap newImage = new Bitmap(sourceImage.Width, sourceImagr.Height);

As a side note, you should use Bitmap objects inside using construct.

George Polevoy
  • 7,450
  • 3
  • 36
  • 61