我正在拍摄一个窗口的屏幕截图,以便使用Leptonica
进行处理,然后使用Tesseract
进行一些OCR
问题是,性能方面我希望避免将BMP写入和读取光盘而只是在内存中工作。这是我制作屏幕截图的方式:
int width, height = 0;
HDC hdcWindow;
HDC hdcMemDC = NULL;
HBITMAP hbmScreen = NULL;
BITMAP bmpScreen;
// Retrieve the handle to a display device context for the client
// area of the window.
//hdcScreen = GetDC(NULL);
//hdcWindow = GetDC(hWnd);
hdcWindow = GetDC(hWnd);
// Create a compatible DC which is used in a BitBlt from the window DC
hdcMemDC = CreateCompatibleDC(hdcWindow);
if (!hdcMemDC)
{
MessageBox(hWnd, L"CreateCompatibleDC has failed", L"Failed", MB_OK);
goto done;
}
// Get the client area for size calculation
RECT rcClient;
GetClientRect(hWnd, &rcClient);
// Create a compatible bitmap from the Window DC
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
if (!hbmScreen)
{
MessageBox(hWnd, L"CreateCompatibleBitmap Failed", L"Failed", MB_OK);
goto done;
}
// Select the compatible bitmap into the compatible memory DC.
SelectObject(hdcMemDC, hbmScreen);
// Bit block transfer into our compatible memory DC.
if (!BitBlt(hdcMemDC,
0, 0,
rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
hdcWindow,
0, 0,
SRCCOPY))
{
MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
goto done;
}
// Get the BITMAP from the HBITMAP
GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
// Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that
// call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc
// have greater overhead than HeapAlloc.
HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
char *lpbitmap = (char *)GlobalLock(hDIB);
// Gets the "bits" from the bitmap and copies them into a buffer
// which is pointed to by lpbitmap.
GetDIBits(hdcWindow, hbmScreen, 0,
(UINT)bmpScreen.bmHeight,
lpbitmap,
(BITMAPINFO *)&bi, DIB_RGB_COLORS);
// A file is created, this is where we will save the screen capture.
HANDLE hFile = CreateFile(L"pics/UI.bmp",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
// Add the size of the headers to the size of the bitmap to get the total file size
DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
//Offset to where the actual bitmap bits start.
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
//Size of the file
bmfHeader.bfSize = dwSizeofDIB;
//bfType must always be BM for Bitmaps
bmfHeader.bfType = 0x4D42; //BM
DWORD dwBytesWritten = 0;
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
//Unlock and Free the DIB from the heap
GlobalUnlock(hDIB);
GlobalFree(hDIB);
//Close the handle for the file that was created
CloseHandle(hFile);
width = rcClient.right - rcClient.left;
height = rcClient.bottom - rcClient.top;
//Clean up
done:
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(hWnd, hdcWindow);
这就是我读它的方式:
PIX* pixUI = pixRead("pics/UI.bmp");
所以,我已经看到该库有PIX * pixReadMemBmp ( const l_uint8 *cdata, size_t size )
method,其中l_uint8
是unsigned char
缓冲区
问题是,我不明白如何从我的HBITMAP
或BITMAP
对象中获取这样的缓冲区。
答案 0 :(得分:1)
首先将位图复制到缓冲区,然后将此缓冲区移交给<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
<script type="text/javascript">
$(function()
{
$(".word").keyup(function()
{
var word=$(this).val();
$(".word_preview").html(word);
return false;
});
});
</script>
<script>
function myFunction() {
var str = document.getElementById("demo").innerHTML;
var res = str.replace(/[^]0/g, '<span style="color:black">').replace(/[^]1/g, '<span style="color:red">').replace(/[^]2/g, '<span style="color:green">').replace(/[^]3/g, '<span style="color:yellow">').replace(/[^]4/g, '<span style="color:blue">').replace(/[^]5/g, '<span style="color:cyan">').replace(/[^]6/g, '<span style="color:#D02090">').replace(/[^]7/g, '<span style="color:white">');
document.getElementById("demo").innerHTML = res;
};
</script>
</head>
<body>
Enter name:
<br/>
<input type="text" name="maprotation" size="50" id="textfield" class="word" class="Stil69">
<input type="reset" name="Submit3" value="Reset" />
<br/><br/>
<h3>2. Click the button to preview your colored name.</h3>
<br/>
<input type="button" onclick="myFunction()" value="Click here"/>
<br/><br/>
<table bgcolor="#333333"><tr><td><span class="word_preview" id="demo"><td></span></tr></table>
<br/>
</body>
</html>
。必须完成复制,因为我认为,pixReadMemBmp()
函数需要位图数据前面的两个位图标题,就像它在文件中一样。伪代码:
pixReadMemBmp()