;#Include #include #include ;#include #include #include #include #Region --- Deklarácie --- Global $sHotKeyEscFunction = "Terminate" Global Const $iMinInt32 = -2147483648 Local $hWndTaskManager = 0 #EndRegion --- Declarations --- #Region --- Program --- Opt('WinWaitDelay', 100) Opt('WinDetectHiddenText', 1) Opt('MouseCoordMode', 2) Opt("PixelCoordMode", 2) HotKeySet("{ESC}", $sHotKeyEscFunction) ;Press Esc to terminate script Send("^+{ESC}") ;ShellExecute("Taskmgr.exe") $hWndTaskManager = WinWait("[CLASS:#32770]") WinActivate("[CLASS:#32770]") Local $sOutput = OCRScreenCaptureToText($hWndTaskManager, $iMinInt32, $iMinInt32, $iMinInt32, $iMinInt32, "eng", True, @ScriptDir & "\image.PNG") If @error Then ErrorMsgBox(((@error = 3 And @extended = 1) ? "Stderr Read: " : "") & $sOutput & ' ' & @error & ' ' & @extended) Exit 3 EndIf MsgBox($MB_SYSTEMMODAL, "OCRScreenCaptureToText", $sOutput) #EndRegion --- Program --- #Region --- Functions --- Func Terminate() Exit 2 EndFunc Func ErrorMsgBox($text, $title = "Chyba") Return MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), $title, $text) EndFunc ;======================================================================================================================================================================================= ; Description: ; Function OCRScreenCaptureToText provide OCR converting part of the screen or specified window to text ; ; Parameters: ; $hWnd - If not zero then corresponding window relative coordinates are used instead of absolute screen coordinates ; $iLeft, $iTop, $iRight, $iBottom - Coordinates of region to capture (if $iMinInt32 is specified then limit value will be used) ; $lang - Languages used in texts; You can combinate it as you need (E.g. "eng+deu+fra+ita+spa+por"); List of LangCode is available here: https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html ; $bShowPreview - If True then preview window of the captured region is shown ; $sFileName - If not empty string then captured region is saved into the file; File extension must be the same as $sFormat constant ; ; Please note: ; First you have to install tesseract (https://github.com/UB-Mannheim/tesseract/wiki) ; You can find proper installer here: https://digi.bib.uni-mannheim.de/tesseract/ ; I used this one: tesseract-ocr-w64-setup-5.4.0.20240606.exe (64-bit) ; Complete documentation is here: https://tesseract-ocr.github.io/tessdoc/ ; To increase the OCR precision try to enlarge the captured image to at least 300 DPI and check another options here: https://tesseract-ocr.github.io/tessdoc/ImproveQuality.html ;======================================================================================================================================================================================= Func OCRScreenCaptureToText($hWnd = 0, $iLeft = $iMinInt32, $iTop = $iMinInt32, $iRight = $iMinInt32, $iBottom = $iMinInt32, $lang = "eng", $bShowPreview = False, $sFileName = "") ; Corrections of the coordinates If $hWnd = 0 Then If $iLeft = $iMinInt32 Or $iRight = $iMinInt32 Then Local $XVirtualScreen = _WinAPI_GetSystemMetrics($SM_XVIRTUALSCREEN) If $iLeft = $iMinInt32 Then $iLeft = $XVirtualScreen If $iRight = $iMinInt32 Then $iRight = $XVirtualScreen + _WinAPI_GetSystemMetrics($SM_CXVIRTUALSCREEN) EndIf If $iTop = $iMinInt32 Or $iBottom = $iMinInt32 Then Local $YVirtualScreen = _WinAPI_GetSystemMetrics($SM_YVIRTUALSCREEN) If $iTop = $iMinInt32 Then $iTop = $YVirtualScreen If $iBottom = $iMinInt32 Then $iBottom = $YVirtualScreen + _WinAPI_GetSystemMetrics($SM_CYVIRTUALSCREEN) EndIf $hWnd = _WinAPI_GetDesktopWindow() Else If $iLeft = $iMinInt32 Then $iLeft = 0 If $iTop = $iMinInt32 Then $iTop = 0 If $iRight = $iMinInt32 Or $iBottom = $iMinInt32 Then Local $aClientSize = WinGetClientSize($hWnd) If $iRight = $iMinInt32 Then $iRight = $aClientSize[0] If $iBottom = $iMinInt32 Then $iBottom = $aClientSize[1] EndIf EndIf If $iRight < $iLeft Then Return SetError(1, 0, "Right cannot be less than Left") If $iBottom < $iTop Then Return SetError(1, 1, "Bottom cannot be less than Top") ; Capture the screen Local $iWidth = $iRight - $iLeft Local $iHeight = $iBottom - $iTop Local $hDDC = _WinAPI_GetDC($hWnd) Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight) Local $hCDC = _WinAPI_CreateCompatibleDC($hDDC) _WinAPI_SelectObject($hCDC, $hBitmap) _WinAPI_BitBlt($hCDC, 0, 0, $iWidth, $iHeight, $hDDC, $iLeft, $iTop, $SRCCOPY) ;normal colors ; _WinAPI_BitBlt($hCDC, 0, 0, $iWidth, $iHeight, $hDDC, $iLeft, $iTop, $NOTSRCCOPY) ;invert colors _WinAPI_DeleteDC($hCDC) _WinAPI_ReleaseDC($hWnd, $hDDC) ; Save the capture in memory as an image of specific format Local Const $sFormat = "PNG" _GDIPlus_Startup() ; Initialize GDI+ library If @error Then Return SetError(2, 0, "_GDIPlus_Startup() - failed") Local $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) ;convert GDI bitmap to GDI+ bitmap _WinAPI_DeleteObject($hBitmap) ;release GDI bitmap resource because not needed anymore ;convert to 4 BPP (it has good OCR results) Local $hImageClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, _GDIPlus_ImageGetWidth($hImage), _GDIPlus_ImageGetHeight($hImage), $GDIP_PXF04INDEXED) _GDIPlus_ImageDispose($hImage) $hImage = $hImageClone Switch $sFormat Case "BMP", "GIF", "JPG", "JPEG", "PNG", "TIF", "TIFF" Case Else Return SetError(2, 2, "Unsupported image format") EndSwitch Local $sCLSID = _GDIPlus_EncodersGetCLSID($sFormat) ;create CLSID for a JPG image file type If @error Then Return SetError(2, 3, "_GDIPlus_EncodersGetCLSID() - failed") Local $tGUID = _WinAPI_GUIDFromString($sCLSID) ;convert CLSID GUID to binary form and returns $tagGUID structure If @error Then Return SetError(2, 4, "_WinAPI_GUIDFromString() - failed") Local $tParams Switch $sFormat #comments-start Case "BMP" $tParams = 0 ; BMP format options: ; $GDIP_PXF01INDEXED = 0x00030101: 1 bpp, indexed ; $GDIP_PXF04INDEXED = 0x00030402: 4 bpp, indexed ; $GDIP_PXF08INDEXED = 0x00030803: 8 bpp, indexed ; $GDIP_PXF16GRAYSCALE = 0x00101004: 16 bpp, grayscale ; $GDIP_PXF16RGB555 = 0x00021005: 16 bpp; 5 bits for each RGB ; $GDIP_PXF16RGB565 = 0x00021006: 16 bpp; 5 bits red, 6 bits green, and 5 bits blue ; $GDIP_PXF16ARGB1555 = 0x00061007: 16 bpp; 1 bit for alpha and 5 bits for each RGB component ; $GDIP_PXF24RGB = 0x00021808: 24 bpp; 8 bits for each RGB ; $GDIP_PXF32RGB = 0x00022009: 32 bpp; 8 bits for each RGB. No alpha. ; $GDIP_PXF32ARGB = 0x0026200A: 32 bpp; 8 bits for each RGB and alpha ; $GDIP_PXF32PARGB = 0x000E200B: 32 bpp; 8 bits for each RGB and alpha, pre-mulitiplied ; $GDIP_PXF48RGB = 0x0010300C: 48 bpp; 16 bits for each RGB ; $GDIP_PXF64ARGB = 0x0034400D: 64 bpp; 16 bits for each RGB and alpha ; $GDIP_PXF64PARGB = 0x001A400E: 64 bpp; 16 bits for each RGB and alpha, pre-multiplied Local $hImageClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, _GDIPlus_ImageGetWidth($hImage), _GDIPlus_ImageGetHeight($hImage), $GDIP_PXF24RGB) _GDIPlus_ImageDispose($hImage) $hImage = $hImageClone #comments-end Case "JPG", "JPEG" $tParams = _GDIPlus_ParamInit(1) ;initialize an encoder parameter list and return $tagGDIPENCODERPARAMS structure Local $tData = DllStructCreate("int Quality") ;create struct to set JPG quality setting DllStructSetData($tData, "Quality", 100) ; Quality option 0-100 (0: lowest, 100: highest) _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tData)) ;add a value to an encoder parameter list Case "TIF", "TIFF" $tParams = _GDIPlus_ParamInit(2) ;initialize an encoder parameter list and return $tagGDIPENCODERPARAMS structure Local $tData = DllStructCreate("int ColorDepth;int Compression") ;create struct to set TIF quality setting ; TIFF color depth options: ; 24 ; 32 DllStructSetData($tData, "ColorDepth", 32) ; TIFF compression options: ; $GDIP_EVTCOMPRESSIONLZW = 2: LZW compression ; $GDIP_EVTCOMPRESSIONCCITT3 = 3: CCITT3 compression ; $GDIP_EVTCOMPRESSIONCCITT4 = 4: CCITT4 compression ; $GDIP_EVTCOMPRESSIONRLE = 5: RLE compression ; $GDIP_EVTCOMPRESSIONNONE = 6: No compression DllStructSetData($tData, "Compression", $GDIP_EVTCOMPRESSIONLZW) _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOLORDEPTH, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "ColorDepth")) ;add a value to an encoder parameter list _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOMPRESSION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Compression")) ;add a value to an encoder parameter list Case Else $tParams = 0 EndSwitch If $sFileName <> "" Then If StringUpper(__GDIPlus_ExtractFileExt($sFileName)) <> $sFormat Then Return SetError(1, 2, "File extension differ from image format") _GDIPlus_ImageSaveToFileEx($hImage, $sFileName, $sCLSID, IsDllStruct($tParams) ? $tParams : 0) ;save image as a file If @error Then Return SetError(1, 3, "_GDIPlus_ImageSaveToFileEx() - failed") EndIf Local $pStream = _WinAPI_CreateStreamOnHGlobal() ;create stream (http://msdn.microsoft.com/en-us/library/ms864401.aspx) If @error Then Return SetError(2, 5, "_WinAPI_CreateStreamOnHGlobal() - failed") _GDIPlus_ImageSaveToStream($hImage, $pStream, $tGUID, $tParams) ;save the formatted bitmap in memory If @error Then Return SetError(2, 6, "_GDIPlus_ImageSaveToStream() - failed") _GDIPlus_ImageDispose($hImage) If $bShowPreview Then Local $tPoint = DllStructCreate("int X;int Y") DllStructSetData($tPoint, "X", $iLeft) DllStructSetData($tPoint, "Y", $iTop) _WinAPI_ClientToScreen($hWnd, $tPoint) Local $hWndPreview = GUICreate("Preview...", $iWidth, $iHeight, DllStructGetData($tPoint, "X") - _WinAPI_GetSystemMetrics($SM_CXFIXEDFRAME), DllStructGetData($tPoint, "Y") - _WinAPI_GetSystemMetrics($SM_CYFIXEDFRAME) - _WinAPI_GetSystemMetrics($SM_CYCAPTION)) If @error Then Return SetError(1, 4, "GUICreate() - failed") Local $hBitmapFromStream = _GDIPlus_BitmapCreateFromStream($pStream) ;create bitmap from a stream (here from the $sFormat in memory) Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hWndPreview) ;create a graphics object from a window handle HotKeySet("{ESC}") ;Press Esc to close the preview window GUISetState(@SW_SHOW) Do _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmapFromStream, 0, 0) ;display streamed image Until GUIGetMsg() = $GUI_EVENT_CLOSE HotKeySet("{ESC}", $sHotKeyEscFunction) ;Restore previous Esc functionality _GDIPlus_GraphicsDispose($hGraphics) _GDIPlus_BitmapDispose($hBitmapFromStream) GUIDelete($hWndPreview) EndIf Local $hMemory = _WinAPI_GetHGlobalFromStream($pStream) ;http://msdn.microsoft.com/en-us/library/aa911736.aspx If @error Then Return SetError(2, 7, "_WinAPI_GetHGlobalFromStream() - failed") Local $iMemSize = _MemGlobalSize($hMemory) If Not $iMemSize Then Return SetError(2, 8, "_MemGlobalSize() - failed") Local $tMemory = DllStructCreate("byte[" & $iMemSize & "]", _MemGlobalLock($hMemory)) Local $bData = DllStructGetData($tMemory, 1) _WinAPI_ReleaseStream($pStream) ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms221473(v=vs.85).aspx _MemGlobalFree($hMemory) _GDIPlus_Shutdown() ; Shut down GDI+ library ; OCR converting of the image to text Local $TesseractExePath = @ProgramFilesDir & "\Tesseract-OCR\tesseract.exe" ;C:\Program Files (x86)\Tesseract-OCR\tesseract.exe If Not FileExists($TesseractExePath) Then $TesseractExePath = StringReplace($TesseractExePath, " (x86)", "") ;C:\Program Files\Tesseract-OCR\tesseract.exe If Not FileExists($TesseractExePath) Then Return SetError(3, 0, "The file 'tesseract.exe' not found") EndIf Local $iPID = Run('"' & $TesseractExePath & '" stdin stdout -l ' & $lang & ' --psm 6"', @ScriptDir, @SW_HIDE, BitOR($STDIN_CHILD, $STDERR_CHILD, $STDOUT_CHILD)) StdinWrite($iPID, $bData) StdinWrite($iPID) ; Calling StdinWrite without a second parameter closes the stream. ProcessWaitClose($iPID) ; Wait until the process has closed using the PID returned by Run. Local $sOutput = '' If @error Then Do $sOutput &= StderrRead($iPID) ; Read the Stderr stream of the PID returned by Run Until @error StdioClose($iPID) Return SetError(3, 1, $sOutput) EndIf Do $sOutput &= StdoutRead($iPID) ; Read the Stdout stream of the PID returned by Run Until @error StdioClose($iPID) Return $sOutput EndFunc #EndRegion --- Functions ---