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字節的邊界。



讀取圖像數據的方法:

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) );



部分摘抄來自http://blog.sina.com.cn/s/blog_48f0f4da0100c3es.html

      http://blog.sina.com.cn/s/blog_49dd59fe01011wbj.html


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com