Windows DIB文件操作详解-3.DDB转DIB

来源:互联网 发布:网线端口显示红灯 编辑:程序博客网 时间:2024/05/22 14:13

上一节讲到DIB转换成DDB以提高位图显示性能,那么这里自然想到DDB转DIB。DDB转DIB有什么用呢?最常见的应用场合就是你得到了一个屏幕截图的DDB,现在想把它保存到磁盘上,这时候就要用到DDB转DIB函数GetDIBits。


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

这个函数获得hbmp的位图信息和数据填充到提前分配好的lpvBits和lpbi指针指向的内存中,完成DDB到DIB转换。

这个函数的使用步骤如下
1.定义BITMAPINFOHEADER bmih结构,设置结构的size,设置bitcount为0。lpvBits参数设为NULL而lpbi参数设为&bmih,如此调用GetDIBits函数,此函数会将hbmp的相关信息(大小、深度等信息)填充到bmih结构。
2.按照步骤1得到的信息分配lpbi和lpvBits结构内存。原则上当lpvBits结构lpvBits不为NULL时,lpbi的前6个参数必须设置,这里直接将bmih内容复制给lpbi。
3.传入分配好的lpbi和lpvBits结构内存地址,调用GetDIBits函数得到位图信息和数据。

一定要注意这里的lpvBits和lpbi内存是自己在调用函数前分配的。

2.屏幕截图保存到文件

这里贴上一个笔者写的截图软件中的屏幕截图DDB转DIB的实例代码,建议下载完整源代码查看

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


最新完整截图软件源代码下载链接,这里CScreenBitmap类中是封装好的截图操作,包括屏幕指定区域截图、复制截图到剪切板上及截图保存到磁盘上,你可以在自己的项目中直接使用它。
原创,转载请注明来自http://blog.csdn.net/wenzhou1219
0 0