1. 程式人生 > >HBITMAP與BITMAP 的區別 BMP影象的格式

HBITMAP與BITMAP 的區別 BMP影象的格式

HBITMAP 是控制代碼;
BITMAP 是例項:
typedef struct tagBITMAP { /* bm */
int bmType;//必須是BM
int bmWidth;//指定點陣圖的寬度(以象素為單位)
int bmHeight;//指定點陣圖的高度(以象素為單位)。
int bmWidthBytes;//一行幾個位元組,4位對齊
BYTE bmPlanes;//指定目標裝置的位面數
BYTE bmBitsPixel;//指定每個象素的位數
LPVOID bmBits;//指向圖象資料的指標
} BITMAP;
注意 bmBits是自己先前設定的 具體看下面複製的:
CBitmap::CreateBitmapIndirect函式的功能是用一個BITMAP結構體重的高度、寬度和位模式(如果指定了一個的話)來初始化一個位圖。呼叫該函式時,使用者可以設定bmBits欄位為NULL或者設為畫素位資料的地址(用以初始化該點陣圖)。
複製自:

http://bbs.csdn.net/topics/10310605
所以如果我們生成點陣圖的時候沒有設定bmBits ,之後通過下面的 方法得到的bm結構中的bmBits是NULL 是無效的指標
這時候我們可以通過GetDIBits獲得bmp影象的DIB格式的資料. 我們傳入的第6個引數 即LPBITMAPINFO 結構體會接收返回的點陣圖資訊 比如點陣圖資料大小 具體見下面BITMAPINFOHEADER的解釋

windows不允許直接對使用者物件操作,其操作得通過控制代碼來進行。
例如:
HBITMAP hBmp;
BITMAP bm;
GetObject(hBmp,sizeof(bm),&bm);
通過HBITMAP取得BITMAP;
以下不是轉載 而是個人理解 不對請指正:注意上面得到的bm是hBmp的資訊 它表示的是hBmp的固有屬性 假如它是與你的屏慕相容的bmp 那麼hBmp的資訊記錄的是螢幕點陣圖的資訊 不會改變。
GetDIBits 當你用點陣圖去獲取資訊時,獲取資訊的位數 什麼的 跟你傳入的BITMAPINFO結構有關係 假如這個bmp已經被選入螢幕DC 你要獲得螢幕的8點陣圖像(256色) 而一般你的螢幕是32位 那麼bm中存放的 bmBitsPixel是32 而你想到8位的話 就 需要在BITMAPINFO結構中設定 然後給GetDIBits作引數!

