C ++:将Hbitmap / BITMAP转换为.bmp文件 [英] C++: Hbitmap/BITMAP into .bmp file

查看:283
本文介绍了C ++:将Hbitmap / BITMAP转换为.bmp文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,整个故事是,我试图使用Leptonica + Tesseract OCR在C + +截取屏幕截图,保存到一个* .bmp文件,然后加载它回到OCR与它。我不需要经常这样做,但由于我似乎不能将截图数据直接复制到Leptonica PIX结构,我需要先将它保存到一个文件。实际上,这个解决方案最好。

Ok, whole story is, I am trying to use Leptonica+Tesseract OCR in C++ to take a screenshot, save it to a *.bmp file, then load it back up to OCR with it. I won't need to do this frequently, but as I cannot seem to copy the screenshot data directly into a Leptonica PIX structure, I need to save it to a file first..actually a solution to this would be preferably.

这里有一些我在网上找到的代码,试图帮助我。

Here's some code I've found online, trying to help me out.

屏幕截图:

HBITMAP ScreenCapture(){
  int width=100;
  int height=100;
  // get the device context of the screen
  HDC hScreenDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);     
  // and a device context to put it in
  HDC hMemoryDC = CreateCompatibleDC(hScreenDC);

  int x = GetDeviceCaps(hScreenDC, HORZRES);
  int y = GetDeviceCaps(hScreenDC, VERTRES);

  // maybe worth checking these are positive values
  HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, x, y);

  // get a new bitmap
  HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);

  BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY);
  hBitmap = (HBITMAP)SelectObject(hMemoryDC, hOldBitmap);

  //GlobalAlloc(GPTR, hBitmap)

  WriteDIB(L"test.bmp", (HGLOBAL)hBitmap);

  // clean up
  DeleteDC(hMemoryDC);
  DeleteDC(hScreenDC);

  return hBitmap;
  // now your image is held in hBitmap. You can save it or do whatever with it
}

尝试写函数: p>

Attempt to write function:

BOOL WriteDIB( LPTSTR szFile, HANDLE hDIB)
{
  cout<<endl<<"Running save function";
  /*HANDLE hDIB=GlobalAlloc(GPTR, sizeof(hDIBtochange));//this doesn't work, the result is four. Also the HANDLE parameter's name would be changed to hDIBtochange, so that the rest of the function uses the old 'hDIB' throughout
  cout<<endl<<sizeof(hDIBtochange);*/
  BITMAPFILEHEADER  hdr;
  LPBITMAPINFOHEADER    lpbi;
  if (!hDIB)
    return FALSE;
  CFile file;
  if( !file.Open( szFile, CFile::modeWrite|CFile::modeCreate) )
    return FALSE;
  lpbi = (LPBITMAPINFOHEADER)hDIB;
  int nColors = 1 << lpbi->biBitCount;
  // Fill in the fields of the file header 
  hdr.bfType        = ((WORD) ('M' << 8) | 'B');    // is always "BM"
  hdr.bfSize        = GlobalSize (hDIB) + sizeof( hdr );
  hdr.bfReserved1   = 0;
  hdr.bfReserved2   = 0;
  hdr.bfOffBits     = (DWORD) (sizeof( hdr ) + lpbi->biSize + nColors * sizeof(RGBQUAD));
  // Write the file header 
  file.Write( &hdr, sizeof(hdr) );
  // Write the DIB header and the bits 
  file.Write( lpbi, GlobalSize(hDIB) );
  return TRUE;
}

多年来无耻地从人们的帖子中复制。
好​​!问题我面对的是,我似乎不能理解如何GlobalInloc的Hbitmap到一个全局可访问句柄,可以转换或使用LPBITMAPINFOHEADER。
在创建lpbi时,Visual Studio 2012调试中的每个字段都是无法读取内存错误。

Shamelessly copied from people's posts over the years. Ok! Problem I face is, I cannot seem to understand how to GlobalAlloc the Hbitmap into a globally accessible Handle, that can be converted or use with LPBITMAPINFOHEADER. Soon as lpbi is created, every single field inside of it is "Unable to read memory" error in Visual Studio 2012 debugging. It's inaccessible, despite being created.

解决方案..
直接从screencap到内存中的PIX。
找到一种保存方法到位图,并定期创建它们阅读..
完全找到另一种方式更有意义。

Solutions.. Go straight from screencap to PIX, inside of memory.. Find a way to save to bitmap and create them periodically to read.. Find another way entirely that makes more sense..

首先,首先,

如果您需要更多信息,我可以尝试提供它。这主要归结为我从来没有像这样的代码,它没有在我的课程中教,所以我试图学习,因为我去。

If you need more info I can try to provide it. This mostly boils down to "I've never done code like this before and it wasn't taught in my classes so I'm trying to learn as I go".

推荐答案

一个更简单的方法来保存HBITMAP文件是使用GDI +。
这让你能够保存为任何格式的窗口支持本机,同时释放你从玩弄或甚至需要了解,各种图像格式的污垢的优势。

A much easier way to save an HBITMAP to file is to make use of GDI+. This gives you the advantage of being able to save to any format that windows supports natively, while freeing you from the muck of playing around with or even needing to understand, various image formats.

在下面的例子中,我只是使用LoadImage作为加载一个预先存在的图像的quik和脏的方式 - 你可以简单地使用你已经捕获的HBITMAP。

In the below example, I've just used LoadImage as a quik and dirty way of loading a pre-existing image - you could simply use the HBITMAP you've already captured.

下面是一个加载位图并再次保存的示例。 (我最初使用image / png作为输出类型,以及适当的输出文件名)

Here's an example that loads a bitmap and saves it again. (I had initially used "image/png" as the output type, along with an appropriate output filename)

#include <windows.h>
#include <gdiplus.h>
using namespace Gdiplus;

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
   UINT  num = 0;          // number of image encoders
   UINT  size = 0;         // size of the image encoder array in bytes

   ImageCodecInfo* pImageCodecInfo = NULL;

   GetImageEncodersSize(&num, &size);
   if(size == 0)
      return -1;  // Failure

   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
   if(pImageCodecInfo == NULL)
      return -1;  // Failure

   GetImageEncoders(num, size, pImageCodecInfo);

   for(UINT j = 0; j < num; ++j)
   {
      if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
      {
         *pClsid = pImageCodecInfo[j].Clsid;
         free(pImageCodecInfo);
         return j;  // Success
      }
   }
   free(pImageCodecInfo);
   return -1;  // Failure
}

int main()
{
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    HBITMAP hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), "babe.bmp", IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);
    Bitmap *image = new Bitmap(hBitmap, NULL);

    CLSID myClsId;
    int retVal = GetEncoderClsid(L"image/bmp", &myClsId);

    image->Save(L"output.bmp", &myClsId, NULL);
    delete image;

    GdiplusShutdown(gdiplusToken);
    return 0;
}

这篇关于C ++:将Hbitmap / BITMAP转换为.bmp文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