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

来源:互联网 发布:手机最好用防蹭网软件 编辑:程序博客网 时间:2024/06/06 19:12

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


1.GetDIBits使用方法

函数定义如下
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. int GetDIBits(  
  2.   HDC hdc,           // handle to DC  
  3.   HBITMAP hbmp,      // handle to bitmap  
  4.   UINT uStartScan,   // first scan line to set  
  5.   UINT cScanLines,   // number of scan lines to copy  
  6.   LPVOID lpvBits,    // array for bitmap bits  
  7.   LPBITMAPINFO lpbi, // bitmap data buffer  
  8.   UINT uUsage        // RGB or palette index  
  9. );  

这个函数获得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的实例代码,建议下载完整源代码查看

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. BOOL CScreenBitmap::ExportToFile(CDC *pDC, TCHAR *szBmpName,  RECT *pRect/*=NULL*/)  
  2. {  
  3.     HBITMAP hExportBmp;  
  4.     BITMAPFILEHEADER bmfh={0};  
  5.   
  6.     /************************************************************************/  
  7.     /* 获得数据                                                                     */  
  8.     /************************************************************************/  
  9.   
  10.     //获得要导出的DDB位图  
  11.     hExportBmp = CopyBitmap(pRect);  
  12.   
  13.     //获得DDB信息  
  14.     BITMAPINFOHEADER bmih={0};  
  15.     bmih.biSize = sizeof(BITMAPINFOHEADER);  
  16.     bmih.biBitCount = 0;  
  17.     if (0 == GetDIBits(pDC->GetSafeHdc(),   
  18.                        hExportBmp,   
  19.                        0, 0,   
  20.                        NULL, (BITMAPINFO *)&bmih,   
  21.                        DIB_RGB_COLORS))  
  22.     {  
  23.         return FALSE;  
  24.     }  
  25.       
  26.     //删除已经分配的存储区  
  27.     if (NULL != m_pbmi)  
  28.     {  
  29.         free(m_pbmi);  
  30.         m_pbmi = NULL;  
  31.     }  
  32.   
  33.     if (NULL != m_pBits)  
  34.     {  
  35.         free(m_pBits);  
  36.         m_pBits = NULL;  
  37.     }  
  38.   
  39.     //分配新的存储区  
  40.     DWORD dwInfoSize;  
  41.     DWORD dwBitsSize;  
  42.   
  43.     if (bmih.biBitCount>=16 && BI_BITFIELDS==bmih.biCompression)  
  44.     {  
  45.         dwInfoSize = sizeof(BITMAPINFOHEADER) + 4*4;//字节对齐,RGBQUAD每个成员存储的内存大小为4字节  
  46.   
  47.         TRACE("%d %d %d\n"sizeof(BITMAPINFO), sizeof(BITMAPINFOHEADER), sizeof(RGBQUAD));  
  48.     }  
  49.     else if (bmih.biBitCount>=16)  
  50.     {  
  51.         dwInfoSize = sizeof(BITMAPINFOHEADER);  
  52.     }  
  53.     else  
  54.     {  
  55.         dwInfoSize = sizeof(BITMAPINFOHEADER) + 4*4*bmih.biClrUsed;//字节对齐,RGBQUAD每个成员存储的内存大小为4字节  
  56.     }  
  57.     dwBitsSize = bmih.biHeight *   
  58.                  (((bmih.biBitCount*bmih.biPlanes*bmih.biWidth + 31) & ~31) >> 3);  
  59.   
  60.     //分配对应的内存区  
  61.     m_pbmi = (PBITMAPINFO)malloc(dwInfoSize);  
  62.     if (NULL == m_pbmi)  
  63.     {  
  64.         return FALSE;  
  65.     }  
  66.   
  67.     m_pBits = (PBYTE)malloc(dwBitsSize);  
  68.     if (NULL == m_pBits)  
  69.     {  
  70.         free(m_pbmi);  
  71.         return FALSE;  
  72.     }  
  73.   
  74.     //读入位图信息和位图数据  
  75.     CopyMemory(m_pbmi, &bmih, sizeof(BITMAPINFOHEADER));  
  76.     if (0 == GetDIBits( pDC->GetSafeHdc(),   
  77.                         hExportBmp,   
  78.                         0, bmih.biHeight,   
  79.                         m_pBits, m_pbmi,   
  80.                         DIB_RGB_COLORS))  
  81.     {  
  82.         free(m_pBits);  
  83.         free(m_pbmi);  
  84.         return FALSE;  
  85.     }  
  86.   
  87.     /************************************************************************/  
  88.     /* 保存数据                                                                     */  
  89.     /************************************************************************/  
  90.   
  91.     //计算文件头信息  
  92.     bmfh.bfType = *(WORD *)"BM";  
  93.     bmfh.bfSize = sizeof(BITMAPFILEHEADER) + dwInfoSize + dwBitsSize;  
  94.     bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + dwInfoSize;  
  95.   
  96.     //写入到对应BMP文件中  
  97.     HANDLE hFile = CreateFile(  szBmpName,  
  98.                                 GENERIC_WRITE, 0,  
  99.                                 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);  
  100.   
  101.     CFile m_saveFile(hFile);  
  102.   
  103.     m_saveFile.Write(&bmfh, sizeof(BITMAPFILEHEADER));  
  104.     m_saveFile.Write(m_pbmi, dwInfoSize);  
  105.     m_saveFile.Write(m_pBits, dwBitsSize);  
  106.   
  107.     m_saveFile.Close();  
  108.   
  109.     ::DeleteObject(hExportBmp);  
  110.   
  111.     return TRUE;  
  112. }  


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