C++ 将位图转换为PIX

C++ 将位图转换为PIX,c++,leptonica,C++,Leptonica,我正在制作一个应用程序,它可以截取显示器的屏幕截图,然后用tesseract读取。 为了获得更好的性能,我希望避免在将屏幕截图发送到tesseract之前保存它 我找到了一些示例和其他相关帖子,找到了使用“pixReadMemBm”但总是返回空ptr的代码: #define _CRT_SECURE_NO_WARNINGS // for strncopy and fopen #include <stdio.h> #include <tchar.h> #include &l

我正在制作一个应用程序,它可以截取显示器的屏幕截图,然后用tesseract读取。 为了获得更好的性能,我希望避免在将屏幕截图发送到tesseract之前保存它

我找到了一些示例和其他相关帖子,找到了使用“pixReadMemBm”但总是返回空ptr的代码:

#define _CRT_SECURE_NO_WARNINGS // for strncopy and fopen

#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>


//include leptonica headers
#include <allheaders.h>

//include tesseract headers
#include <baseapi.h>

using namespace std;

TCHAR CurDir[MAX_PATH];
tesseract::TessBaseAPI *api;

void init_tesseract_ocr();
PIX* tesseract_preprocess(PIX* pixs);
string tesseract_ocr(PIX* image);
PIX* ScreenShot(int left, int top, int sizex, int sizey);

int main()
{
    GetCurrentDirectory(MAX_PATH, CurDir);
    init_tesseract_ocr();

    PIX* sc = ScreenShot(0, 0, 500, 30);
    //PIX* pp = tesseract_preprocess(sc);

    //string text = tesseract_ocr(pp);

    //cout << text << endl;

    system("pause");

    return 0;
}



PIX* ScreenShot(int left, int top, int sizex, int sizey)
{
    // get the device context of the screen
    HDC hScreenDC = CreateDC("DISPLAY", NULL, NULL, NULL);

    // and a device context to put it in
    HDC hMemoryDC = CreateCompatibleDC(hScreenDC);


    HBITMAP hBitmap;
    hBitmap = CreateCompatibleBitmap(hScreenDC, sizex, sizey);

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

    BitBlt(hMemoryDC, 0, 0, sizex, sizey, hScreenDC, left, top, SRCCOPY);

    BITMAP bmpScreen;
    GetObject(hBitmap, 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;

    HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
    char *lpbitmap = (char *)GlobalLock(hDIB);

    GetDIBits(hScreenDC, hBitmap, 0,
        (UINT)bmpScreen.bmHeight,
        lpbitmap,
        (BITMAPINFO *)&bi, DIB_RGB_COLORS);

    // 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  

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /*HANDLE hFile = CreateFile("UI.bmp",
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);

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

    //Close the handle for the file that was created
    CloseHandle(hFile);*/
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////

    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));
    PIX *mypix = pixReadMemBmp(&buffer[0], buffer.size());

    if (mypix == NULL)
    {
        cout << "mypix is NULL" << endl;
    }
    else
    {
        pixWriteImpliedFormat("preprocess.bmp", mypix, 0, 0);
    }

    DeleteDC(hMemoryDC);
    DeleteDC(hScreenDC);
    DeleteObject(hBitmap);

    GlobalUnlock(hDIB);
    GlobalFree(hDIB);

    /////////////////////////////////////

    return mypix;
}
#为strncopy和fopen定义(CRT)安全(NO)警告//
#包括
#包括
#包括
#包括
#包括
#包括
//包括细锥虫头
#包括
//包括tesseract标头
#包括
使用名称空间std;
TCHAR CurDir[MAX_PATH];
tesseract::TessBaseAPI*api;
void init_tesseract_ocr();
PIX*tesseract_预处理(PIX*pixs);
字符串tesseract_ocr(PIX*图像);
PIX*屏幕截图(左整数、上整数、大小整数、大小整数);
int main()
{
GetCurrentDirectory(最大路径,CurDir);
init_tesseract_ocr();
PIX*sc=屏幕截图(0,0500,30);
//PIX*pp=预处理(sc);
//字符串文本=tesseract_ocr(pp);

//如果您将“pixmap”保存到文件
preprocess.bmp
,并且图像文件很好,那么您就知道拷贝到内存工作正常(因为这就是保存到文件中的内容)。因此问题可能不是您认为它在哪里,而是如何传递内存中的图像?它总是属于“If(mypix==null)”所以我不明白复制到内存是如何工作的?那么你也不会向文件中写入任何内容,这意味着你说“如果我将屏幕截图保存到文件中,我会得到预期的结果”是误导性的。或者当你这么说的时候,你是指使用
pixWriteImpliedFormat
写入文件的其他内容吗?请编辑你的问题,以澄清细节并详细说明。另外,请花一些时间阅读,以及。很抱歉,我应该说,用于将文件写入磁盘的代码仅在上面是创建缓冲区的行。它确实创建了一个具有预期屏幕截图的文件。我没有尝试pixwriteimpliedformat,但它显然无法工作,因为pix指针为空。因此问题在于如何创建缓冲区,“pixreadmembmp”之前的4行
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));
PIX *mypix = pixReadMemBmp(&buffer[0], buffer.size());