HBITMAP与BITMAP 的区别 BMP图像的格式

58 篇文章 0 订阅
50 篇文章 0 订阅

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

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是将 hBitmap 保存成 bmp 图片的代码: ```c void SaveBitmapToBmp(HBITMAP hBitmap, LPCWSTR filePath) { HDC hDC; int iBits; WORD wBitCount; DWORD dwPaletteSize = , dwBmBitsSize, dwDIBSize, dwWritten; BITMAP Bitmap; BITMAPFILEHEADER bmfHdr; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; HANDLE fh, hDib, hPal, hOldPal = NULL; hDC = CreateDC(L"DISPLAY", NULL, NULL, NULL); iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); DeleteDC(hDC); if (iBits <= 1) wBitCount = 1; else if (iBits <= 4) wBitCount = 4; else if (iBits <= 8) wBitCount = 8; else wBitCount = 24; GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap); bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = Bitmap.bmWidth; bi.biHeight = Bitmap.bmHeight; bi.biPlanes = 1; bi.biBitCount = wBitCount; bi.biCompression = BI_RGB; bi.biSizeImage = ; bi.biXPelsPerMeter = ; bi.biYPelsPerMeter = ; bi.biClrUsed = ; bi.biClrImportant = ; dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight; hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER)); lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); *lpbi = bi; hPal = GetStockObject(DEFAULT_PALETTE); if (hPal) { hDC = GetDC(NULL); hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE); RealizePalette(hDC); } GetDIBits(hDC, hBitmap, , (UINT)Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + dwPaletteSize, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); if (hOldPal) { SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); RealizePalette(hDC); ReleaseDC(NULL, hDC); } fh = CreateFile(filePath, GENERIC_WRITE, , NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (fh == INVALID_HANDLE_VALUE) return; bmfHdr.bfType = x4D42; dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; bmfHdr.bfSize = dwDIBSize; bmfHdr.bfReserved1 = ; bmfHdr.bfReserved2 = ; bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize; WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL); GlobalUnlock(hDib); GlobalFree(hDib); CloseHandle(fh); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值