上一节讲到DIB转换成DDB以提高位图显示性能,那么这里自然想到DDB转DIB。DDB转DIB有什么用呢?最常见的应用场合就是你得到了一个屏幕截图的DDB,现在想把它保存到磁盘上,这时候就要用到DDB转DIB函数GetDIBits。
int GetDIBits( HDC hdc, // handle to DC HBITMAP hbmp, // handle to bitmap UINT uStartScan, // first scan line to set UINT cScanLines, // number of scan lines to copy LPVOID lpvBits, // array for bitmap bits LPBITMAPINFO lpbi, // bitmap data buffer UINT uUsage // RGB or palette index );
BOOL CScreenBitmap::ExportToFile(CDC *pDC, TCHAR *szBmpName, RECT *pRect/*=NULL*/) { HBITMAP hExportBmp; BITMAPFILEHEADER bmfh={0}; /************************************************************************/ /* 获得数据 */ /************************************************************************/ //获得要导出的DDB位图 hExportBmp = CopyBitmap(pRect); //获得DDB信息 BITMAPINFOHEADER bmih={0}; bmih.biSize = sizeof(BITMAPINFOHEADER); bmih.biBitCount = 0; if (0 == GetDIBits(pDC->GetSafeHdc(), hExportBmp, 0, 0, NULL, (BITMAPINFO *)&bmih, DIB_RGB_COLORS)) { return FALSE; } //删除已经分配的存储区 if (NULL != m_pbmi) { free(m_pbmi); m_pbmi = NULL; } if (NULL != m_pBits) { free(m_pBits); m_pBits = NULL; } //分配新的存储区 DWORD dwInfoSize; DWORD dwBitsSize; if (bmih.biBitCount>=16 && BI_BITFIELDS==bmih.biCompression) { dwInfoSize = sizeof(BITMAPINFOHEADER) + 4*4;//字节对齐,RGBQUAD每个成员存储的内存大小为4字节 TRACE("%d %d %d\n", sizeof(BITMAPINFO), sizeof(BITMAPINFOHEADER), sizeof(RGBQUAD)); } else if (bmih.biBitCount>=16) { dwInfoSize = sizeof(BITMAPINFOHEADER); } else { dwInfoSize = sizeof(BITMAPINFOHEADER) + 4*4*bmih.biClrUsed;//字节对齐,RGBQUAD每个成员存储的内存大小为4字节 } dwBitsSize = bmih.biHeight * (((bmih.biBitCount*bmih.biPlanes*bmih.biWidth + 31) & ~31) >> 3); //分配对应的内存区 m_pbmi = (PBITMAPINFO)malloc(dwInfoSize); if (NULL == m_pbmi) { return FALSE; } m_pBits = (PBYTE)malloc(dwBitsSize); if (NULL == m_pBits) { free(m_pbmi); return FALSE; } //读入位图信息和位图数据 CopyMemory(m_pbmi, &bmih, sizeof(BITMAPINFOHEADER)); if (0 == GetDIBits( pDC->GetSafeHdc(), hExportBmp, 0, bmih.biHeight, m_pBits, m_pbmi, DIB_RGB_COLORS)) { free(m_pBits); free(m_pbmi); return FALSE; } /************************************************************************/ /* 保存数据 */ /************************************************************************/ //计算文件头信息 bmfh.bfType = *(WORD *)"BM"; bmfh.bfSize = sizeof(BITMAPFILEHEADER) + dwInfoSize + dwBitsSize; bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + dwInfoSize; //写入到对应BMP文件中 HANDLE hFile = CreateFile( szBmpName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); CFile m_saveFile(hFile); m_saveFile.Write(&bmfh, sizeof(BITMAPFILEHEADER)); m_saveFile.Write(m_pbmi, dwInfoSize); m_saveFile.Write(m_pBits, dwBitsSize); m_saveFile.Close(); ::DeleteObject(hExportBmp); return TRUE; }