使用CBitmap对象保存和绘制图片

CBitmap是位图类,它封装了Windows GDI中的位图,并提供了一些操作位图的函数。使用CBitmap对象前要先进行初始化,常用的初始化函数有LoadBitmap、LoadOEMBitmap、CreateBitmap、CreateCompatibleBitmap等。

LoadBitmap()是加载一张bmp图片来初始化位图对象,函数参数为图片名称或图片资源ID。 

LoadOEMBitmap()是加载一个预定义的Windows位图来初始化位图对象。 

CreateBitmap()用一个指定宽度、高度和位图模式的依赖于设备的内存位图初始化位图对象。

CreateCompatibleBitmap()初始化位图对象并使之与指定设备兼容。

GetBitmap()可以获得位图的一些信息,如图片大小,颜色格式等,它将这些信息填充到一个BITMAP结构中。

下面是使用CBitmap类完成不同功能的三个示例:

1、在窗口上显示一张bmp图片

在窗口上显示bmp图片的一种方法:先调用成员函数LoadBitmap()初始化位图对象,然后将位图对象选入到与当前窗口DC兼容的一个DC中,再利用Bitbit()函数将兼容DC中位图绘制到当前窗口DC中。

void CtestDlg::OnPaint()
{
    CPaintDC dc(this);

    //创建位图对象并加载图片进行初始化
    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP1);//参数为图片资源的ID或名称

    //获得图片大小等信息
    BITMAP bp;
    bitmap.GetBitmap(&bp);

    //创建与当前DC兼容的DC
    CDC dcCompatible;
    dcCompatible.CreateCompatibleDC(&dc);

    //将位图选入到兼容DC中
    CBitmap* pOldBitmap = dcCompatible.SelectObject(&bitmap);

    //将兼容DC中位图绘制到当前DC中
    dc.BitBlt(100, 100, bp.bmWidth, bp.bmHeight, &dcCompatible, 0, 0, SRCCOPY);

    dcCompatible.SelectObject(pOldBitmap);
    dcCompatible.DeleteDC();
}
View Code

2、保存窗口上的指定区域内容到位图对象 / 将位图对象上的内容显示到窗口上

/************************************************************************/
/* 保存窗口上指定区域的内容到位图对象                                           */
/************************************************************************/
void CFangDaDlg::ScreenShot()
{
    CPaintDC dc(this);

    //创建位图对象并初始化,使之与当前DC兼容
    //CBitmap m_MemBitmap;
    m_MemBitmap.CreateCompatibleBitmap(&dc, 280, 320); 

    //创建与当前DC兼容的DC
    CDC dcCompatible; 
    dcCompatible.CreateCompatibleDC(&dc);  

    //将位图选入到兼容DC中
    CBitmap* pOldBitmap = dcCompatible.SelectObject(&m_MemBitmap);  

    //绘制窗口内容到兼容DC中,窗口内容即绘制到位图对象m_MemBitmap中
    dcCompatible.BitBlt(0, 0, 280, 320, &dc, 100, 100, SRCCOPY);

    dcCompatible.SelectObject(pOldBitmap);
    dcCompatible.DeleteDC();
}
/************************************************************************/
/*  将位图对象上的内容显示到窗口上                                      */
/************************************************************************/
void CFangDaDlg::ScreenPaint()
{
    CPaintDC dc(this);

    //获得图片大小
    BITMAP bm;            
    m_MemBitmap.GetBitmap(&bm)

        //创建与当前DC兼容的DC
        CDC dcCompatible;      
    dcCompatible.CreateCompatibleDC(&cdc);    

    //将位图选入到兼容DC中
    CBitmap *pOldBitmap=dcCompatible.SelectObject(&m_MemBitmap);   

    //将兼容DC中位图绘制到当前DC中
    dc.BitBlt(100, 100, bm.bmWidth , bm.bmHeight, &dcCompatible, 0, 0, SRCCOPY);  

    dcCompatible.SelectObject(pOldBitmap);            
    dcCompatible.DeleteDC();
    m_MemBitmap.DeleteObject();     
}
View Code

3、保存窗口上的指定区域内容到bmp文件

方法为调用CreateDIBSection()创建位图,获得指向位图数据的指针,然后将窗口指定区域的内容先绘制到位图上,然后再根据bmp文件的格式将文图数据写入到bmp文件中。

bmp文件一般包含四个部分:1为位图文件头BITMAPFILEHEADER,2为位图信息头BITMAPINFOHEADER,3为调色板Palette(如果为24位真彩色则不需要改调色板),4为位图实际数据。

以下转载自:http://www.cnblogs.com/bigbigtree/archive/2012/02/09/2343476.html