BMP影象 以下是有部分資訊是摘抄自其它網友的
由四部分組成:
A. 第一部分為點陣圖檔案頭BITMAPFILEHEADER,它是一個結構體,定義如下:
typedef struct tagBITMAPFILEHEADER{
WORD bfType; /檔案型別,必須是0x424D,即字串“BM”
DWORD bfSize; /指定檔案大小,包括這14個位元組
WORD bfReserved1; /保留字,不用考慮
WORD bfReserved2; /保留字,不用考慮
DWORD bfOffBits; /從檔案頭到實際點陣圖資料的偏移位元組數
}BITMAPFILEHEADER;
這個結構的長度是固定的,為14個位元組(WORD為無符號16位二進位制整數,DWORD為無符號32位二進位制整數)。
B. 第二部分為點陣圖資訊頭BITMAPINFOHEADER,也是一個結構,定義如下:
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; /該結構的長度,為40
LONG biWidth; / 影象的寬度,單位是畫素
LONG biHeight; / 影象的高度,單位是畫素
WORD biPlanes; / 位平面數,必須是1,不用考慮
WORD biBitCount;/ 指定顏色位數,1為二值,4為16色,8為256色,16、24、32為真彩色 DWORD biCompression; / 指定是否壓縮,有效的值為BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS
DWORD biSizeImage; / 實際的點陣圖資料佔用的位元組數
LONG biXPelsPerMeter; / 目標裝置水平解析度,單位是每米的畫素數
LONG biYPelsPerMeter; / 目標裝置垂直解析度,單位是每米的畫素數
DWORD biClrUsed;/實際使用的顏色數,若該值為0,則使用顏色數為2的bitBitCount次方種
DWORD biClrImportant; /影象中重要的顏色數,若該值為0,則所有的顏色都是重要的
} BITMAPINFOHEADER;
這個結構的長度是固定的,為40個位元組(LONG為32為二進位制整數)。
偏移 域的名稱 長度/位元組 內容
000Eh(14) biSize 4
檔案資訊頭的長度
40(28h):Windows
00012h(18) biWidth 4 點陣圖的寬度,以畫素為單位
00016h(22) biHeight 4 點陣圖的高度,以畫素為點為
001Ah(26) Biplanes 2 點陣圖的為平面數(該值總是為1)
001Ch(28) biBitCount 2
每個畫素的位平面數,有下面幾種情況:
1:單色點陣圖
4:16色點陣圖
8:256色點陣圖
16:16bit高彩色點陣圖
24:24bit真彩色點陣圖
32:32bit增強型真彩色點陣圖
001Eh(30) biCompression 4
壓縮說明:
0:不壓縮(用BI_RGB表示)
1:RLE8,使用8位RLE壓縮方式(用BI_RLE8表示)
2:RLE4,使用4位RLE壓縮方式(用BI_RLE4表示)
3:Bitfields:位域存放方式(用BI_BITFIELDS表示)
0022h(34) biSizeImage 4 點陣圖資料的大小,以位元組為單位。該數必須是4的倍數。當影象儲存的是非壓縮資料的時候,它的取值可以為0,實際上,此時點陣圖資料的大小可以通過biBitCount,biWidth,biHeight等計算出來
0026h(38) biXPelsPerMeter 4 用畫素/米表示的水平解析度
002Ah(42) biYPelsPerMeter 4 用畫素/米表示的垂直解析度
002Eh(46) biClrUsed 4 點陣圖使用的顏色數,如果為0則表示使用了全部可能的顏色
0032h(50) biClrImportant 4 指定重要的顏色數。當該域的值等於顏色數時(或者等於0時),表示所有顏色都一樣重要
C. 第三部分為調色盤(Palette),當然,這裡是對那些需要調色盤的點陣圖檔案而言的。真彩色影象不需要調色盤,BITMAPINFOHEADER後直接是點陣圖資料。調色盤實際上是一個數組,共有biClrUsed個元素(如果該值為零,則有2的biBitCount次方個元素)。陣列中每個元素的型別是一個RGBQUAD結構,佔4個位元組,其定義如下:
typedef struct tagRGBQUAD
{
BYTE rgbBlue; //該顏色的藍色分量
BYTE rgbGreen; //該顏色的綠色分量
BYTE rgbRed; //該顏色的紅色分量
BYTE rgbReserved;//保留值
} RGBQUAD;
D.第四部分是實際的影象資料,對於用到調色盤的點陣圖,影象資料就是該畫素顏色在調色盤中的索引值,對於真彩色影象,影象資料就是實際的R、G、B值:
• 對於2色點陣圖:用1位就可以表示該畫素的顏色(一般0表示黑,1表示白),所以一個
位元組就可以表示8個畫素;
• 對於16色點陣圖,用4位可以表示一個畫素的顏色,所以一個位元組可以表示2個畫素;
• 對於256色點陣圖,一個位元組剛好可以表示1個畫素;
色深24位的點陣圖
★ 每一行的位元組數必須是4的整數倍,如果不是,則需要補齊;(bitSizeImage中提到過)
★ BMP檔案的資料存放是從下到上,從左到右的。也就是說,從檔案中最先讀到的是影象最下面的左邊第一個畫素,然後是左邊第二個畫素,接下來是倒數第二行左邊第一個畫素,左邊第二個畫素,依次類推
每個畫素用3個位元組表示,順序依次為紅,綠和藍的值。每行用0填充到4位元組的邊界。

讀取影象資料的方法:
[cpp] view plain copy
HBITMAP hBmp = (HBITMAP)LoadImage( NULL , “z:\bg4.bmp” , IMAGE_BITMAP , 0 , 0 , LR_CREATEDIBSECTION | LR_LOADFROMFILE);
if (hBmp != NULL)
{
BITMAP bmp = {0};
int ret = GetObject( hBmp , sizeof(BITMAP) , &bmp );
if (ret)
{
TRACE( “Width = %d Height = %d BitsPerPixel = %d\n” , bmp.bmWidth , bmp.bmHeight , bmp.bmBitsPixel );

BYTE* pPixel = (BYTE*)bmp.bmBits; //指向BMP畫素的指標

int x = 1439 , y = 899; //指定要獲取畫素的座標 規定圖片左上角座標為0,0

BYTE pOffset = pPixel + (bmp.bmHeight - 1) bmp.bmWidthBytes; //指向最後一行畫素資料

pOffset = (pOffset - y * bmp.bmWidthBytes) + x * bmp.bmBitsPixel / 8; //指向指定畫素位置

DWORD rgb = 0;

memcpy( &rgb , pOffset , bmp.bmBitsPixel / 8 );

TRACE( “(x = %d y = %d) = %u\n” , x , y , rgb );

}

DeleteObject( hBmp );
hBmp = NULL;
ZeroMemory( &bmp , sizeof(bmp) );
}
//上面程式碼裡的rgb就是你要的畫素了

//如果你是在對話方塊之類的處理的話可以用類似下面的程式碼實現
CDC* pDc = GetDC();
POINT pt;
pt.x = 10;
pt.y = 10;
pDc->SetPixel( pt , RGB(255,0,0) );