Thanks to swagfag I made sample script below to demonstrate use of using Tesseract to ocr a file and screenshot using pixReadMemBmp / TessBaseAPISetImage. Uncomment the line with out.bmp to see output of screenshot
Code: Select all
#NoEnv ; Don't check empty variables to see if they are environment variables (significantly improves performance)
; https://www.autohotkey.com/boards/viewtopic.php?f=76&t=93120
; download to same folder
; https://github.com/tesseract-ocr/tessdata/blob/master/eng.traineddata
; https://github.com/nguyenq/tess4j/blob/master/src/main/resources/win32-x86-64/libtesseract500.dll (dont forget to Unblock)
; https://github.com/nguyenq/lept4j/blob/master/src/main/resources/win32-x86-64/liblept1820.dll (same)
; https://github.com/tesseract-ocr/test/blob/master/testing/phototest.tif
msgbox % ocr("phototest.tif") ; ocr file
msgbox % ocr() ; ocr screen
return
ocr(win_id="",x1=0,y1=0,x2="",y2="",whitelist="",bw="",v=20,leptonica=0)
{
static hAPI, header
if !hAPI
LoadLibrary("libtesseract500.dll")
, LoadLibrary("liblept1820.dll")
, hAPI := DllCall("libtesseract500\TessBaseAPICreate", "Ptr")
, DllCall("libtesseract500\TessBaseAPIInit3", "Ptr", hAPI, "AStr", A_ScriptDir, "AStr", "eng")
, VarSetCapacity(header, 54, 0)
, NumPut(0x360000, NumPut(1, NumPut(0x5FC64D42, header, "UInt"), "UInt"), "UInt") ; Bitmap file header (14 bytes)
if whitelist
DllCall("libtesseract500\TessBaseAPISetVariable", "Ptr", hAPI, "Str", "tessedit_char_whitelist", "Str", whitelist)
if (win_id<>"") && FileExist(win_id)
hPix := DllCall("liblept1820\pixRead", "AStr", win_id, "Ptr")
, DllCall("libtesseract500\TessBaseAPISetImage2", "Ptr", hAPI, "Ptr", hPix)
, str:= DllCall("libtesseract500\TessBaseAPIGetUTF8Text", "Ptr", hAPI, "AStr")
else {
if (win_id=="")
win_id:=WinExist("A")
if (x2=="")
WinGetPos,,,x2,,ahk_id %win_id%
if (y2=="")
WinGetPos,,,,y2,ahk_id %win_id%
x:=min(x1,x2), y:=min(y1,y2), w:=abs(x2-x1)+1, h:=abs(y2-y1)+1
, bh := -h ; must be -h for Tesseract
, NumPut(32, NumPut(1, NumPut(bh, NumPut(w, NumPut(40, header, 14, "uint"), "int"), "int"), "UShort"), 0, "UShort") ; bitmap info for CreateDIB (40 bytes) positive h for Capture2Text to work
, src := DllCall("user32.dll\GetDCEx", "Ptr", win_id, "Ptr", 0, "UInt", 3, "Ptr")
, dst := DllCall("CreateCompatibleDC", "Ptr", src, "Ptr")
, DIB := DllCall("CreateDIBSection", "Ptr", dst, "Ptr", &header+14, "UInt", 0, "Ptr*", pbits, "Ptr", 0, "UInt", 0, "Ptr")
, DllCall("SelectObject", "Ptr", dst, "Ptr", DIB, "Ptr")
, DllCall("BitBlt", "ptr", dst, "int", 0, "int", 0, "int", w, "int", h, "ptr", src, "int", x, "int", y, "Uint", 0xCC0020)
if (bw<>"")
{
b:=(bw>>16)&x0xFF, g:=(bw>>8)&0xFF, r:=bw&0xFF
Loop % w*h
{
Addr := pbits + A_Index*4
if (abs(r - NumGet(Addr+2, 0, "UChar"))<=v)
&& (abs(g - NumGet(Addr+1, 0, "UChar"))<=v)
&& (abs(b - NumGet(Addr+0, 0, "UChar"))<=v)
Numput(0, Addr+0, "UInt")
else Numput(0xFFFFFF, Addr+0, "UInt")
}
}
if leptonica
{
hData := DllCall("GlobalAlloc", "uint", 0x2, "uint", 54 + w*h*4, "ptr")
, pData := DllCall("GlobalLock", "ptr", hData, "ptr")
, DllCall("RtlMoveMemory", "ptr", pData + 0, "ptr", &header, "UInt", 54) ; destination, source, length
, DllCall("RtlMoveMemory", "ptr", pData + 54, "ptr", pbits, "UInt", w*h*4)
, hPix := DllCall("liblept1820\pixReadMemBmp", "Ptr", pData, "UInt", 54+w*h*4, "Ptr")
, DllCall("libtesseract500\TessBaseAPISetImage2", "Ptr", hAPI, "Ptr", hPix)
; , out := FileOpen("out.bmp", "w"), out.Rawwrite(pData+0,54+w*h*4), out.Close()
, DllCall("GlobalUnlock", "ptr", hData) ; don't unlock immediately after rtlmovememory, wait a little bit
} else DllCall("libtesseract500\TessBaseAPISetImage", "Ptr", hAPI, "Ptr", pbits, "UInt", w, "UInt", h, "UInt", bytes_per_pixel := 4, "UInt", bytes_per_line := 4*w)
str := DllCall("libtesseract500\TessBaseAPIGetUTF8Text", "Ptr", hAPI, "AStr")
DllCall("DeleteDC", "ptr", dst)
, DllCall("DeleteObject", "ptr", dib)
, DllCall("ReleaseDC", "ptr", win_id, "ptr", src)
}
return str
}
LoadLibrary(dll)
{
if !hModule:=DllCall("LoadLibrary", "Str", dll, "Ptr")
msgbox % "LoadLibrary(" dll "): " GetLastError(A_LastError)
return hModule
}
GetLastError(Error=0)
{
VarSetCapacity(ErrorString, 1024)
IfEqual, Error, 0, SetEnv, Error, %A_LastError%
if DllCall("FormatMessage"
, "UINT", 0x1000 ; FORMAT_MESSAGE_FROM_SYSTEM: The function should search the system message-table resource(s) for the requested message.
, "PTR", 0 ; A handle to the module that contains the message table to search.
, "UINT", Error
, "UINT", 0 ; Language-ID is automatically retreived
, "Str", ErrorString
, "UINT", 1024 ; Buffer-Length
, "STR", "") ; "str", "") ;An array of values that are used as insert values in the formatted message. (not used)
return ErrorString
}