Original article:
Http://hi.baidu.com/mayadong7349/blog/item/1b7e2b445f8e9e1c6a63e53a.html
# Include <stdio. h>
# Include <stdlib. h>
# Include <windows. h>
File * fpsrcbmpfile;
File * fpdestbmp file;
Void getbmpheader (pbitmapfileheader, pbitmapinfoheader );
Void changebmpheader (pbitmapfileheader, pbitmapinfoheader, word );
Void setbmpheader (const pbitmapfileheader, const pbitmapinfoheader );
Void setrgbquad ();
Void rgbtograde (); // 24-bit real color to 8-bit gray
Void gradetorgb (); // convert an 8-bit grayscale bitmap to a 24-bit real color
Int main (INT argc, char * argv [])
{
Bitmapfileheader bfheader; // BMP File Header
Bitmapinfoheader biheader; // Bitmap header
Memset (& bfheader, 0, sizeof (bitmapfileheader ));
Memset (& biheader, 0, sizeof (bitmapinfoheader ));
If (argc! = 2)
{
Puts ("\ n \ t *** error: I need two parameters .");
Puts ("\ t example: rgbtoquad.exe D: \ flower.bmp ");
System ("Pause> NUL ");
Exit (exit_success );
}
If (fpsrcbmpfile = fopen (argv [1], "rb") = NULL ){
Perror ("\ t *** open file failed :( read )");
System ("Pause> NUL ");
Exit (exit_failure );
}
Getbmpheader (& bfheader, & biheader );
If (bfheader. bftype! = 0x4d42 ){
Puts ("\ t * end: this file is not bitmap file .");
System ("Pause> NUL ");
Exit (exit_success );
}
If (biheader. bibitcount! = 24 & biheader. bibitcount! = 8 ){
Puts ("\ n * end: This BMP file is neither a 24bit nor a 8bit bitmap .");
System ("Pause> NUL ");
Exit (exit_success );
}
// The 8-Bit Bitmap that adopts the program length encoding method cannot be converted into a 24-Bit Bitmap according to this algorithm.
If (biheader. bibitcount = 8 & biheader. bicompression! = Bi_rgb ){
Puts ("\ n * end: This 8bit BMP file is not bi_rgb type ");
System ("Pause> NUL ");
Exit (exit_success );
}
If (fpdestbmp file = fopen ("D: \ _ done_.bmp", "WB") = NULL ){
Perror ("fopen failed :( write )");
System ("Pause> NUL ");
Exit (exit_failure );
}
Switch (biheader. bibitcount ){
Case 8: gradetorgb (); break;
Case 24: rgbtograde (); break;
Default: break;
}
Fclose (fpdestbmp file );
Fclose (fpsrcbmpfile );
System ("Pause> NUL ");
Return 0;
}
Void getbmpheader (pbitmapfileheader pbfheader, pbitmapinfoheader pbiheader)
{
Fread (pbfheader, sizeof (bitmapfileheader), 1, fpsrcbmpfile );
Fread (pbiheader, sizeof (bitmapinfoheader), 1, fpsrcbmpfile );
}
Void changebmpheader (pbitmapfileheader pbfheader, pbitmapinfoheader pbiheader, word wtype)
{
Pbiheader-> bibitcount = wtype; // 24 or 8
Pbiheader-> biclrused = (wtype = 24 )? 0: 256;
Pbfheader-> bfoffbits = 54 + pbiheader-> biclrused * sizeof (rgbquad );
Pbiheader-> bisizeimage = (pbiheader-> biwidth * pbiheader-> bibitcount) + 31 )&~ 31)/8) * pbiheader-> biheight;
Pbfheader-> bfsize = pbfheader-> bfoffbits + pbiheader-> bisizeimage;
}
Void setbmpheader (const pbitmapfileheader pbfheader, const pbitmapinfoheader pbiheader)
{
Fwrite (pbfheader, sizeof (bitmapfileheader), 1, fpdestbmp file );
Fwrite (pbiheader, sizeof (bitmapinfoheader), 1, fpdestbmp file );
}
Void setrgbquad ()
{
Int I;
Rgbquad [256];
For (I = 0; I <256; I ++ ){
Rgbquad [I]. rgbblue = I;
Rgbquad [I]. rgbgreen = I;
Rgbquad [I]. rgbred = I;
Rgbquad [I]. rgbreserved = 0;
}
Fwrite (rgbquad, 256 * sizeof (rgbquad), 1, fpdestbmp file );
}
Void rgbtograde (){
Long W, h;
Colorref RGB;
Byte R, G, B;
Byte gray;
Byte count24, count8;
Byte bmp nul = 0;
Bitmapfileheader bfheader; // BMP File Header
Bitmapinfoheader biheader; // Bitmap header
Memset (& bfheader, 0, sizeof (bitmapfileheader ));
Memset (& biheader, 0, sizeof (bitmapinfoheader ));
Rewind (fpsrcbmpfile );
Getbmpheader (& bfheader, & biheader );
Changebmpheader (& bfheader, & biheader, 8 );
Setbmpheader (& bfheader, & biheader );
Setrgbquad ();
Count24 = (4-(biheader. biwidth * 3) % 4) % 4;
Count8 = (4-(biheader. biwidth) % 4) % 4;
For (H = biheader. biHeight-1; h> = 0; h --){
For (W = 0; W <biheader. biwidth; W ++ ){
Fread (& RGB, 3, 1, fpsrcbmpfile );
If (feof (fpsrcbmpfile )){
Break;
}
// RGB: 0x00bbggrr
R = getbvalue (RGB );
G = getgvalue (RGB );
B = getrvalue (RGB );
// See http://zhidao.baidu.com/question/152910968.html
Gray = (byte) (77 * r + 151 * g + 28 * B)> 8); // 24-bit to 8-Bit Core Algorithm
Fwrite (& gray, sizeof (Gray), 1, fpdestbmp file );
} // For (W
Fseek (fpsrcbmpfile, count24, seek_cur );
Fwrite (& bmp nul, 1, count8, fpdestbmp file );
} // For (H =...
}
Void gradetorgb ()
{
Long W, h;
Colorref RGB;
Byte gray;
Byte count24, count8; // 24-Bit Bitmap, 8-Bit Bitmap, each scan line needs to be filled with 0 count
Byte bmp nul = 0;
Bitmapfileheader bfheader; // BMP File Header
Bitmapinfoheader biheader; // Bitmap header
Memset (& bfheader, 0, sizeof (bitmapfileheader ));
Memset (& biheader, 0, sizeof (bitmapinfoheader ));
Rewind (fpsrcbmpfile );
Getbmpheader (& bfheader, & biheader );
Changebmpheader (& bfheader, & biheader, 24 );
Setbmpheader (& bfheader, & biheader );
Fseek (fpsrcbmpfile, 256 * sizeof (rgbquad), seek_cur); // skip the color table because the 24-Bit Bitmap does not require a color table.
Count24 = (4-(biheader. biwidth * 3) % 4) % 4;
Count8 = (4-(biheader. biwidth) % 4) % 4;
For (H = biheader. biHeight-1; h> = 0; h --){
For (W = 0; W <biheader. biwidth; W ++ ){
Fread (& gray, 1, 1, fpsrcbmpfile );
If (feof (fpsrcbmpfile )){
Break;
}
RGB = RGB (Gray, gray, gray );//
8-bit to 24-Bit Core algorithms
Fwrite (& RGB, 3, 1, fpdestbmp file );
} // For (W
Fseek (fpsrcbmpfile, count8, seek_cur );
Fwrite (& bmp nul, 1, count24, fpdestbmp file );
} // For (H
}