2016-05-13 13 views
0

ich einen Screenshot von einem Fenster, um Proccess es mit Leptonica zu nehmen und später mit TesseractKonvertieren eines Windows Bitmap zu einem PIX (unsigned char buffer)

einige OCR tun Das Problem ist, Leistung klug würde ich mag es, das BMP nicht auf die CD zu schreiben und zu lesen, sondern einfach im Speicher zu arbeiten. Dies ist, wie ich den Screenshot machen:

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); 

Und das ist, wie ich es gelesen:

PIX* pixUI = pixRead("pics/UI.bmp"); 

Also, ich habe gesehen, dass die Bibliothek ein PIX * pixReadMemBmp (const l_uint8 *cdata, size_t size)method hat, die ein l_uint8 nimmt, welches eine unsigned char Puffer

Das Problem ist, ich verstehe nicht, wie ich einen solchen Puffer von meinem HBITMAP oder BITMAP Objekt bekommen kann.

Antwort

1

Kopieren Sie die Bitmap zuerst in einen Puffer und übergeben Sie diesen Puffer dann an pixReadMemBmp(). Das Kopieren muss getan werden, weil, wie ich annahm, die pixReadMemBmp() Funktion die beiden Bitmap-Header vor den Bitmap-Daten benötigt, so wie es in einer Datei wäre. Pseudocode:

std::vector<unsigned char> buffer(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmpSize); 
std::copy(reinterpret_cast<unsigned char*>(&bmfHeader), reinterpret_cast<unsigned char*>(&bmfHeader) + sizeof(BITMAPFILEHEADER), buffer.begin()); 
std::copy(reinterpret_cast<unsigned char*>(&bi), reinterpret_cast<unsigned char*>(&bi) + sizeof(BITMAPINFOHEADER), buffer.begin() + sizeof(BITMAPFILEHEADER)); 
std::copy(lpbitmap, lpbitmap + dwBmpSize, buffer.begin() + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); 
pixReadMemBmp(&buffer[0], buffer.size());