Convert an image to grayscale
Solution 1
"I want a Bitmap d, that is grayscale. I do see a consructor that includes System.Drawing.Imaging.PixelFormat, but I don't understand how to use that."
Here is how to do this
Bitmap grayScaleBP = new
System.Drawing.Bitmap(2, 2, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);
EDIT: To convert to grayscale
Bitmap c = new Bitmap("fromFile");
Bitmap d;
int x, y;
// Loop through the images pixels to reset color.
for (x = 0; x < c.Width; x++)
{
for (y = 0; y < c.Height; y++)
{
Color pixelColor = c.GetPixel(x, y);
Color newColor = Color.FromArgb(pixelColor.R, 0, 0);
c.SetPixel(x, y, newColor); // Now greyscale
}
}
d = c; // d is grayscale version of c
Faster Version from switchonthecode follow link for full analysis:
public static Bitmap MakeGrayscale3(Bitmap original)
{
//create a blank bitmap the same size as original
Bitmap newBitmap = new Bitmap(original.Width, original.Height);
//get a graphics object from the new image
using(Graphics g = Graphics.FromImage(newBitmap)){
//create the grayscale ColorMatrix
ColorMatrix colorMatrix = new ColorMatrix(
new float[][]
{
new float[] {.3f, .3f, .3f, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
//create some image attributes
using(ImageAttributes attributes = new ImageAttributes()){
//set the color matrix attribute
attributes.SetColorMatrix(colorMatrix);
//draw the original image on the new image
//using the grayscale color matrix
g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
}
}
return newBitmap;
}
Solution 2
Bitmap d = new Bitmap(c.Width, c.Height);
for (int i = 0; i < c.Width; i++)
{
for (int x = 0; x < c.Height; x++)
{
Color oc = c.GetPixel(i, x);
int grayScale = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11));
Color nc = Color.FromArgb(oc.A, grayScale, grayScale, grayScale);
d.SetPixel(i, x, nc);
}
}
This way it also keeps the alpha channel.
Enjoy.
Solution 3
There's a static method in ToolStripRenderer
class, named CreateDisabledImage
.
Its usage is as simple as:
Bitmap c = new Bitmap("filename");
Image d = ToolStripRenderer.CreateDisabledImage(c);
It uses a little bit different matrix than the one in the accepted answer and additionally multiplies it by a transparency of value 0.7, so the effect is slightly different than just grayscale, but if you want to just get your image grayed, it's the simplest and best solution.
Solution 4
The code below is the simplest solution:
Bitmap bt = new Bitmap("imageFilePath");
for (int y = 0; y < bt.Height; y++)
{
for (int x = 0; x < bt.Width; x++)
{
Color c = bt.GetPixel(x, y);
int r = c.R;
int g = c.G;
int b = c.B;
int avg = (r + g + b) / 3;
bt.SetPixel(x, y, Color.FromArgb(avg,avg,avg));
}
}
bt.Save("d:\\out.bmp");
Solution 5
None of the examples above create 8-bit (8bpp) bitmap images. Some software, such as image processing, only supports 8bpp. Unfortunately the MS .NET libraries do not have a solution. The PixelFormat.Format8bppIndexed format looks promising but after a lot of attempts I couldn't get it working.
To create a true 8-bit bitmap file you need to create the proper headers. Ultimately I found the Grayscale library solution for creating 8-bit bitmap (BMP) files. The code is very simple:
Image image = Image.FromFile("c:/path/to/image.jpg");
GrayBMP_File.CreateGrayBitmapFile(image, "c:/path/to/8bpp/image.bmp");
The code for this project is far from pretty but it works, with one little simple-to-fix problem. The author hard-coded the image resolution to 10x10. Image processing programs do not like this. The fix is open GrayBMP_File.cs (yeah, funky file naming, I know) and replace lines 50 and 51 with the code below. The example sets the resolution to 200x200 but you should change it to the proper number.
int resX = 200;
int resY = 200;
// horizontal resolution
Copy_to_Index(DIB_header, BitConverter.GetBytes(resX * 100), 24);
// vertical resolution
Copy_to_Index(DIB_header, BitConverter.GetBytes(resY * 100), 28);
0fnt
Updated on November 06, 2020Comments
-
0fnt over 3 years
Is there a way to convert an image to grayscale 16 bits per pixel format, rather than setting each of the r,g and b components to luminance. I currently have a bmp from file.
Bitmap c = new Bitmap("filename");
I want a Bitmap d, that is grayscale version of c. I do see a constructor that includes System.Drawing.Imaging.PixelFormat, but I don't understand how to use that. I'm new to Image Processing and the relevant C# libraries, but have a moderate experience with C# itself.
Any help, reference to an online source, hint or suggestion will be appreciated.
EDIT: d is the grayscale version of c.