將HDC轉化成BMP保存(轉)

//========================================================================
//TITLE:
//    将HDC保存为BMP文件
//AUTHOR:
//    norains
//DATE:
//    Friday 25-September-2009
//Environment:
//    WINDOWS CE 5.0
//========================================================================

    HDC在MSDN中的全称为:The handle of device context。通常,我们都用来做相应的显示操作。
   
    熟悉WIN32的朋友对于其应该不会陌生,经常采用GetDC,GetWindowDC等等来获取其句柄。而用得最多的,可能就BeginPaint,如:

   使用起来非常简单,但如果想将其内容保存为普通的图像文档,可就没那么容易。确切地说,在只知道HDC句柄的情况下,我们无法保存其内容的;但我们可以剑走偏锋,将HDC的内容写到一个缓存中,然后我们再保存该缓存的内容即可。
  
   听起来很简单,却又像很复杂,不么?没关系,我们现在一步一步来。
  
  
   首先,我们需要一个HDC的句柄。如同前面所说,你可以有多种方法,比如GetDC,GetWindowDC,甚至CreateDC。反正呢,你用什么方法我不管,我只要有一个HDC的句柄就好了。
  
   有了HDC的句柄,接下来我们所需要做的,知道这HDC的大小,也就宽度和长度。这个不难,我们只要简单地调用GetDeviceCaps,然后参数给予HORZRES或VERTRES即可:
 

    为什么要知道大小呢?因为我们要用它来创建缓存。而这缓存,说白了,其实就一个BMP格式的数据结构而已。
   
    为了创建这个关键的缓存,我们必须调用CreateDIBSection函数,而该函数形参又用到BITMAPINFOHEADER,所以我们的一切,就先从填充该结构体开始。
   
    该结构体定义如下:

    结构体里面还有一个BITMAPINFOHEADER,其定义如下:

    这么多变量,有点头晕?大可不必紧张,其实我们只需要填充其中几个,其它统统置为0即可:

    一切从最简单做起,对于BMP而言,最简单的自然24位位图,这就什么biPlanes和biBitCount分别设置为1和24的原因。
   
    填充完BITMAPINFO结构,我们还不能马上调用CreateDIBSection,因为形参中还有一个HDC。虽然我们可以直接采用已知的HDC句柄,但接下来还要将创建的HBITMAP和HDC相连接,所以我们还先创建一个缓存DC:

    一切准备就绪之后,就调用CreateDIBSection吧:

    pData分配的一个内存空间,将来用来存储HDC的内容,只不过现在一切都空的。如果你将这数据保存出来,你会发现一团漆黑。
   
    将HBITMAP和HDC结合:

    至此为止,我们前期工作已经准备就绪,我们只需要将HDC的内容用BitBlt绘制到缓存中即可:

  这里其实还有一个小技巧,如果你想绘制HDC的某个区域,你只需要用StretchBlt替代即可:

    喜欢追究问题的你,也许会发现,在调用该函数之后,pData所指向的内存缓冲区已经改变。的,没错,这些改变的数据就我们所需要的。接下来我们所需要做的仅仅,将这数据按BMP文件的格式,保存下来即可。
   
    BMP文件格式其实很简单,最开始文件头信息,然后图片信息,接下来数据。我们只需要按照这格式,顺序将数据写入即可。
   
    文件头信息和图片信息,微软已经为我们定义好了相应的结构体:
   
    BMP信息:

    文件头信息:

    我们首先填充这两个结构体数值:

    接下来的事情,估计大家都轻车熟路了。创建文件,然后写入数据,保存,完毕。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是将 hBitmap 保存bmp 图片的代码: ```c void SaveBitmapToBmp(HBITMAP hBitmap, LPCWSTR filePath) { HDC hDC; int iBits; WORD wBitCount; DWORD dwPaletteSize = , dwBmBitsSize, dwDIBSize, dwWritten; BITMAP Bitmap; BITMAPFILEHEADER bmfHdr; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; HANDLE fh, hDib, hPal, hOldPal = NULL; hDC = CreateDC(L"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 wBitCount = 24; 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 = ; bi.biXPelsPerMeter = ; bi.biYPelsPerMeter = ; bi.biClrUsed = ; bi.biClrImportant = ; 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, , (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(filePath, GENERIC_WRITE, , NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (fh == INVALID_HANDLE_VALUE) return; bmfHdr.bfType = x4D42; dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; bmfHdr.bfSize = dwDIBSize; bmfHdr.bfReserved1 = ; bmfHdr.bfReserved2 = ; 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); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值