bmp文件格式详细解析
?
先區(qū)分幾個(gè)概念:16色和16位色一樣嗎? 不一樣! 顏色位數(shù),即是用多少位字節(jié)表示的值,每一位可以表示0和1兩值。通常圖片的顏色深度,簡(jiǎn)稱色深,就是用位數(shù)來(lái)表示的,所以,我通常會(huì)看到8位色,16位色,24位色和32位色。而我們?cè)谄渌胤娇吹降挠质?6色,256色,16777216色等等,這些怎么一回事呢?
16色即代表16種顏色,256色即256種顏色,8位色就是用8個(gè)位來(lái)表示的顏色,即2的8次方,就是256色,16位色2的16次方,就是65536色,24位即16777216色,32位即4294967296色
他 們之間并不存在轉(zhuǎn)換關(guān)系,只有兼容關(guān)系,你不可能將紅色轉(zhuǎn)換為藍(lán)色,也不可能將一個(gè)黑白的圖片轉(zhuǎn)換成一個(gè)彩色圖片,但可以將彩色圖片變成黑白圖片,就像以 前的黑白電視機(jī)播放彩色錄像始終是黑白的,而彩色電視機(jī)播放黑白的錄像還是黑白的,當(dāng)由多到少時(shí),它會(huì)丟失顏色數(shù)據(jù),當(dāng)由少到多時(shí),并不會(huì)還原丟失的數(shù) 據(jù)。 好了,切入正題: bmp文件結(jié)構(gòu)解析: 一個(gè)bmp圖片最多由4大部分組成:BITMAPFILEHEADER結(jié)構(gòu)體,BITMAPINFOHEADER結(jié)構(gòu)體,RGBQUAD結(jié)構(gòu)體(這個(gè)結(jié)構(gòu)體可以有,也可以沒(méi)有),DIB數(shù)據(jù)區(qū)。其中DIB意思就是Device-Independent?Bitmap(設(shè)備無(wú)關(guān)位圖)。
一個(gè)bmp文件以BITMAPFILEHEADER結(jié)構(gòu)體開始,
typedef struct tagBITMAPFILEHEADER {
WORD bfType;//固定為0x4d42;
??? DWORD bfSize; //文件大小
?? ?WORD bfReserved1; //保留字,不考慮
??? WORD bfReserved2; //保留字,同上
??? DWORD bfOffBits; //實(shí)際位圖數(shù)據(jù)的偏移字節(jié)數(shù),即前三個(gè)部分長(zhǎng)度之和
??? } BITMAPFILEHEADER;
?BITMAPFILEHEADER的第1個(gè)屬性是bfType(2字節(jié)),這里恒定等于0x4D42。由于內(nèi)存中的數(shù)據(jù)排列高位在左,低位在右,所以內(nèi)存中從左往右看就顯示成(42 4D),所以在winhex中頭兩個(gè) 字節(jié)顯示為(42 4D)就是這樣形成的,以后的數(shù)據(jù)都是這個(gè)特點(diǎn),不再作重復(fù)說(shuō)明。
BITMAPFILEHEADER的第2個(gè)屬性是bfSize(4字節(jié)),表示整個(gè)bmp文件的大小。
BITMAPFILEHEADER的第3個(gè)、第4個(gè)屬性分別是bfReserved1、bfReserved2(各2字節(jié)),這里是2個(gè)保留屬性,都為0,這里等于&H0000、0x0000。
BITMAPFILEHEADER的第5個(gè)屬性是bfOffBits(4字節(jié)),表示DIB數(shù)據(jù)區(qū)在bmp文件中的位置偏移量,比如等于0x00000076=118,表示數(shù)據(jù)區(qū)從文件開始往后數(shù)的118字節(jié)開始。
?BITMAPFILEHEADER結(jié)構(gòu)體這里就講完了,大家會(huì)發(fā)現(xiàn)BITMAPFILEHEADER只占了bmp文件開始的14字節(jié)長(zhǎng)度,但需要 特別說(shuō)明的是:我們?cè)诰幊虝r(shí),經(jīng)常是以二進(jìn)制的形式打開一個(gè)bmp文件,然后將其開頭的14個(gè)字節(jié)讀入自己定義的BITMAPFILEHEADER 結(jié)構(gòu)體中,如果按上述定義結(jié)構(gòu)體的方式,需要注意,這個(gè)自己定義的結(jié)構(gòu)體在內(nèi)存中由于字節(jié)對(duì)齊,會(huì)占用16字節(jié)的空間,因而直接讀入16字節(jié),按字節(jié)順序 賦值給結(jié)構(gòu)體,出來(lái)的數(shù)據(jù)是錯(cuò)誤的,這樣的話,可以先將這14字節(jié)的數(shù)據(jù)讀入到一個(gè)緩沖器中,然后從緩沖器中按字節(jié)對(duì)結(jié)構(gòu)體進(jìn)行賦值。詳細(xì)程序見后附錄。 鑒于此中原因,在vb中定義一個(gè)BITMAPFILEHEADER結(jié)構(gòu)體變量,其長(zhǎng)度占了16個(gè)字節(jié),原因就是第1個(gè)屬性本來(lái)應(yīng)該只分配2個(gè)字節(jié),但實(shí)際被 分配了4個(gè)字節(jié),多出來(lái)2個(gè)字節(jié),所以如果想保存一張bmp圖片,寫入BITMAPFILEHEADER結(jié)構(gòu)體時(shí)一定要注意這一點(diǎn)。
接下來(lái)是BITMAPINFO結(jié)構(gòu)體部分。BITMAPINFO段由兩部分組成:BITMAPINFOHEADER結(jié)構(gòu)體和RGBQUAD結(jié)構(gòu) 體。其中RGBQUAD結(jié)構(gòu)體表示圖片的顏色信息,有些時(shí)候可以省略,一般的24位圖片和32位圖片都不帶RGBQUAD結(jié)構(gòu)體,因?yàn)镈IB數(shù)據(jù)區(qū)直接表 示的RGB值,一般4位圖片和8位圖片才帶有RGBQUAD結(jié)構(gòu)體。(多少位的圖片就是用多少位來(lái)表示一個(gè)顏色信息,例如4位圖片表示用4個(gè)bit來(lái)表示 一個(gè)顏色信息。)一個(gè)bmp文件中有沒(méi)有RGBQUAD結(jié)構(gòu)體,可以根據(jù)前面BITMAPFILEHEADER結(jié)構(gòu)體的第5個(gè)屬性bfOffBits來(lái)判 斷,因?yàn)锽ITMAPINFOHEADER結(jié)構(gòu)體長(zhǎng)度為40bit,如果BITMAPINFOHEADER結(jié)構(gòu)體結(jié)束后還未到DIB數(shù)據(jù)區(qū)的偏移量,就說(shuō) 明接下來(lái)的數(shù)據(jù)是RGBQUAD結(jié)構(gòu)體部分。
下面進(jìn)入正題BITMAPINFOHEADER部分。
typedef struct tagBITMAPINFOHEADER{
?//public:
?DWORD biSize; //指定此結(jié)構(gòu)體的長(zhǎng)度,為40
?LONG biWidth; //位圖寬
?LONG biHeight; //位圖高
?WORD biPlanes; //平面數(shù),為1
?WORD biBitCount; //采用顏色位數(shù),可以是1,2,4,8,16,24,新的可以是32
?DWORD biCompression; //壓縮方式,可以是0,1,2,其中0表示不壓縮
?DWORD biSizeImage; //實(shí)際位圖數(shù)據(jù)占用的字節(jié)數(shù)
?LONG biXPelsPerMeter; //X方向分辨率
?LONG biYPelsPerMeter; //Y方向分辨率
?DWORD biClrUsed; //使用的顏色數(shù),如果為0,則表示默認(rèn)值(2^顏色位數(shù))
?DWORD biClrImportant; //重要顏色數(shù),如果為0,則表示所有顏色都是重要的
} BITMAPINFOHEADER;
BITMAPINFOHEADER的第1個(gè)屬性是biSize(4字節(jié)),表示BITMAPINFOHEADER結(jié)構(gòu)體的長(zhǎng)度,最常見的長(zhǎng)度是40字節(jié)。
BITMAPINFOHEADER的第2個(gè)屬性是biWidth(4字節(jié)),表示bmp圖片的寬度
BITMAPINFOHEADER的第3個(gè)屬性是biHeight(4字節(jié)),表示bmp圖片的高度
BITMAPINFOHEADER的第4個(gè)屬性是biPlanes(2字節(jié)),表示bmp圖片的平面屬,顯然顯示器只有一個(gè)平面,所以恒等于1,這里等于0x0001。
BITMAPINFOHEADER的第5個(gè)屬性是biBitCount(2字節(jié)),表示bmp圖片的顏色位數(shù),即1位圖(單色或二值圖像),8位圖,16位圖,24位圖、32位圖等等。
BITMAPINFOHEADER的第6個(gè)屬性是biCompression(4字節(jié)),表示圖片的壓縮屬性,bmp圖片是不壓縮的,等于0,所以這里為0x00000000。
BITMAPINFOHEADER的第7個(gè)屬性是biSizeImage(4字節(jié)),表示bmp圖片數(shù)據(jù)區(qū)的大小,當(dāng)上一個(gè)數(shù)值biCompression等于0時(shí),這里的值可以省略不填,所以這里等于0x00000000。
BITMAPINFOHEADER的第8個(gè)屬性是biXPelsPerMeter(4字節(jié)),表示圖片X軸每米多少像素,可省略,這里等于0x00000EC3=3779像素/米。
BITMAPINFOHEADER的第9個(gè)屬性是biYPelsPerMeter(4字節(jié)),表示圖片Y軸每米多少像素,可省略,這里等于0x00000EC3=3779像素/米。
BITMAPINFOHEADER的第10個(gè)屬性是biClrUsed(4字節(jié)),表示使用了多少個(gè)顏色索引表,一般biBitCount屬性小于16才會(huì)用到,等于0時(shí)表示有2^biBitCount個(gè)顏色索引表,所以這里仍等于0x00000000。
BITMAPINFOHEADER的第11個(gè)屬性是biClrImportant(4字節(jié)),表示有多少個(gè)重要的顏色,等于0時(shí)表示所有顏色都很重要,所以這里等于0x00000000。
至此BITMAPINFOHEADER結(jié)構(gòu)體結(jié)束。
由于這個(gè)圖片到這里還未到達(dá)DIB數(shù)據(jù)區(qū)的偏移量,或者說(shuō)由于BITMAPINFOHEADER的第5個(gè)屬性是biBitCount<16,也就是在1位圖(只有兩種顏色),4位圖(只有2^4=16種顏色),8位圖(只有2^8=256種顏色)的情況下,此時(shí)會(huì)有顏色表,也就是接下來(lái)的部分:RGBQUAD結(jié)構(gòu)體。
//調(diào)色板Palette,當(dāng)然,這里是對(duì)那些需要調(diào)色板的位圖文件而言的。24位和32位是不需要調(diào)色板的。
//(調(diào)色板結(jié)構(gòu)體個(gè)數(shù)等于使用的顏色數(shù),即是多少色圖就有多少個(gè),4位圖16色,就有16個(gè)RGBQUAD結(jié)構(gòu)體。)
typedef struct tagRGBQUAD {
//public:
BYTE rgbBlue; //該顏色的藍(lán)色分量
BYTE rgbGreen; //該顏色的綠色分量
BYTE rgbRed; //該顏色的紅色分量
BYTE rgbReserved; //保留值
} RGBQUAD;
這里舉個(gè)4位圖也就是16色圖的例子:一 個(gè)RGBQUAD結(jié)構(gòu)體只占用4字節(jié)空間,從左到右每個(gè)字節(jié)依次表示(藍(lán)色,綠色,紅色,未使用)。舉例的這個(gè)圖片我數(shù)了數(shù)總共有16個(gè)RGBQUAD結(jié) 構(gòu)體,由于該圖片是4位圖,2^4正好等于16,所以它把16種顏色全部都枚舉出來(lái)了,這些顏色就是一個(gè)顏色索引表。顏色索引表編號(hào)從0開始,總共16個(gè) 顏色,所以編號(hào)為0-15。從winhex中可以看到按照順序,這16個(gè)RGBQUAD結(jié)構(gòu)體依次為:
編號(hào):(藍(lán),綠,紅,空)
0號(hào):(00,00,00,00)
1號(hào):(00,00,80,00)
2號(hào):(00,80,00,00)
3號(hào):(00,80,80,00)
4號(hào):(80,00,00,00)
5號(hào):(80,00,80,00)
6號(hào):(80,80,00,00)
7號(hào):(80,80,80,00)
8號(hào):(C0,C0,C0,00)
9號(hào):(00,00,FF,00)
10號(hào):(00,FF,00,00)
11號(hào):(00,FF,FF,00)
12號(hào):(FF,00,00,00)
13號(hào):(FF,00,FF,00)
14號(hào):(FF,FF,00,00)
15號(hào):(FF,FF,FF,00)
到這里,正好滿足DIB數(shù)據(jù)區(qū)的偏移量,所以后面的字節(jié)就是圖片內(nèi)容了。這里需要提醒的是所有的DIB數(shù)據(jù)掃描行是上下顛倒的,也就是說(shuō)一幅圖片先繪制底部的像素,再繪制頂部的像素,所以這些DIB數(shù)據(jù)所表示的像素點(diǎn)就是從圖片的左下角開始,一直表示到圖片的右上角。
?
程序附錄:
// std.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
//ReadBitMap
//
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define WIDTHBYTES(bits) (((bits)+31)/32*4)
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
//位圖文件頭信息結(jié)構(gòu)定義
//其中不包含文件類型信息(由于結(jié)構(gòu)體的內(nèi)存結(jié)構(gòu)決定,要是加了的話將不能正確讀取文件信息)
typedef struct tagBITMAPFILEHEADER {
?WORD bfType;//固定為0x4d42
?DWORD bfSize; //文件大小
?WORD bfReserved1; //保留字,不考慮
?WORD bfReserved2; //保留字,同上
?DWORD bfOffBits; //實(shí)際位圖數(shù)據(jù)的偏移字節(jié)數(shù),即前三個(gè)部分長(zhǎng)度之和
} BITMAPFILEHEADER;
//信息頭BITMAPINFOHEADER,也是一個(gè)結(jié)構(gòu),其定義如下:
typedef struct tagBITMAPINFOHEADER{
?//public:
?DWORD biSize; //指定此結(jié)構(gòu)體的長(zhǎng)度,為40
?LONG biWidth; //位圖寬
?LONG biHeight; //位圖高
?WORD biPlanes; //平面數(shù),為1
?WORD biBitCount; //采用顏色位數(shù),可以是1,2,4,8,16,24,新的可以是32
?DWORD biCompression; //壓縮方式,可以是0,1,2,其中0表示不壓縮
?DWORD biSizeImage; //實(shí)際位圖數(shù)據(jù)占用的字節(jié)數(shù)
?LONG biXPelsPerMeter; //X方向分辨率
?LONG biYPelsPerMeter; //Y方向分辨率
?DWORD biClrUsed; //使用的顏色數(shù),如果為0,則表示默認(rèn)值(2^顏色位數(shù))
?DWORD biClrImportant; //重要顏色數(shù),如果為0,則表示所有顏色都是重要的
} BITMAPINFOHEADER;
//調(diào)色板Palette,當(dāng)然,這里是對(duì)那些需要調(diào)色板的位圖文件而言的。24位和32位是不需要調(diào)色板的。
//(似乎是調(diào)色板結(jié)構(gòu)體個(gè)數(shù)等于使用的顏色數(shù)。)
typedef struct tagRGBQUAD {
?//public:
?BYTE rgbBlue; //該顏色的藍(lán)色分量
?BYTE rgbGreen; //該顏色的綠色分量
?BYTE rgbRed; //該顏色的紅色分量
?BYTE rgbReserved; //保留值
} RGBQUAD;
?
void showBmpHead(BITMAPFILEHEADER* pBmpHead)
{
?printf("位圖文件頭:\n");
?printf("bmp格式標(biāo)志bftype:0x%x\n",pBmpHead->bfType );
?printf("文件大小:%d\n",pBmpHead->bfSize);
?printf("保留字:%d\n",pBmpHead->bfReserved1);
?printf("保留字:%d\n",pBmpHead->bfReserved2);
?printf("實(shí)際位圖數(shù)據(jù)的偏移字節(jié)數(shù):%d\n",pBmpHead->bfOffBits);
}
void showBmpInforHead(tagBITMAPINFOHEADER* pBmpInforHead)
{
?printf("位圖信息頭:\n");
?printf("結(jié)構(gòu)體的長(zhǎng)度:%d\n",pBmpInforHead->biSize);
?printf("位圖寬:%d\n",pBmpInforHead->biWidth);
?printf("位圖高:%d\n",pBmpInforHead->biHeight);
?printf("biPlanes平面數(shù):%d\n",pBmpInforHead->biPlanes);
?printf("biBitCount采用顏色位數(shù):%d\n",pBmpInforHead->biBitCount);
?printf("壓縮方式:%d\n",pBmpInforHead->biCompression);
?printf("biSizeImage實(shí)際位圖數(shù)據(jù)占用的字節(jié)數(shù):%d\n",pBmpInforHead->biSizeImage);
?printf("X方向分辨率:%d\n",pBmpInforHead->biXPelsPerMeter);
?printf("Y方向分辨率:%d\n",pBmpInforHead->biYPelsPerMeter);
?printf("使用的顏色數(shù):%d\n",pBmpInforHead->biClrUsed);
?printf("重要顏色數(shù):%d\n",pBmpInforHead->biClrImportant);
}
void showRgbQuan(tagRGBQUAD* pRGB)
{
?printf("(%-3d,%-3d,%-3d) ",pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue);
}
?
void main()
{
?BITMAPFILEHEADER bitHead;
?BITMAPINFOHEADER bitInfoHead;
?FILE* pfile;
?char strFile[50];
?char *BmpFileHeader;
?WORD *temp_WORD;
?DWORD *temp_DWORD;
?printf("please input the .bmp file name:\n");
?scanf("%s",strFile);
?
?pfile = fopen(strFile,"rb");//打開文件
??? BmpFileHeader=(char *)calloc(14,sizeof(char));
?if(pfile!=NULL)
?{
??printf("file bkwood.bmp open success.\n");
??//讀取位圖文件頭信息
??
??
??
??fread(BmpFileHeader,1,14,pfile);
??temp_WORD=(WORD* )(BmpFileHeader);
??bitHead.bfType=*temp_WORD;
??if(bitHead.bfType != 0x4d42)
??{
???printf("file is not .bmp file!");
???
???return;
??}
??temp_DWORD=(DWORD *)(BmpFileHeader+sizeof(bitHead.bfType));
??bitHead.bfSize=*temp_DWORD;
??temp_WORD=(WORD*)(BmpFileHeader+sizeof(bitHead.bfType)+sizeof(bitHead.bfSize));
??bitHead.bfReserved1=*temp_WORD;
??temp_WORD=(WORD*)(BmpFileHeader+sizeof(bitHead.bfType)+sizeof(bitHead.bfSize)+sizeof(bitHead.bfReserved1));
??bitHead.bfReserved2=*temp_WORD;
??temp_DWORD=(DWORD*)(BmpFileHeader+sizeof(bitHead.bfType)+sizeof(bitHead.bfSize)+sizeof(bitHead.bfReserved1)+sizeof(bitHead.bfReserved2));
??bitHead.bfOffBits=*temp_DWORD;
?
??
??
??showBmpHead(&bitHead);
??printf("\n\n");
?
??//讀取位圖信息頭信息
??fread(&bitInfoHead,1,sizeof(BITMAPINFOHEADER),pfile);
??showBmpInforHead(&bitInfoHead);
??printf("\n");
??
?}
?else
?{
??printf("file open fail!\n");
??return;
?}
?
?tagRGBQUAD *pRgb ;
?if(bitInfoHead.biBitCount < 24)//有調(diào)色板
?{
??//讀取調(diào)色盤結(jié)信息
??long nPlantNum = long(pow(2,double(bitInfoHead.biBitCount))); // Mix color Plant Number;
??pRgb=(tagRGBQUAD *)malloc(nPlantNum*sizeof(tagRGBQUAD));
??memset(pRgb,0,nPlantNum*sizeof(tagRGBQUAD));
??int num = fread(pRgb,4,nPlantNum,pfile);
??printf("Color Plate Number: %d\n",nPlantNum);
??printf("顏色板信息:\n");
??for (int i =0; i<nPlantNum;i++)
??{
???if (i%5==0)
???{
????printf("\n");
???}
???showRgbQuan(&pRgb[i]);
??}
??printf("\n");
?}
?int width = bitInfoHead.biWidth;
?int height = bitInfoHead.biHeight;
?//分配內(nèi)存空間把源圖存入內(nèi)存
?int l_width = WIDTHBYTES(width* bitInfoHead.biBitCount);//計(jì)算位圖的實(shí)際寬度并確保它為32的倍數(shù)
?BYTE *pColorData=(BYTE *)malloc(height*l_width);
?memset(pColorData,0,height*l_width);
?long nData = height*l_width;
?//把位圖數(shù)據(jù)信息讀到數(shù)組里
?fread(pColorData,1,nData,pfile);
?
?//將位圖數(shù)據(jù)轉(zhuǎn)化為RGB數(shù)據(jù)
?tagRGBQUAD* dataOfBmp;
?dataOfBmp = (tagRGBQUAD *)malloc(width*height*sizeof(tagRGBQUAD));//用于保存各像素對(duì)應(yīng)的RGB數(shù)據(jù)
?memset(dataOfBmp,0,width*height*sizeof(tagRGBQUAD));
?if(bitInfoHead.biBitCount<24)//有調(diào)色板,即位圖為非真彩色
?{
??int k;
??int index = 0;
??if (bitInfoHead.biBitCount == 1)
??{
???for(int i=0;i<height;i++)
????for(int j=0;j<width;j++)
????{
?????BYTE mixIndex= 0;
?????k = i*l_width + j/8;//k:取得該像素顏色數(shù)據(jù)在實(shí)際數(shù)據(jù)數(shù)組中的序號(hào)
?????//j:提取當(dāng)前像素的顏色的具體值
?????mixIndex = pColorData[k];
?????switch(j%8)
?????{
?????case 0:
??????mixIndex = mixIndex<<7;
??????mixIndex = mixIndex>>7;
??????break;
?????case 1:
??????mixIndex = mixIndex<<6;
??????mixIndex = mixIndex>>7;
??????break;
?????case 2:
??????mixIndex = mixIndex<<5;
??????mixIndex = mixIndex>>7;
??????break;
?????case 3:
??????mixIndex = mixIndex<<4;
??????mixIndex = mixIndex>>7;
??????break;
?????case 4:
??????mixIndex = mixIndex<<3;
??????mixIndex = mixIndex>>7;
??????break;
?????case 5:
??????mixIndex = mixIndex<<2;
??????mixIndex = mixIndex>>7;
??????break;
?????case 6:
??????mixIndex = mixIndex<<1;
??????mixIndex = mixIndex>>7;
??????break;
?????case 7:
??????mixIndex = mixIndex>>7;
??????break;
?????}
?????//將像素?cái)?shù)據(jù)保存到數(shù)組中對(duì)應(yīng)的位置
?????dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;
?????dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;
?????dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;
?????dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;
?????index++;
????}
??}
??if(bitInfoHead.biBitCount==2)
??{
???for(int i=0;i<height;i++)
????for(int j=0;j<width;j++)
????{
?????BYTE mixIndex= 0;
?????k = i*l_width + j/4;//k:取得該像素顏色數(shù)據(jù)在實(shí)際數(shù)據(jù)數(shù)組中的序號(hào)
?????//j:提取當(dāng)前像素的顏色的具體值
?????mixIndex = pColorData[k];
?????switch(j%4)
?????{
?????case 0:
??????mixIndex = mixIndex<<6;
??????mixIndex = mixIndex>>6;
??????break;
?????case 1:
??????mixIndex = mixIndex<<4;
??????mixIndex = mixIndex>>6;
??????break;
?????case 2:
??????mixIndex = mixIndex<<2;
??????mixIndex = mixIndex>>6;
??????break;
?????case 3:
??????mixIndex = mixIndex>>6;
??????break;
?????}
?????//將像素?cái)?shù)據(jù)保存到數(shù)組中對(duì)應(yīng)的位置
?????dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;
?????dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;
?????dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;
?????dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;
?????index++;
????}
??}
??if(bitInfoHead.biBitCount == 4)
??{
???for(int i=0;i<height;i++)
????for(int j=0;j<width;j++)
????{
?????BYTE mixIndex= 0;
?????k = i*l_width + j/2;
?????mixIndex = pColorData[k];
?????if(j%2==0)
?????{//低
??????mixIndex = mixIndex<<4;
??????mixIndex = mixIndex>>4;
?????}
?????else
?????{//高
??????mixIndex = mixIndex>>4;
?????}
?????dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;
?????dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;
?????dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;
?????dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;
?????index++;
????}
??}
??if(bitInfoHead.biBitCount == 8)
??{
???for(int i=0;i<height;i++)
????for(int j=0;j<width;j++)
????{
?????BYTE mixIndex= 0;
?????k = i*l_width + j;
?????mixIndex = pColorData[k];
?????dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;
?????dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;
?????dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;
?????dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;
?????index++;
?
????}
??}
??if(bitInfoHead.biBitCount == 16)
??{
???for(int i=0;i<height;i++)
????for(int j=0;j<width;j++)
????{
?????WORD mixIndex= 0;
?????k = i*l_width + j*2;
?????WORD shortTemp;
?????shortTemp = pColorData[k+1];
?????shortTemp = shortTemp<<8;
?????mixIndex = pColorData[k] + shortTemp;
?????dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;
?????dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;
?????dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;
?????dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;
?????index++;
????}
??}
?}
?else//位圖為24位真彩色
?{
??int k;
??int index = 0;
??for(int i=0;i<height;i++)
???for(int j=0;j<width;j++)
???{
????k = i*l_width + j*3;
????dataOfBmp[index].rgbRed = pColorData[k+2];
????dataOfBmp[index].rgbGreen = pColorData[k+1];
????dataOfBmp[index].rgbBlue = pColorData[k];
????index++;
???}
?}
?printf("像素?cái)?shù)據(jù)信息:\n");
/*
?for (int i=0; i<width*height; i++)
?{
??if (i%5==0)
??{
???printf("\n");
??}
??showRgbQuan(&dataOfBmp[i]);
?}
*/
?fclose(pfile);
?
?if (bitInfoHead.biBitCount<24)
?{
??free(pRgb);
?}
?free(dataOfBmp);
?free(pColorData);
???free(BmpFileHeader);
?printf("\n");
}?
轉(zhuǎn)載于:https://www.cnblogs.com/h2zZhou/p/5280789.html
總結(jié)
以上是生活随笔為你收集整理的bmp文件格式详细解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 给UIButton添加背景图片
- 下一篇: 读书笔记第一二章