您的位置:首页 > 编程语言 > C语言/C++

VC/MFC怎样将位图CBitmap对象保存成为bmp格式文件?(你在网上找的不一定灵,看我的一定灵)

2014-06-03 10:01 405 查看


VC/MFC怎样将位图CBitmap对象保存成为bmp格式文件?

 

虽然说现在写程序主要依靠 Internet ,特别是 Google 搜索(不过有时候 被墙,只能凑合着用百度)。编程技术人员的普遍经验都是:Google 在搜索技术资料的时候确实比 百度 要强。

 

废话少说,今晚找了些资料,终于搞定了 将CBitmap表示的位图对象保存成为正宗的 bmp 格式文件。不过其中有些小的曲折,总结一下,网上大体提供了以下几种方式:

 

1. 用 CImage 来解决,就几行,但需要 .net 支持;

Cpp代码  


// http://blog.csdn.net/benpluslib/article/details/3975774  

// 使用下面的代码,可以把CBitmap类中的图像保存到图像文件中。支持格式:BMP、JPG、GIF和PNG。   

// 但CImage只在.net下有  

// CImage imgTemp;      // CImage是MFC中的类。  

// imgTemp.Attach(Bitmap.operator HBITMAP());  

// imgTemp.Save(strFilePath);  

 

2. 很多网站提供的 void WriteBmp(CBitmap   *PBitmap, char m_FileName[])  原代码,要放在 某个 Windows 类中作为成员函数才行。但很不幸,不怎么灵。

Cpp代码  


// http://blog.csdn.net/xs813/article/details/6321924  

// 保存CBitmap到文件   

// 经过测试,这个方法是不灵的:  

// 有时候能正确保存,  

// 有时候保存之后打开报“绘图失败”,  

// 有时候程序执行非法操作  

void CTestClipboardDlg::WriteBmp(CBitmap   *PBitmap, char m_FileName[])     

// 代码省略,网上有(既然不灵,也就没必要贴出来了)  

  

// 调用方式  

                //WriteBmp(cbm, "clipboard1.bmp");  // 这个方法不行  

 

3. 也还有 bool SaveBitmapToFile(CBitmap* bitmap, LPSTR lpFileName) 此方法甚好,就用它了。下面贴出完整的经本人辛苦格式化的代码,再此向作者致敬(虽然原作者已无从考证)。

Cpp代码  


// http://blog.sina.com.cn/s/blog_6ee382440100moeu.html  

// http://apps.hi.baidu.com/share/detail/32878068  

// bitmap 位图CBitmap对象指针  

// lpFileName 为位图文件名    

bool SaveBitmapToFile(CBitmap* bitmap, LPSTR lpFileName)  

{              

    HBITMAP hBitmap;    // 为刚才的屏幕位图句柄  

    HDC hDC; //设备描述表    

    int iBits; //当前显示分辨率下每个像素所占字节数    

    WORD wBitCount; //位图中每个像素所占字节数    

    DWORD dwPaletteSize = 0, //定义调色板大小  

        dwBmBitsSize,  //位图中像素字节大小     

        dwDIBSize,   //位图文件大小  

        dwWritten;  //写入文件字节数  

    BITMAP Bitmap; //位图属性结构    

    BITMAPFILEHEADER bmfHdr; //位图文件头结构    

    BITMAPINFOHEADER bi; //位图信息头结构      

    LPBITMAPINFOHEADER lpbi; //指向位图信息头结构    

    HANDLE fh,   //定义文件  

        hDib,    //分配内存句柄  

        hPal,   //调色板句柄  

        hOldPal = NULL;  

      

    //计算位图文件每个像素所占字节数    

    hBitmap = (HBITMAP)*bitmap;    

    hDC = CreateDC("DISPLAY",NULL,NULL,NULL);    

    iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);    

    DeleteDC(hDC);  

      

    if (iBits <= 1)    

        wBitCount = 1;    

    else if (iBits <= 4)    

        wBitCount = 4;    

    else if (iBits <= 8)    

        wBitCount = 8;    

    else if (iBits <= 24)    

        wBitCount = 24;    

    else if (iBits <= 32)  

        wBitCount = 32;  

      

    //计算调色板大小    

    if (wBitCount <= 8)    

        dwPaletteSize = (1 << wBitCount) * sizeof (RGBQUAD);  

      

    //设置位图信息头结构    

    GetObject(hBitmap, sizeof (BITMAP), (LPSTR)&Bitmap);  

    bi.biSize = sizeof (BITMAPINFOHEADER);    

    bi.biWidth = Bitmap.bmWidth;    

    bi.biHeight = Bitmap.bmHeight;    

    bi.biPlanes = 1;      

    bi.biBitCount = wBitCount;    

    bi.biCompression = BI_RGB;    

    bi.biSizeImage = 0;    

    bi.biXPelsPerMeter = 0;    

    bi.biYPelsPerMeter = 0;    

    bi.biClrUsed = 0;    

    bi.biClrImportant = 0;    

      

    dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31) / 32) * 4 * Bitmap.bmHeight;    

      

    //为位图内容分配内存    

    hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof (BITMAPINFOHEADER));    

    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);    

    *lpbi = bi;  

      

    // 处理调色板         

    hPal = GetStockObject(DEFAULT_PALETTE);    

    if (hPal)    

    {    

        hDC = ::GetDC(NULL);      

        hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);    

        RealizePalette(hDC);  

    }    

      

    //   获取该调色板下新的像素值    

    GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,    

        (LPSTR)lpbi + sizeof (BITMAPINFOHEADER) + dwPaletteSize,  

        (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);    

      

    //恢复调色板       

    if (hOldPal)      

    {    

        SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);    

        RealizePalette(hDC);    

        ::ReleaseDC(NULL, hDC);  

    }    

      

    //创建位图文件              

    fh = CreateFile(lpFileName, GENERIC_WRITE,  

        0, NULL, CREATE_ALWAYS,  

        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);    

      

    if (fh == INVALID_HANDLE_VALUE)  

        return FALSE;    

      

    //   设置位图文件头    

    bmfHdr.bfType = 0x4D42;     //   "BM"    

    dwDIBSize = sizeof (BITMAPFILEHEADER)       

        + sizeof (BITMAPINFOHEADER)    

        + dwPaletteSize + dwBmBitsSize;      

    bmfHdr.bfSize = dwDIBSize;    

    bmfHdr.bfReserved1 = 0;    

    bmfHdr.bfReserved2 = 0;    

    bmfHdr.bfOffBits = (DWORD)sizeof (BITMAPFILEHEADER)     

        + (DWORD)sizeof (BITMAPINFOHEADER)    

        + dwPaletteSize;      

      

    //   写入位图文件头    

    WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);    

      

    //   写入位图文件其余内容    

    WriteFile(fh, (LPSTR)lpbi, dwDIBSize,  

        &dwWritten, NULL);  

      

    //清除            

    GlobalUnlock(hDib);    

    GlobalFree(hDib);    

    CloseHandle(fh);    

  

    return TRUE;      

}    

 

使用的方式也相当的简单。

Cpp代码  


SaveBitmapToFile(cbm, "clipboard.bmp");  

 

4. 其他第三方库:比如 CxImage ,现在还没有来得及研究。

 

下一步准备将 CBitmap 保存为 jpg 格式,或将已保存的 bmp 格式文件 转为 jpg 格式文件。

原文地址:http://coding1688.iteye.com/blog/1547035
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cpp