理解分辨率
我们常说的屏幕分辨率为640×480,刷新频率为70Hz,意思是说每行要扫描640个象素,一共有480行,每秒重复扫描屏幕70次。
理解调色板
有一个长宽各为200个象素,颜色数为16色的彩色图,如果每一个象素都用R、G、B三个分量表示,所以每个象素需要用3个字节。整个图象要用200×200×3,约120k字节,可不是一个小数目,如果我们使用调色板的话就能省很多。
如果图片上的每一个象素都用R、G、B三个分量表示,即我们认为这张图片的颜色数为256×256×256(俗称真彩色图),而如果只是一个16色图,也就是说这幅图中最多只有16种颜色,明显这种方法很浪费空间。
我们可以用一个表:表中的每一行记录一种颜色的R、G、B值。这样当我们表示一个象素的颜色时,只需要指出该颜色是在第几行,即该颜色在表中的索引值。举个例子,如果表的第0行为255,0,0(红色),那么当某个象素为红色时,只需要标明0即可。
让我们再来计算一下:16行可以用4位来表示,所以一个象素只需半个字节。整个图象要用200×200×0.5,约20k字节,再加上表占用的字节为3×16=48字节.整个占用的字节数约为前面的1/6,省很多吧?
这张R、G、B的表,就是我们常说的调色板(Palette),另一种叫法是颜色查找表LUT(Look Up Table),似乎更确切一些。Windows位图中便用到了调色板技术。
下面是保存整个窗口内容到bmp图片的代码:
void CtestDlg::SaveScreenToFile(LPCTSTR szFileName)
{
    //创建与当前窗口DC兼容的DC
    HDC hScrDC = ::GetDC(m_hWnd);
    HDC hMemDC = NULL;
    hMemDC = ::CreateCompatibleDC(hScrDC);

    //获得窗口大小
    CRect rect;
    GetClientRect(&rect);
    int nWidth = rect.Width();
    int nHeight = rect.Height(); 

    //位图结构信息
    BITMAPINFO bi; 
    ZeroMemory(&bi, sizeof(BITMAPINFO));
    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bi.bmiHeader.biWidth = nWidth;//
    bi.bmiHeader.biHeight = nHeight;//
    bi.bmiHeader.biPlanes = 1;//必须为1
    bi.bmiHeader.biBitCount = 24;//24位真彩色图

    //创建应用程序可以直接写入的、与设备无关的位图,指向该位图位数据值的指针保存到lpBitmapBits中
    BYTE *lpBitmapBits = NULL;
    HBITMAP bitmap = ::CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, (LPVOID*)&lpBitmapBits, NULL, 0);
    //将位图选入到兼容DC中
    HGDIOBJ oldbmp = ::SelectObject(hMemDC, bitmap);

    //将窗口上的内容绘制到兼容DC中,即绘制到位图上
    ::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, 0, 0, SRCCOPY);
    
    //位图文件头BITMAPFILEHEADER
    BITMAPFILEHEADER bh;
    ZeroMemory(&bh, sizeof(BITMAPFILEHEADER));
    bh.bfType = 0x4d42;//文件类型,必须是0x424D,即字符串“BM” 
    bh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//为从文件头到实际的位图数据的偏移字节数
    bh.bfSize = bh.bfOffBits + ((nWidth*nHeight)*3);//整个文件大小

    //创建bmp文件,根据bmp文件格式写入数据
    FILE* file = _wfopen(szFileName,L"wb");
    if(file)
    { 
        fwrite(&bh,1,sizeof(BITMAPFILEHEADER),file);//位图文件头BITMAPFILEHEADER
        fwrite(&(bi.bmiHeader),1,sizeof(BITMAPINFOHEADER),file);//位图信息头BITMAPINFOHEADER
        fwrite(lpBitmapBits,1,3 * nWidth * nHeight,file);//实际位图数据
        fclose(file);
    }

    ::SelectObject(hMemDC, oldbmp);
    ::DeleteObject(bitmap);
    ::DeleteObject(hMemDC);
    ::ReleaseDC(NULL, hScrDC);
}
View Code

4、利用CImage类保存窗口上指定区域内容到多种格式的图片 

还可以利用CImage类来进行窗口的截屏,其可以保存为多种图片格式,如jpeg、png等,使图片占用更少空间。CImage需包含头文件<atlimage.h>

以下是使用CImage类来截取整个屏幕的功能实现:

bool PrintScreen()
{
    CString strPicName(_T("screen.jpg"));

    HDC hdcScreen = ::GetDC(NULL);
    //GetDeviceCaps()获得设备描述表的信息
    int nBitPerPixel = GetDeviceCaps(hdcScreen, BITSPIXEL);//像素位数
    int nWidth = GetDeviceCaps(hdcScreen, HORZRES);//宽度(像素)
    int nHeight = GetDeviceCaps(hdcScreen, VERTRES);//高度(像素)

    CImage image;
    image.Create(nWidth, nHeight, nBitPerPixel);
    BitBlt(image.GetDC(), 0, 0, nWidth, nHeight, hdcScreen, 0, 0, SRCCOPY);
    ::ReleaseDC(NULL, hdcScreen);
    image.ReleaseDC();
    HRESULT hRes = S_FALSE;
    hRes = image.Save(strPicName, Gdiplus::ImageFormatJPEG);
    if(SUCCEEDED(hRes))
        return true;
    else
        return false;
}
View Code

  

你可能感兴趣的:(使用CBitmap对象保存和绘制图片)