以下代码未经过测试,只是编译没有问题,以前同事问到这个,所以才有下面代码:
class CBitmapBits { public: CBitmapBits() : m_pBitsBuf(NULL) , m_dwWidth(0) , m_dwHeight(0) { } ~CBitmapBits() { Destroy(); } // 释放位图数据 void Destroy() { if (m_pBitsBuf != NULL) { delete[] m_pBitsBuf; m_pBitsBuf = NULL; } m_dwWidth = 0; m_dwHeight = 0; } public: BYTE *m_pBitsBuf; // 据按RGB排列,按行优先排列,无4字节对齐,大小等于:宽度*高度*3 DWORD m_dwWidth; // 位图宽度 DWORD m_dwHeight; // 位图高度 }; // 把HBITMAP绘制到DC左上角 BOOL DrawHBitmapToDC( IN HBITMAP hBitmap, // 位图句柄 IN HDC hDC // 待绘制DC ) { // 参数有效性 if (hBitmap==NULL || hDC==NULL) { return FALSE; } // 取得位图数据信息,宽度高度等 BITMAP bmpObj = {0}; if ( ::GetObject(hBitmap, sizeof(bmpObj), &bmpObj) == 0 || bmpObj.bmWidth <= 0 || bmpObj.bmHeight <= 0 ) { return FALSE; } // 创建内存DC HDC hMemDC = ::CreateCompatibleDC(hDC); if (hMemDC == NULL) { return FALSE; } // 把HBITMAP选入内存DC HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap); // 把内存DC拷贝绘制到目标DC上 ::BitBlt(hDC, 0, 0, bmpObj.bmWidth, bmpObj.bmHeight, hMemDC, 0, 0, SRCCOPY); // 释放内存DC ::SelectObject(hMemDC, hOldBitmap); ::DeleteDC(hMemDC); // 绘制成功 return TRUE; } // 由HBITMAP获取位图数据 BOOL GetHBitmapBits( IN HBITMAP hBitmap, // 位图句柄 OUT CBitmapBits &bitmapBits // 输出颜色数 ) { // 初始化输出参数 bitmapBits.Destroy(); // 参数有效性 if (hBitmap == NULL) { return FALSE; } // 取得位图数据信息,宽度高度等 BITMAP bmpObj = {0}; if ( ::GetObject(hBitmap, sizeof(bmpObj), &bmpObj) == 0 || bmpObj.bmWidth <= 0 || bmpObj.bmHeight <= 0 ) { return FALSE; } // 创建DIB内存DC HDC hDIBDC = ::CreateCompatibleDC(NULL); if (hDIBDC == NULL) { return FALSE; } // 创建DIB兼容位图 BITMAPINFO hdr; ZeroMemory(&hdr , sizeof(BITMAPINFO)); hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); hdr.bmiHeader.biWidth = bmpObj.bmWidth; hdr.bmiHeader.biHeight = -bmpObj.bmHeight; // 这里的目的是直接按正常行顺序使用数据 hdr.bmiHeader.biPlanes = 1; hdr.bmiHeader.biBitCount = 32; BYTE * pbtPixels = NULL; HBITMAP hDIBitmap = ::CreateDIBSection(hDIBDC, (BITMAPINFO *)&hdr, DIB_RGB_COLORS, (void **)&pbtPixels, NULL, 0); if (hDIBitmap == NULL) { ::DeleteDC(hDIBDC); return FALSE; } // 把DIB位图选入DIB内存DC HBITMAP hOldDIBBmp = (HBITMAP)::SelectObject(hDIBDC, hDIBitmap); // 把HBITMAP绘制到DIB内存DC上 if (DrawHBitmapToDC(hBitmap, hDIBDC) == FALSE) { ::SelectObject(hDIBDC, hOldDIBBmp); ::DeleteDC(hDIBDC); ::DeleteObject(hDIBitmap); return FALSE; } // 从pbtPixels中取得位图数据存放到bitmapBits中 // 申请存放数据内存 bitmapBits.m_pBitsBuf = new BYTE[bmpObj.bmWidth*bmpObj.bmHeight*3]; if (bitmapBits.m_pBitsBuf == NULL) { ::SelectObject(hDIBDC, hOldDIBBmp); ::DeleteDC(hDIBDC); ::DeleteObject(hDIBitmap); return FALSE; } // 记录图片宽度高度 bitmapBits.m_dwWidth = bmpObj.bmWidth; bitmapBits.m_dwHeight = bmpObj.bmHeight; // 行优先遍历取得每点RGB数据 long lSrcRowStartPos = 0; long lSrcPos = 0; long lDstRowStartPos = 0; long lDstPos = 0; for (long lRowIndex=0; lRowIndex<bmpObj.bmHeight; lRowIndex++) { // 计算行首位置 lSrcRowStartPos = lRowIndex * bmpObj.bmWidth * 4; lDstRowStartPos = lRowIndex * bmpObj.bmWidth * 3; // 遍历每一列 for (long lColumnIndex=0; lColumnIndex<bmpObj.bmWidth; lColumnIndex++) { // 计算当前像素点的起始位置,以及目标存放位置 lSrcPos = lSrcRowStartPos + lColumnIndex*4; lDstPos = lDstRowStartPos + lColumnIndex*3; // 源中应该是BGRA的4字节顺序,这里转存为RGB数据 bitmapBits.m_pBitsBuf[lDstPos] = pbtPixels[lSrcPos+2]; bitmapBits.m_pBitsBuf[lDstPos+1] = pbtPixels[lSrcPos+1]; bitmapBits.m_pBitsBuf[lDstPos+2] = pbtPixels[lSrcPos]; } } // 释放DIB内存DC及位图 ::SelectObject(hDIBDC, hOldDIBBmp); ::DeleteDC(hDIBDC); ::DeleteObject(hDIBitmap); // 取得数据成功 return TRUE; }