如何从文件读取显示位图?
自己总结的,感觉有些书上说得不清楚!直接拷贝到View类中的OnDraw()函数中即可
一.MFC中如何从文件读取显示位图
1.新建一个CDC对象dc,dc的成员函数直接根据pDC(已经跟当前窗口关联了)创建一个内存DC,在内存DC中选入CBitmap,然后通过BitBlt把内存DC的东西显示
CDC dc;
CBitmap m_bitmap;
dc.CreateCompatibleDC (pDC)
HBITMAP hBitmap=(HBITMAP)LoadImage(NULL,"d:\\skagon.bmp",IMAGE_BITMAP,
0,0,LR_LOADFROMFILE);
m_bitmap.Attach (hBitmap);
BITMAP bm;
m_bitmap.GetBitmap (&bm);
dc.SelectObject (&m_bitmap);
pDC->BitBlt (0,0,bm.bmWidth ,bm.bmHeight ,&dc,0,0,SRCCOPY);
2.创建一个CClientDC(跟当前窗口关联),然后再新建一个新的CDC指针,指针的成员函数去:根据当前的CClientDC创建内存DC,在内存DC中选入CBitmap,然后通过BitBlt把内存DC的东西显示
CClientDC dc(this);
CDC * ddc = new CDC;
CBitmap bitmap;
ddc->CreateCompatibleDC(&dc);
bitmap.m_hObject=(HBITMAP)LoadImage(NULL,"d:\\skagon.bmp",IMAGE_BITMAP,
0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);
ddc->SelectObject(bitmap);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt (0,0,rect.right,rect.bottom,ddc,0,0,SRCCOPY);
3.和'1'的步骤大致一样,不过这里是用CBitmap.m_hObject变量去关联获取的句柄。而不是CBitmap.Attach()函数
CDC dc;
dc.CreateCompatibleDC(pDC);
CBitmap bitmap;
bitmap.m_hObject=(HBITMAP)LoadImage(NULL,"d:\\skagon.bmp",IMAGE_BITMAP,
0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);
dc.SelectObject(bitmap);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt (0,0,rect.right,rect.bottom,&dc,0,0,SRCCOPY);
4.从文件中载入内存,获得“bmp文件头指针&数据指针&宽&高”4个信息即可在View类中得OnDraw()函数中显示出来。
CFile dibFile("d:\\skagon.bmp",CFile::modeRead);
BYTE *pDib=new BYTE[dibFile.GetLength()];
dibFile.Read((void*)pDib,dibFile.GetLength());
BITMAPINFO * m_pBitmapInfo = (BITMAPINFO*)(pDib+14);
BITMAPINFOHEADER * m_pBitmapInfoHeader = (BITMAPINFOHEADER*)(pDib+14);
BYTE * m_pData = (pDib + 1078);
::StretchDIBits( pDC->m_hDC, 0, 0, m_pBitmapInfoHeader->biWidth, m_pBitmapInfoHeader->biHeight, 0, 0,
m_pBitmapInfoHeader->biWidth, m_pBitmapInfoHeader->biHeight,
m_pData, m_pBitmapInfo, DIB_RGB_COLORS, SRCCOPY );
//其中,pDC->m_hDC也可以更改为pDC->GetSafeHdc(),因为GetSafeHdc()的返回值就是m_hDC
二,SDK中如何从文件读取显示位图
(1)对于需要调色板的图,要想正确地显示,必须根据bmp文件,产生逻辑调色板。产生的方法是:
①为逻辑调色板指针分配内存,大小为逻辑调色板结构(LOGPALETTE)长度加NumColors个PALETTENTRY大小
(调色板的每一项都是一个PALETTEENTRY结构);
②填写逻辑调色板结构的头pPal->palNumEntries = NumColors; pPal->palVersion = 0x300;
③从文件中读取调色板的RGB值,填写到每一项中;
④产生逻辑调色板:hPalette=CreatePalette(pPal)。
(2)产生位图(BITMAP)句柄,该项工作由函数CreateDIBitmap来完成。
hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData,(LONG)CBM_INIT,
(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);
CreateDIBitmap的作用是产生一个和Windows设备无关的位图。该函数的第一项参数为设备上下文句柄。如果位图用到了调色板,要在调用CreateDIBitmap之前将逻辑调色板选入该设备上下文中,产生hBitmap后,再把原调色板选入该设备上下文中,并释放该上下文;
第二项为指向BITMAPINFOHEADER的指针;第三项就用常量CBM_INI,不用考虑;
第四项为指向调色板的指针;
第五项为指向BITMAPINFO(包括BITMAPINFOHEADER,调色板,及实际的图象数据)的指针;
第六项就用常量DIB_RGB_COLORS,不用考虑。
上面提到了设备上下文,相信编过Windows程序的读者对它并不陌生,这里再简单介绍一下。Windows操作系统统一管理着诸如显示,打印等操作,将它们看作是一个个的设备,每一个设备都有一个复杂的数据结构来维护。所谓设备上下文就是指这个数据结构。然而,我们不能直接和这些设备上下文打交道,只能通过引用标识它的句柄(实际上是一个整数),让Windows去做相应的处理。产生的逻辑调色板句柄hPalette和位图句柄hBitmap要在处理WM_PAINT消息时使用,这样才能在屏幕上显示出来,处理过程如下面的程序。
HDC hDC,hMemDC;
PAINTSTRUCT ps;
case WM_PAINT:
{
hDC = BeginPaint(hwnd, &ps); //获得屏幕设备上下文
if (hBitmap) //hBitmap一开始是NULL,当不为NULL时表示有图
{
hMemDC = CreateCompatibleDC(hDC); //建立一个内存设备上下文
if (hPalette) //有调色板
{ //将调色板选入屏幕设备上下文
SelectPalette (hDC, hPalette, FALSE);
//将调色板选入内存设备上下文
SelectPalette (hMemDC, hpalette, FALSE);
RealizePalette (hDC);
}
//将位图选入内存设备上下文
SelectObject(hMemDC, hBitmap);
//显示位图
BitBlt(hDC, 0, 0, bi.biWidth, bi.biHeight, hMemDC, 0, 0, SRCCOPY);
//释放内存设备上下文
DeleteDC(hMemDC);
}
//释放屏幕设备上下文
EndPaint(hwnd, &ps);
break;
}
在上面的程序中,我们调用CreateCompatibleDC创建一个内存设备上下文。SelectObject函数将与设备无关的位图选入内存设备上下文中。然后我们调用BitBlt函数在内存设备上下文和屏幕设备上下文中进行位拷贝。由于所有操作都是在内存中进行,所以速度很快。
![](https://img2024.cnblogs.com/blog/35695/202408/35695-20240826070647288-243310440.jpg)