I'm trying to build a function to convert a color image to monochrome. There's a lot of confusion around terminology, but I'm talking about true black-and-white, where we only have 2 colors: black and white - no grays.
Here is an example of what I'm trying to achieve:
I also wanted a way to control the "threshold" of the conversion (i.e. how "bright" does a pixel have to be to produce a white pixel).
Here is what I have right now.
private Bitmap bitmap2Monochrome(Bitmap srcImg, int brightness)
{
Bitmap monoImg = new Bitmap(srcImg.Width, srcImg.Height);
// Loop through all the pixels in the image
for (int y = 0; y < srcImg.Height; y++)
{
for (int x = 0; x < srcImg.Width; x++)
{
// Get pixel color
Color existingColor = srcImg.GetPixel(x, y);
// Average R, G, and B to determine "brightness" of this pixel
int gray = (int)((existingColor.R + existingColor.G + existingColor.G) / 3);
// If the "brightness" is greater than the threshold, this is a white pixel
int color = 0;
if (gray > brightness)
{
color = 255;
}
// Update the output image
Color newColor = Color.FromArgb(color, color, color);
monoImg.SetPixel(x, y, newColor);
}
}
return monoImg;
}
This method works exactly the way I want, but it is (understandably) very slow. This is due to the fact that the GetPixel()
and SetPixel()
functions are very slow.
I would love to use a ColorMatrix
because they are so fast, but I'm not very good at matrices, and I can't seem to come up with a matrix that would achieve this result.
Here's an example of how the logic works:
- Source color =
(200, 150, 250)
- So, grayscale equivalent =
(200, 200, 200)
- So, gray value =
200
- So,
200 > threshold
- So, monochrome value =
255
- So, monochrome color =
(255, 255, 255)
Is there any way I could achieve this sort of functionality using a ColorMatrix
?
I'm also open to other ideas!