CBitmapHelper.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #include "CBitmapHelper.h"
  2. #include "../pch/pch.h"
  3. CBitmapHelper::CBitmapHelper()
  4. {
  5. }
  6. CBitmapHelper::~CBitmapHelper()
  7. {
  8. }
  9. int CBitmapHelper::SaveBitmapToFile(HBITMAP hBitmap, LPCWSTR lpFileName) //hBitmap 为刚才的屏幕位图句柄
  10. {
  11. //lpFileName 为位图文件名
  12. WORD wBitCount; //位图中每个像素所占字节数
  13. //定义调色板大小,位图中像素字节大小,位图文件大小,写入文件字节数
  14. DWORD dwPaletteSize = 0, dwBmBitsSize, dwDIBSize, dwWritten;
  15. BITMAP Bitmap; //位图属性结构
  16. BITMAPFILEHEADER bmfHdr; //位图文件头结构
  17. BITMAPINFOHEADER bi; //位图信息头结构
  18. HANDLE fh; //定义文件,分配内存句柄,调色板句柄
  19. LPSTR lpbk, lpmem;
  20. wBitCount = 32;
  21. //设置位图信息头结构
  22. GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  23. bi.biSize = sizeof(BITMAPINFOHEADER);
  24. bi.biWidth = Bitmap.bmWidth;
  25. bi.biHeight = Bitmap.bmHeight; //为负,正向的位图;为正,倒向的位图
  26. bi.biPlanes = 1;
  27. bi.biBitCount = wBitCount;
  28. bi.biCompression = BI_RGB;
  29. bi.biSizeImage = 0;
  30. bi.biXPelsPerMeter = 0;
  31. bi.biYPelsPerMeter = 0;
  32. bi.biClrUsed = 0;
  33. bi.biClrImportant = 0;
  34. dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
  35. //创建位图文件
  36. fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  37. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  38. if(fh == INVALID_HANDLE_VALUE)
  39. {
  40. return FALSE;
  41. }
  42. //设置位图文件头
  43. bmfHdr.bfType = 0x4D42; // "BM"
  44. dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;
  45. bmfHdr.bfSize = dwDIBSize;
  46. bmfHdr.bfReserved1 = 0;
  47. bmfHdr.bfReserved2 = 0;
  48. bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
  49. //写入位图文件头
  50. WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
  51. //写入位图信息头
  52. WriteFile(fh, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
  53. //获取位图阵列
  54. lpmem = new char[dwBmBitsSize];
  55. lpbk = (LPSTR) new char[dwBmBitsSize];
  56. GetBitmapBits(hBitmap, dwBmBitsSize, lpmem);//正向的内存图象数据
  57. //转化为倒向数据(仅在bmHeight为正时需要)
  58. for(int i = 0; i < Bitmap.bmHeight; i++)
  59. {
  60. memcpy(lpbk + Bitmap.bmWidth * i * 4, lpmem + Bitmap.bmWidth * (Bitmap.bmHeight - i - 1) * 4, Bitmap.bmWidth * 4);
  61. }
  62. //写位图数据
  63. WriteFile(fh, lpbk, dwBmBitsSize, &dwWritten, NULL);
  64. //清除
  65. delete[]lpbk;
  66. delete[]lpmem;
  67. CloseHandle(fh);
  68. return TRUE;
  69. }
  70. HBITMAP CBitmapHelper::Scale(HBITMAP srcBitmap, int MaxWidth, int MaxHeight)
  71. {
  72. BITMAP Bitmap;
  73. GetObject(srcBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  74. int srcWidth = Bitmap.bmWidth;
  75. int srcHeight = Bitmap.bmHeight;
  76. double scaleX = (double)srcWidth / MaxWidth;
  77. double scaleY = (double)srcHeight / MaxHeight;
  78. double realScale;
  79. if(scaleX > scaleY)
  80. {
  81. realScale = scaleX;
  82. }
  83. else
  84. {
  85. realScale = scaleY;
  86. }
  87. int newWidth = (int)(srcWidth / realScale);
  88. int newHeight = (int)(srcHeight / realScale);
  89. HDC hSrcDC = ::CreateCompatibleDC(NULL);
  90. SelectObject(hSrcDC, srcBitmap);
  91. HDC hMemDC = CreateCompatibleDC(hSrcDC);
  92. //创建一个与屏幕设备描述表兼容的位图
  93. HBITMAP hNewBitmap = CreateCompatibleBitmap(hSrcDC, newWidth, newHeight);
  94. //把新位图选到内存设备描述表中
  95. HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hNewBitmap);
  96. ::StretchBlt(hMemDC, 0, 0, newWidth, newHeight, hSrcDC, 0, 0, srcWidth, srcHeight, SRCCOPY);
  97. hNewBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
  98. return hNewBitmap;
  99. }
  100. HBITMAP CBitmapHelper::CopyScreenToBitmap(LPRECT lpRect) //lpRect 代表选定区域
  101. {
  102. HDC hScrDC, hMemDC; //屏幕和内存设备描述表
  103. HBITMAP hBitmap, hOldBitmap;//位图句柄
  104. int nX, nY, nX2, nY2; //选定区域坐标
  105. int nWidth, nHeight; //位图宽度和高度
  106. int xScrn, yScrn; //屏幕宽度和高度
  107. //确保选定区域不为空矩形
  108. if(IsRectEmpty(lpRect))
  109. {
  110. return NULL;
  111. }
  112. //为屏幕创建设备描述表
  113. hScrDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
  114. //为屏幕设备描述表创建兼容的内存设备描述表
  115. hMemDC = CreateCompatibleDC(hScrDC); //或者::CreateCompatibleDC(NULL)
  116. //获得选定区域坐标
  117. nX = lpRect->left;
  118. nY = lpRect->top;
  119. nX2 = lpRect->right;
  120. nY2 = lpRect->bottom;
  121. //获得屏幕宽度和高度
  122. xScrn = GetDeviceCaps(hScrDC, HORZRES);
  123. yScrn = GetDeviceCaps(hScrDC, VERTRES);
  124. //确保选定区域是可见的
  125. if(nX < 0)
  126. {
  127. nX = 0;
  128. }
  129. if(nY < 0)
  130. {
  131. nY = 0;
  132. }
  133. if(nX2 > xScrn)
  134. {
  135. nX2 = xScrn;
  136. }
  137. if(nY2 > yScrn)
  138. {
  139. nY2 = yScrn;
  140. }
  141. nWidth = nX2 - nX;
  142. nHeight = nY2 - nY;
  143. //创建一个与屏幕设备描述表兼容的位图
  144. hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
  145. //把新位图选到内存设备描述表中
  146. hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
  147. //把屏幕设备描述表拷贝到内存设备描述表中
  148. BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);
  149. //得到屏幕位图的句柄
  150. hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
  151. //清除
  152. DeleteDC(hScrDC);
  153. DeleteDC(hMemDC);
  154. return hBitmap; //返回位图句柄
  155. }
  156. bool CBitmapHelper::OcrRect(tesseract::TessBaseAPI& tess, LPRECT lpRect, std::string& result)
  157. {
  158. HDC hScrDC, hMemDC; //屏幕和内存设备描述表
  159. HBITMAP hBitmap, hOldBitmap;//位图句柄
  160. int nX, nY, nX2, nY2; //选定区域坐标
  161. int nWidth, nHeight; //位图宽度和高度
  162. int xScrn, yScrn; //屏幕宽度和高度
  163. //确保选定区域不为空矩形
  164. if(IsRectEmpty(lpRect))
  165. {
  166. return false;
  167. }
  168. //为屏幕创建设备描述表
  169. hScrDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
  170. //为屏幕设备描述表创建兼容的内存设备描述表
  171. hMemDC = CreateCompatibleDC(hScrDC); //或者::CreateCompatibleDC(NULL)
  172. //获得选定区域坐标
  173. nX = lpRect->left;
  174. nY = lpRect->top;
  175. nX2 = lpRect->right;
  176. nY2 = lpRect->bottom;
  177. //获得屏幕宽度和高度
  178. xScrn = GetDeviceCaps(hScrDC, HORZRES);
  179. yScrn = GetDeviceCaps(hScrDC, VERTRES);
  180. //确保选定区域是可见的
  181. if(nX < 0)
  182. {
  183. nX = 0;
  184. }
  185. if(nY < 0)
  186. {
  187. nY = 0;
  188. }
  189. if(nX2 > xScrn)
  190. {
  191. nX2 = xScrn;
  192. }
  193. if(nY2 > yScrn)
  194. {
  195. nY2 = yScrn;
  196. }
  197. nWidth = nX2 - nX;
  198. nHeight = nY2 - nY;
  199. //创建一个与屏幕设备描述表兼容的位图
  200. hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
  201. //把新位图选到内存设备描述表中
  202. hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
  203. BITMAP bm;
  204. GetObject(hBitmap, sizeof(BITMAP), &bm);
  205. BITMAPINFOHEADER bi = { 0 };
  206. bi.biSize = sizeof(BITMAPINFOHEADER);
  207. bi.biWidth = bm.bmWidth;
  208. bi.biHeight = bm.bmHeight;
  209. bi.biPlanes = bm.bmPlanes;
  210. bi.biBitCount = bm.bmBitsPixel;
  211. bi.biCompression = BI_RGB;
  212. bi.biSizeImage = bm.bmHeight * bm.bmWidthBytes;
  213. //把屏幕设备描述表拷贝到内存设备描述表中
  214. BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);
  215. char* lpmem = new char[bi.biSizeImage];
  216. //正向的内存图象数据
  217. GetBitmapBits(hBitmap, bi.biSizeImage, lpmem);
  218. //清除
  219. DeleteDC(hScrDC);
  220. DeleteDC(hMemDC);
  221. //开始测试ocr
  222. tess.SetImage((const unsigned char*)lpmem, bm.bmWidth, bm.bmHeight, 4, bm.bmWidthBytes);
  223. tess.Recognize(0);
  224. const char* utf8_ret = tess.GetUTF8Text();
  225. char szRes[256] = { 0 };
  226. int j = 0;
  227. for (int i = 0; i < 255; i++)
  228. {
  229. if (utf8_ret[i] == '\32')
  230. {
  231. //如果是空格,直接忽略
  232. }
  233. else if (utf8_ret[i] == '\n')
  234. {
  235. //换行键,到了末尾了
  236. result = szRes;
  237. break;
  238. }
  239. else
  240. {
  241. szRes[j] = utf8_ret[i];
  242. j++;
  243. }
  244. }
  245. delete[] lpmem;
  246. tess.Clear();
  247. return true;
  248. }