24位點陣圖轉8位灰度圖
阿新 • • 發佈:2019-02-07
如何用RGB轉化得到的灰度資料寫入8位bmp檔案,請看如下程式碼
其中lp中儲存的是已經轉化得到的現成灰度資料,標紅的程式碼是與24位點陣圖不同的地方。
<span style="font-size:18px;">//(整個點陣圖由檔案頭、資訊頭、調色盤、顏色表這四部分組合構成 typedef long LONG; typedef unsigned long DWORD; typedef unsigned short WORD; #pragma pack (push ,1)//由於4位元組對齊,而資訊頭大小為54位元組,第一部分14位元組, //第二部分40位元組,所以會將第一部分補齊為16自己,直接用sizeof,開啟圖片時就會 //遇到premature end-of-file encountered錯誤 typedef struct {//點陣圖檔案頭,14位元組 WORD bfType; // 指定檔案型別,必須是0x424D,即字串“BM”,也就是說所有.bmp檔案的頭兩個位元組都是“BM”。 DWORD bfSize; // 點陣圖檔案的大小,包括這14個位元組,以位元組為單位 WORD bfReserved1; // 點陣圖檔案保留字,必須為0 WORD bfReserved2; // 點陣圖檔案保留字,必須為0 DWORD bfOffBits; // 點陣圖資料的起始位置,以相對於點陣圖, 檔案頭的偏移量表示,以位元組為單位 } BMPFILEHEADER_T; #pragma pack (pop) typedef struct{//這個結構的長度是固定的,為40個位元組,可以自己算一下,DWORD、LONG4個位元組,WORD兩個位元組 DWORD biSize;//指定這個結構的長度,為40 LONG biWidth;//指定圖象的寬度,單位是象素。 LONG biHeight;//指定圖象的高度,單位是象素。 WORD biPlanes;//必須是1,不用考慮。 WORD biBitCount;/*指定表示顏色時要用到的位數,常用的值為1(黑白二色圖), 4(16色圖), 8(256色), 24(真彩色圖)(新的.bmp格式支援32位色,這裡就不做討論了)。*/ DWORD biCompression;/*指定點陣圖是否壓縮,有效的值為BI_RGB,BI_RLE8,BI_RLE4, BI_BITFIELDS(都是一些Windows定義好的常量)。要說明的是, Windows點陣圖可以採用RLE4,和RLE8的壓縮格式,但用的不多。 我們今後所討論的只有第一種不壓縮的情況,即biCompression為BI_RGB的情況。*/ DWORD biSizeImage;/*指定實際的點陣圖資料佔用的位元組數,其實也可以從以下的公式中計算出來: biSizeImage=biWidth’ × biHeight 要注意的是:上述公式中的biWidth’必須是4的整倍數(所以不是biWidth,而是biWidth’, 表示大於或等於biWidth的,最接近4的整倍數。舉個例子,如果biWidth=240,則biWidth’=240; 如果biWidth=241,biWidth’=244)。如果biCompression為BI_RGB,則該項可能為零*/ LONG biXPelsPerMeter;//指定目標裝置的水平解析度,單位是每米的象素個數 LONG biYPelsPerMeter;//指定目標裝置的垂直解析度,單位同上。 DWORD biClrUsed;//指定本圖象實際用到的顏色數,如果該值為零,則用到的顏色數為2的biBitCount指數次冪 DWORD biClrImportant;//指定本圖象中重要的顏色數,如果該值為零,則認為所有的顏色都是重要的。 } BMPINFOHEADER_T; char * bmp_file = "行人資料庫-負樣本99.bmp";//要儲存的bmp檔名,字尾不要忘了 //int width = cx.GetWidth(); //int height = cx.GetHeight(); // 點陣圖第一部分,檔案資訊 BMPFILEHEADER_T bfh; int kk = sizeof(BMPFILEHEADER_T);//14,不對齊的話會得到16,這樣建立的BMP打不開 int nn = sizeof(BMPINFOHEADER_T);// second section size,40 bfh.bfType = (WORD)0x4d42; //bm //灰度影象8位深度 int newbiBitCount = 8; //8點陣圖像資料每行位元組數為4的倍數 int lineByte = (width * newbiBitCount / 8 + 3) / 4 * 4; //灰度圖有顏色表,顏色表大小,以位元組為單位,灰度影象顏色表為1024位元組,彩色影象顏色表大小為0 int colorTablesize = 1024; <span style="color:#ff0000;">bfh.bfSize = kk + nn + colorTablesize + lineByte*height;</span> bfh.bfReserved1 = 0; // reserved bfh.bfReserved2 = 0; // reserved bfh.bfOffBits = sizeof(BMPFILEHEADER_T) + sizeof(BMPINFOHEADER_T);//真正的資料的位置 // 點陣圖第二部分,資料資訊 BMPINFOHEADER_T bih; bih.biSize = sizeof(BMPINFOHEADER_T); bih.biWidth = width; bih.biHeight = height; bih.biPlanes = 1;//為1,不用改 <span style="color:#ff0000;">bih.biBitCount = newbiBitCount;</span> bih.biCompression = 0;//不壓縮 bih.biSizeImage = datalen; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.biClrUsed = 0; bih.biClrImportant = 0;//每個畫素都重要 FILE * fp = fopen(bmp_file, "wb");//建立bmp檔案 if (!fp) return-1; fwrite(&bfh, 8, 1, fp); fwrite(&bfh.bfReserved2, sizeof(bfh.bfReserved2), 1, fp); fwrite(&bfh.bfOffBits, sizeof(bfh.bfOffBits), 1, fp); fwrite(&bih, sizeof(BMPINFOHEADER_T), 1, fp); //灰度影象,有顏色表,寫入檔案 RGBQUAD colortable[256]; for (int i = 0; i<256; ++i) { colortable[i].rgbBlue = i; colortable[i].rgbGreen = i; colortable[i].rgbRed = i; colortable[i].rgbReserved = 0; } RGBQUAD* pColorTable1 = colortable; <span style="color:#ff0000;">fwrite(pColorTable1, sizeof(RGBQUAD), 256, fp);</span> //為新影象申請空間 BYTE*ptempimageBuf = new unsigned char[lineByte*height]; if (!ptempimageBuf) return -3; for (int i = 0; i<height; i++) //color change from 24 to 8 bit { for (int j = 0, k = 0; j<width; j++) { ptempimageBuf[i*lineByte + j] = lp[i*width+j]; } } //寫入rgb資料 <span style="color:#ff0000;">fwrite(ptempimageBuf, lineByte*height, 1, fp);</span> fclose(fp); delete[]ptempimageBuf;</span>