【MFC】位图CBitmap、BITMAP、HBITMAP之间的转换

【MFC】位图CBitmap、BITMAP、HBITMAP之间的转换

一:理解

BITMAP是C++中定义的位图结构体

HBITMAP是Windows中使用的位图句柄

CBitmap是MFC封装的位图类

二:相互转换

1、HBITMAP->CBitmap 

方法一:

HBITMAP hBitmap=(HBITMAP)::LoadImage(NULL, str, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
CBitmap bitmap;
bitmap.Attach(hBitmap);

方法二:

 

HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, str, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);        
CBitmap *bitmap=CBitmap::FromHandle(hBitmap);

 

注意:Attach和FromHandle的区别

 

FromHandle得到的指针是临时变量,通过Attach连接的句柄可以长久保留,但通过FromHandle得到的只是暂时的,大概只在一个消息区间内有效,很快便会被删除,所以基本上不能用。我用了FromHandle然后一直出错!!!

 

实验源码,在(OnPaint函数中添加) 

复制代码
CString str = _T("E:\\picture\\lena.bmp");
HBITMAP hBitmap=(HBITMAP)::LoadImage(NULL, str, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
CBitmap bitmap;
bitmap.Attach(hBitmap);
CPaintDC dc(this);
CDC MemDC;
MemDC.CreateCompatibleDC(&dc);
MemDC.SelectObject(&bitmap);
CRect rect;
GetClientRect(&rect);
dc.BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);
复制代码

注意:CBitmap类中的成员函数:

BOOL LoadBitmap(LPCTSTR lpszRecourceName);   
BOOL LoadBitmap(UINT nIDResource); 

都可以加载位图,但他们只能加载工程中的位图,不能像LoadImage一样,加载硬盘中的位图。尤其要注意:

BOOL LoadBitmap(LPCTSTR lpszRecourceName)函数中的lpszRecourceName不能为路径字符串。它指的是位图的ID是用字符串表示的。 

比如:我在工程中创建了一个位图资源IDB_BITMAP1 ,lpszResourceName是指什么呢,是硬盘上的bitmap1.bmp吗,如果是,以下代码为什么是错的。

复制代码
CBitmap   bmp;   
bmp.LoadBitmap("d:\\..\\res\\bitmpa1.bmp");   
CDC   memdc;   
BITMAP   bm;   
bmp.GetBitmap(&bm);   
memdc.CreateCompatibleDC(pDC);   
memdc.SelectObject(&bmp);   
pDC->BitBlt(0,0,bm.bmWidth,bm.bmHeight,&memdc,0,0,SRCCOPY);  
复制代码

用Notepad打开*.rc文件,找到类似下面一行:   

IDB_BITMAP   BITMAP   "res\\background.bmp"   
改成:Bitmap1   BITMAP   "res\background.bmp"   
或者,在VC中察看位图资源的属性,将其ID栏内改为"Bitmap"(注意,一定要加引号)。
然后调用:bmp.LoadBitmap("Bitmap1"); 保证成功。   
资源可以用一个整数来标示,也可以用一个字符串标示。但无论如何,这些ID都不是指位图文件名。 

2、HBITMAP->BITMAP 

CString str = _T("E:\\picture\\lena.bmp");
HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, str, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
BITMAP bm;
::GetObject(hBitmap, sizeof(bm), &bm);

3、CBitmap->BITMAP

CBitmap bitmap;
bitmap.LoadBitmapW(IDB_BITMAP1);
BITMAP bm;
bitmap.GetBitmap(&bm);

4、CBitmap->HBITMAP

方法一:

CBitmap bitmap;        
bitmap.LoadBitmapW(IDB_BITMAP1);
HBITMAP hBitmap = (HBITMAP)bitmap.m_hObject;

方法二:

CBitmap bitmap;
bitmap.LoadBitmapW(IDB_BITMAP1);
HBITMAP hBitmap = (HBITMAP)bitmap;

5、BITMAP->HBITMAP

HBITMAP hBitmap;

pbm->GetHBITMAP(NULL, &hBitmap);

6、BITMAP->CBitmap 

Bitmap* pBitmap = new Bitmap(width,height,PixelFormat24bppRGB);
HBITMAP hBitmap;
BITMAP bm;
pBitmap ->GetHBITMAP(NULL,&hBitmap);
CBitmap* bmp;
bmp.Attach(hBitmap);

 

以下是将MFC 24位图转换为1位位图的源代码: // 获取24位图像素数据 CImage image; image.Load(_T("24bit.bmp")); BYTE* pSrc = (BYTE*)image.GetBits(); int nWidth = image.GetWidth(); int nHeight = image.GetHeight(); // 创建1位位图 CBitmap bitmap; bitmap.CreateBitmap(nWidth, nHeight, 1, 1, NULL); // 获取1位位图像素数据 BYTE* pDst = new BYTE[nWidth * nHeight / 8]; memset(pDst, 0, nWidth * nHeight / 8); BITMAPINFOHEADER bih; bih.biSize = sizeof(BITMAPINFOHEADER); bih.biWidth = nWidth; bih.biHeight = nHeight; bih.biPlanes = 1; bih.biBitCount = 1; bih.biCompression = BI_RGB; bih.biSizeImage = 0; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.biClrUsed = 0; bih.biClrImportant = 0; BITMAPINFO bi; bi.bmiHeader = bih; bi.bmiColors[0] = RGB(0, 0, 0); bi.bmiColors[1] = RGB(255, 255, 255); // 将24位图转换为1位位图 for (int i = 0; i < nHeight; i++) { for (int j = 0; j < nWidth; j++) { int nIndex = i * nWidth + j; BYTE r = pSrc[nIndex * 3]; BYTE g = pSrc[nIndex * 3 + 1]; BYTE b = pSrc[nIndex * 3 + 2]; BYTE nGray = (r * 30 + g * 59 + b * 11) / 100; if (nGray < 128) { pDst[i * ((nWidth + 31) / 32) + j / 8] |= (BYTE)(0x80 >> (j % 8)); } } } // 将1位位图像素数据写入位图对象 CBitmap* pOldBitmap = dc.SelectObject(&bitmap); SetDIBits(dc.GetSafeHdc(), (HBITMAP)bitmap.GetSafeHandle(), 0, nHeight, pDst, &bi, DIB_RGB_COLORS); dc.SelectObject(pOldBitmap); delete[] pDst; 注意:上述代码仅支持24位RGB格式的位图,如果需要支持其他格式的位图,需要根据实际情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值