In image processing, we often need to convert real-color images into black and white images. Strictly speaking, it should be a grayscale image, because the real black and white images are only pure black and pure white. Before getting started, let's briefly add the image representation principles in the computer. Images in computers can be roughly divided into bitmap and Metafile ). Bitmap can be regarded as a two-dimensional grid. The entire image is composed of multiple points. The number of points equals to the width of the bitmap multiplied by the height. Each vertex is called a pixel. Each pixel has a definite color. When many elements are combined, a complete image is formed. Most of the images we usually use are bitmaps, such as those taken by a digital camera. Because the bitmap can perfectly represent the details of the image, it can better restore the original scene of the image. However, bitmap also has disadvantages: first, it is relatively large, so many compressed image formats have been developed to store bitmap images. Currently, the most widely used format is JPEG, which has been widely used on the web, in addition, there are GIF, PNG, and so on. The second is that when bitmap is enlarged, it is inevitable that the bitmap will appear "sawtooth", which is also determined by the essential characteristics of the bitmap. Therefore, in reality, we also need to use another image format: vector image. Different from bitmap, a vector chart is different from a bitmap. A vector chart is drawn using mathematical formulas through circles, line segments, and so on. Therefore, no deformation occurs during amplification, however, vector images cannot describe very complex images. Vector graphs are used to describe graphic patterns, and various CAD software are used to save files in vector format.
Before explaining the color conversion, we need to first understand the Color Representation of Bitmap. In bitmap, color is usually represented in RGB three colors (the color palette is used when there are few digits ). Therefore, each pixel uses different digits to indicate different numbers of colors. As shown in:
Number of digits per pixel |
Number of colors that a pixel can allocate |
1 |
2 ^ 1 = 2 |
2 |
2 ^ 2 = 4 |
4 |
2 ^ 4 = 16 |
8 |
2 ^ 8 = 256 |
16 |
2 ^ 16 = 65,536 |
24 |
2 ^ 24 = 16,777,216 |
We can see that when we use a 24-bit color (3 bytes), we can get more than 16 million colors, which are already very rich.
It should be close to the color that can be distinguished by the human eye. Currently, the most commonly used color in the computer is the 24-bit color. Do not use the external GDI + with a 32-bit color. The extra channel is used to describe Alpha, that is, the transparent component.
The three bytes in the 24-bit color are used to describe the R, G, and B color components respectively. We can see that there is no brightness component, because in the RGB representation, brightness can also be obtained directly from the color component. The range of each color component value ranges from 0 to 255. The greater the value of a color component, it indicates that the brightness of this component is higher, so 255 indicates the brightest, and 0 indicates the lowest. So what is the brightness value of a Real-Color Pixel when it is converted to a grayscale image? The average value we first think of is R + G + B/3. In reality, we use the following formula:
Y = 0.299r + 0.587G + 0.114b
This formula is generally referred to as the grayscale formula of psychology. Here we can see that the green component accounts for the largest proportion. Scientists found that the grayscale image obtained by using the above formula is the closest to the human's perception of the grayscale image.
Because there are only 256 colors (one byte) in a grayscale image, the converted image is usually saved in the 8-bit format instead of the 24-bit format, which saves space. The 8-Bit Bitmap uses the color palette to save the color. Instead of directly saving the color value. 256 colors can be saved in the color palette, so 256 gray colors can be saved to the color palette. The Code is as follows:
Using system;
Using system. Collections. Generic;
Using system. text;
Using system. drawing;
Using system. Drawing. imaging;
Namespace consoleapplication2
{
Class Program
{
Unsafe static void main (string [] ARGs)
{
Bitmap IMG = (Bitmap) image. fromfile (@ "E: \ My Documents ents \ my pictures \ cherry_blossom_1002.jpg ");
Bitmap bit = new Bitmap (IMG. Width, IMG. Height, pixelformat. format8bppindexed );
Bitmapdata DATA = IMG. lockbits (New rectangle (0, 0, IMG. Width, IMG. Height), imagelockmode. readonly, pixelformat. format24bpprgb );
Byte * BP = (byte *) data. scan0.topointer ();
Bitmapdata data2 = bit. lockbits (New rectangle (0, 0, bit. Width, bit. Height), imagelockmode. readwrite, pixelformat. format8bppindexed );
Byte * bp2 = (byte *) data2.scan0. topointer ();
For (INT I = 0; I! = Data. height; I ++)
{
For (Int J = 0; J! = Data. width; j ++)
{
// 0.3r + 0.59G + 0.11b
Float value = 0.11f * BP [I * data. stride + J * 3] + 0.59f * BP [I * data. stride + J * 3 + 1] + 0.3f * BP [I * data. stride + J * 3 + 2];
Bp2 [I * data2.stride + J] = (byte) value;
}
}
IMG. unlockbits (data );
Bit. unlockbits (data2 );
Colorpalette palette = bit. palette;
For (INT I = 0; I! = Palette. Entries. length; I ++)
{
Palette. Entries [I] = color. fromargb (I, I, I );
}
Bit. palette = palette;
Bit. Save (@ "E: \ temp \ bb.jpeg", imageformat. JPEG );
IMG. Dispose ();
Bit. Dispose ();
}
}
}
In the code, I used pointers to directly manipulate bitmap data. The same operation is much faster than getpixel and setpixel. We would like to thank Microsoft for retaining this powerful tool in C.