ioa747 Posted July 31, 2022 Share Posted July 31, 2022 (edited) SmartNote tesseract Edition: SmartNote is a screen snip tool to snip screen area with OCR ability from tesseract 100+ languages I tried it in Windows 10 with the version tesseract-ocr-w32-setup-v5.3.0.20221214.exe Snipe new note Double Click the tray icon to start NewCapture or While Left Windows Key IsPressed, tap 2 times the Left Shift key (is useful when Capture menu or context menu). While start NewCapture point click anywhere to escape. (Does not catch smaller than 9*9 px) While start NewCapture escape with ESC Spoiler Tesseract info Of course, you will have to install it first. tesseract-installer-for-windows Languages supported https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html More info Command-Line-Usage SmartNote.au3 expandcollapse popup; https://www.autoitscript.com/forum/topic/208600-smartnote/ ;---------------------------------------------------------------------------------------- ; Title...........: SmartNote.au3 ; Description.....: SmartNote is a screen snip tool to take Screenshot with OCR ability from Tesseract (100+ languages) ; AutoIt Version..: 3.3.16.1 Author: ioa747 ;---------------------------------------------------------------------------------------- #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=mmcndmgr-106.ico #AutoIt3Wrapper_Res_Description=SmartNote is a screen snip tool to take Screenshot with OCR ability from Tesseract (100+ languages) #AutoIt3Wrapper_Res_Fileversion=0.0.5.20240413 #AutoIt3Wrapper_Res_ProductName=SmartNote.au3 #AutoIt3Wrapper_Res_CompanyName=ioa747 #AutoIt3Wrapper_Res_LegalCopyright=ioa747 #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #NoTrayIcon If WinExists(StringTrimRight(@ScriptName, 4) & "_STUB") Then Exit 5 AutoItWinSetTitle(StringTrimRight(@ScriptName, 4) & "_STUB") If @AutoItX64 Then Exit MsgBox(262144 + 64, StringTrimRight(@ScriptName, 4), "Please run as 32bit", 60) #include <MsgBoxConstants.au3> #include <ScreenCapture.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StaticConstants.au3> #include <TrayConstants.au3> #include <Misc.au3> #include <Array.au3> #include <GDIPlus.au3> #include <Clipboard.au3> #include <String.au3> ; Initialization DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", "int", -4) ; -4=PerMonitorAwareV2 Opt("MouseCoordMode", 1) ; 1=absolute, 0=relative, 2=client Opt("TrayMenuMode", 3) ; 0=append, 1=no default menu, 2=no automatic check, 4=menuitemID not return Opt("TrayOnEventMode", 1) ; Enable TrayOnEventMode. Opt("GUIOnEventMode", 1) ; 0=disabled, 1=OnEvent mode enabled ; tray entry to exit script Global $TRAY_ExitScript = TrayCreateItem("Exit") TrayItemSetOnEvent(-1, "TRAY_EVENT") ; separator TrayCreateItem("") ; tray entry to capture Global $TRAY_NewCapture = TrayCreateItem("Capture") TrayItemSetOnEvent(-1, "TRAY_EVENT") TraySetOnEvent($TRAY_EVENT_PRIMARYDOUBLE, "TRAY_EVENT") TraySetIcon("mmcndmgr.dll", -106) TraySetClick(16) ; $TRAY_CLICK_SECONDARYUP = 16 TraySetState($TRAY_ICONSTATE_SHOW) TraySetToolTip("SmartNote" & @CRLF & "Double Click to take new note") Global $mPos, $aRecPos[4], $hGUICapture, $block_gui Global $hDLL = DllOpen("user32.dll") ; array to hold the Contextmenu data Global $NoteGui[1][14] $NoteGui[0][0] = 0 ; cnt, Note_Handle $NoteGui[0][1] = "jpgPath" $NoteGui[0][2] = "Gui_Size" $NoteGui[0][3] = "ID_PicCtrl" $NoteGui[0][4] = "ID_ContextMenu" $NoteGui[0][5] = "ID_cMenuCopy" $NoteGui[0][6] = "ID_cMenuShareX" $NoteGui[0][7] = "ID_cMenuSave" $NoteGui[0][8] = "ID_cMenuOpen" $NoteGui[0][9] = "ID_cMenuOCR-eng" $NoteGui[0][10] = "ID_cMenuOCR-eng+ell" $NoteGui[0][11] = "ID_cMenuClose" $NoteGui[0][12] = "ID_Dummy_DeleteKey" $NoteGui[0][13] = "ID_Dummy_EnterKey" ; Check for leftover files Global $iFileExists = FileExists(@ScriptDir & "\tmp") If $iFileExists Then FileDelete(@ScriptDir & "\tmp\*.*") Else DirCreate(@ScriptDir & "\tmp") EndIf ;~ HotKeySet("{PGUP}", "_Array_Gui_display") ; *** Debug _ArrayDisplay($NoteGui, "$NoteGui") <<- HotKey ; ℹ️ While Left Windows Key IsPressed, tap 2 times the Left SHIFT key to start NewCapture, ; is useful when Capture menu or contex menu. ; While start NewCapture point click anywhere to escape. (does not catch smaller than 9*9 px) ; While start NewCapture escape with ESC Global $iShift ; loop until program exit ;************************************************ While Sleep(100) $iShift = 0 While _IsPressed("5B", $hDLL) ; 5B Left Windows key Sleep(100) If _IsPressed("A0", $hDLL) Then ; A0 Left SHIFT key While _IsPressed("A1", $hDLL) Sleep(100) WEnd $iShift += 1 EndIf If $iShift = 2 Then NewCapture() ExitLoop EndIf WEnd WEnd ;************************************************ ;---------------------------------------------------------------------------------------- Func NewCapture() ; NewCapture Local $aRecPos[4], $aMPos[2], $tPos ;, $aTipPos[4], $iX, $iY Local $iDeskWidth, $iDeskHeight, $iDeskLeft, $iDeskTop Local $sDevice, $hMonitor, $sCurDevice, $aData, $Status = 0 ; make Capture gui $hGUICapture = GUICreate("Capture_gui", 1, 1, 1, 1, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) GUISetBkColor("0xFFFF00", $hGUICapture) ; $COLOR_YELLOW WinSetTrans($hGUICapture, "", 50) ; make mouse block gui $block_gui = GUICreate("block_gui", 1, 1, 1, 1, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) WinSetTrans($block_gui, "", 1) GUISetState(@SW_SHOW, $block_gui) GUISetCursor($MCID_CROSS, 1, $block_gui) Sleep(200) Local $iMaxLoop = 1200, $iCntLoop = 0 While Sleep(10) $iCntLoop += 1 If $iCntLoop = $iMaxLoop Then ExitLoop ; get mouse coordinates $tPos = _WinAPI_GetMousePos() $aMPos[0] = DllStructGetData($tPos, 1) $aMPos[1] = DllStructGetData($tPos, 2) ; get $hMonitor from previously defined Mouse coordinates $hMonitor = _WinAPI_MonitorFromPoint($tPos) ; get monitor $aData appropriate for previously defined coordinates $aData = _WinAPI_GetMonitorInfo($hMonitor) If Not @error Then $sDevice = $aData[3] $iDeskLeft = DllStructGetData($aData[0], 1) $iDeskTop = DllStructGetData($aData[0], 2) $iDeskWidth = DllStructGetData($aData[0], 3) $iDeskHeight = DllStructGetData($aData[0], 4) EndIf ;move the $block_gui to active monitor If $sCurDevice <> $sDevice Then $sCurDevice = $sDevice ;ConsoleWrite("- $sCurDevice=" & $sCurDevice & @CRLF) WinMove($block_gui, "", $iDeskLeft, $iDeskTop, $iDeskWidth, $iDeskHeight) EndIf ; whait Left_mouse_button _IsPressed If _IsPressed("01", $hDLL) Then $Status = 1 $aMPos = MouseGetPos() $aRecPos[0] = $aMPos[0] $aRecPos[1] = $aMPos[1] ; Wait until key is released. While _IsPressed("01", $hDLL) Sleep(50) $aMPos = MouseGetPos() $aRecPos[2] = $aMPos[0] $aRecPos[3] = $aMPos[1] ; show Capture gui GUISetState(@SW_SHOW, $hGUICapture) WinMove($hGUICapture, "", $aRecPos[0], $aRecPos[1], $aRecPos[2] - $aRecPos[0], $aRecPos[3] - $aRecPos[1]) WEnd ElseIf _IsPressed("1B", $hDLL) Then ;1B=ESC key - emergency exit GUIDelete($hGUICapture) GUIDelete($block_gui) Return SetError(1, 1, 0) EndIf If $Status = 1 Then ExitLoop WEnd GUIDelete($hGUICapture) GUIDelete($block_gui) ;ConsoleWrite($aRecPos[0] & ";" & $aRecPos[1] & ";" & $aRecPos[2] - $aRecPos[0] & ";" & $aRecPos[3] - $aRecPos[1] & @CRLF) ; if bigger from 9*9 px then create note If ($aRecPos[2] - $aRecPos[0]) > 9 And ($aRecPos[3] - $aRecPos[1]) > 9 Then CreateNew_NoteGui($aRecPos) ; create new note ;Return $FilePath EndFunc ;==>NewCapture ;---------------------------------------------------------------------------------------- Func CreateNew_NoteGui($aRecPos) ; create new note gui Local $n, $aSize[2] ReDim $NoteGui[UBound($NoteGui) + 1][14] $NoteGui[0][0] += 1 $n = $NoteGui[0][0] $aSize[0] = $aRecPos[2] - $aRecPos[0] ; width $aSize[1] = $aRecPos[3] - $aRecPos[1] ; height ; create note GUI $NoteGui[$n][0] = GUICreate($NoteGui[$n][1], $aSize[0], $aSize[1], $aRecPos[0], $aRecPos[1], $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) GUISetOnEvent($GUI_EVENT_RESIZED, "GUI_EVENT", $NoteGui[$n][0]) ; jpg Path for _ScreenCapture_Capture $NoteGui[$n][1] = @ScriptDir & "\tmp\image_" & $NoteGui[$n][0] & ".jpg" _ScreenCapture_Capture($NoteGui[$n][1], $aRecPos[0], $aRecPos[1], $aRecPos[2], $aRecPos[3]) ; save the Gui_Size $NoteGui[$n][2] = $aSize ; set jpg Path as GUI title WinSetTitle($NoteGui[$n][0], "", $NoteGui[$n][1]) ; Creates a Picture control $NoteGui[$n][3] = GUICtrlCreatePic($NoteGui[$n][1], 0, 0, 0, 0, -1, $GUI_WS_EX_PARENTDRAG) ; Creates a Label control just for $SS_GRAYFRAME GUICtrlCreateLabel("", 0, 0, $aSize[0], $aSize[1], $SS_GRAYFRAME) ; Creates a context menu $NoteGui[$n][4] = GUICtrlCreateContextMenu($NoteGui[$n][3]) ; MenuItem for the context menu "Copy to Clipboard" $NoteGui[$n][5] = GUICtrlCreateMenuItem("Copy to Clipboard" & @TAB & "ENTER", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_CopyToClipboard") ; MenuItem for the context menu "ID_cMenuShareX" $NoteGui[$n][6] = GUICtrlCreateMenuItem("Send to ShareX", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_ShareX") ; MenuItem for the context menu "Save as..." $NoteGui[$n][7] = GUICtrlCreateMenuItem("Save as...", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_SaveAs") ; MenuItem for the context menu "Open" $NoteGui[$n][8] = GUICtrlCreateMenuItem("Open", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_Open") ; separator GUICtrlCreateMenuItem("", $NoteGui[$n][4]) ; MenuItem for the context menu "OCR - eng" $NoteGui[$n][9] = GUICtrlCreateMenuItem("OCR - eng", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_OCR_Eng") ; MenuItem for the context menu "OCR - eng+ell" $NoteGui[$n][10] = GUICtrlCreateMenuItem("OCR - eng+ell", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_OCR_EngEll") ; separator GUICtrlCreateMenuItem("", $NoteGui[$n][4]) ; MenuItem for the context menu "Close" $NoteGui[$n][11] = GUICtrlCreateMenuItem("Close" & @TAB & "DELETE" , $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_Close") ; Display the GUI. GUISetState(@SW_SHOW, $NoteGui[$n][0]) $NoteGui[$n][12] = GUICtrlCreateDummy() $NoteGui[$n][13] = GUICtrlCreateDummy() Local $aAccelKeys[2][2] = [ ["{DELETE}", $NoteGui[$n][12] ], ["{ENTER}", $NoteGui[$n][13] ] ] GUISetAccelerators($aAccelKeys) GUICtrlSetOnEvent($NoteGui[$n][12], "cm_Close") GUICtrlSetOnEvent($NoteGui[$n][13], "cm_CopyToClipboard") Return $NoteGui[$n][0] EndFunc ;==>CreateNew_NoteGui ;---------------------------------------------------------------------------------------- Func SaveFileDlg($Active_title) ; Save file Dialog ; Create a constant variable in Local scope of the message to display in FileSaveDialog. Local Const $sMessage = "Choose a filename." ; Display a save dialog to select a file. Local $sFileSaveDialog = FileSaveDialog($sMessage, @ScriptDir & "\SET\", "image (*.jpg)", $FD_PATHMUSTEXIST) If @error Then ; Display the error message. MsgBox($MB_SYSTEMMODAL, "", "No file was saved.") Else ; Retrieve the filename from the filepath e.g. Example.jpg Local $sFileName = StringTrimLeft($sFileSaveDialog, StringInStr($sFileSaveDialog, "\", $STR_NOCASESENSEBASIC, -1)) ; Check if the extension .jpg is appended to the end of the filename. Local $iExtension = StringInStr($sFileName, ".", $STR_NOCASESENSEBASIC) ; If a period (dot) is found then check whether or not the extension is equal to .jpg If $iExtension Then ; If the extension isn't equal to .jpg then append to the end of the filepath. If Not (StringTrimLeft($sFileName, $iExtension - 1) = ".jpg") Then $sFileSaveDialog &= ".jpg" Else ; If no period (dot) was found then append to the end of the file. $sFileSaveDialog &= ".jpg" EndIf ; Display the saved file. ;ConsoleWrite("You saved the following file:" & @CRLF & $sFileSaveDialog & @CRLF) FileCopy($Active_title, $sFileSaveDialog, $FC_OVERWRITE + $FC_CREATEPATH) EndIf EndFunc ;==>SaveFileDlg ;---------------------------------------------------------------------------------------- Func NoteGui_Delete($hWnd) ; NoteGui_Delete For $i = 1 To $NoteGui[0][0] If $NoteGui[$i][0] = $hWnd Then _ArrayDelete($NoteGui, $i) $NoteGui[0][0] -= 1 ExitLoop EndIf Next EndFunc ;==>NoteGui_Delete ;---------------------------------------------------------------------------------------- Func PicToClip($Path) ; put image to clipboard (Thanks to @Nine) _GDIPlus_Startup() Local $hImage = _GDIPlus_ImageLoadFromFile($Path) Local $hBitmap1 = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) _GDIPlus_ImageDispose($hImage) Local $hBitmap2 = _WinAPI_CopyImage($hBitmap1, $IMAGE_BITMAP, 0, 0, $LR_COPYDELETEORG + $LR_COPYRETURNORG) _WinAPI_DeleteObject($hBitmap1) _GDIPlus_Shutdown() _ClipBoard_Open(0) _ClipBoard_Empty() _ClipBoard_SetDataEx($hBitmap2, $CF_BITMAP) _ClipBoard_Close() _WinAPI_DeleteObject($hBitmap2) EndFunc ;==>PicToClip ;---------------------------------------------------------------------------------------- Func TesseracOCR($ImagePath, $lang) ; perform ocr (Thanks to @JohnOne) ;~ ; $lang = more LangCode -> https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html ;~ ; more info at -> https://tesseract-ocr.github.io/tessdoc/Command-Line-Usage.html#simplest-invocation-to-ocr-an-image ;~ ; Of course you will have to install it first. -> https://github.com/UB-Mannheim/tesseract/wiki ;~ ; I tried it in Windows 10 with the version -> https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-w32-setup-v5.3.0.20221214.exe Local $ResultTextPath, $OutPutPath, $Result ;C:\Program Files (x86)\Tesseract-OCR\tesseract.exe Local Const $TesseractExePath = @ProgramFilesDir & "\Tesseract-OCR\tesseract.exe" ; ℹ️ Give your path * <- $ResultTextPath = @ScriptDir & "\tmp\Result" $OutPutPath = $ResultTextPath & ".txt" ShellExecuteWait($TesseractExePath, '"' & $ImagePath & '" "' & $ResultTextPath & '" -l ' & $lang & ' --psm 6', "", "", @SW_HIDE) ;ConsoleWrite($TesseractExePath & ' "' & $ImagePath & '" "' & $ResultTextPath & '" -l ' & $lang & ' --psm 6' & @CRLF) If @error Then Exit MsgBox($MB_OK + $MB_TOPMOST + $MB_ICONERROR, "Error", @error) EndIf $Result = FileRead($OutPutPath) ;Remove last @LF Local $LastG = StringRight($Result, 1) If $LastG = @LF Then $Result = StringTrimRight($Result, 1) Local $Msg = @CRLF & @CRLF & _StringRepeat(@TAB, 4) & "Copy to ClipBoard ?" Local $iMsgBoxAnswer = MsgBox(4, "OCR Result", $Result & $Msg) If $iMsgBoxAnswer = 6 Then ;Yes ClipPut($Result) ToolTip("The text was copied to the clipboard") Sleep(1000) ToolTip("") EndIf FileDelete($OutPutPath) EndFunc ;==>TesseracOCR ;---------------------------------------------------------------------------------------- Func TRAY_EVENT() ; TRAY_Event Switch @TRAY_ID ; Check the last tray item identifier. Case $TRAY_EVENT_PRIMARYDOUBLE, $TRAY_NewCapture NewCapture() Case $TRAY_ExitScript DllClose($hDLL) Exit EndSwitch EndFunc ;==>TRAY_EVENT ;---------------------------------------------------------------------------------------- Func GUI_EVENT() ; GUI_EVENT Select Case @GUI_CtrlId = $GUI_EVENT_RESIZED Local $aSize For $i = 1 To $NoteGui[0][0] If $NoteGui[$i][0] = @GUI_WinHandle Then $aSize = $NoteGui[$i][2] WinMove(@GUI_WinHandle, "", Default, Default, $aSize[0], $aSize[1]) ControlMove(@GUI_WinHandle, "", "Static1", 0, 0, $aSize[0], $aSize[1]) ControlMove(@GUI_WinHandle, "", "Static2", 0, 0, $aSize[0], $aSize[1]) ExitLoop EndIf Next EndSelect EndFunc ;==>GUI_EVENT ;---------------------------------------------------------------------------------------- Func cm_CopyToClipboard() ; ContextMenu "Copy to Clipboard" Local $Active_title = WinGetTitle(@GUI_WinHandle) ToolTip("Copied to clipboard") PicToClip($Active_title) Sleep(500) ToolTip("") EndFunc ;==>cm_CopyToClipboard ;---------------------------------------------------------------------------------------- Func cm_ShareX() ; ContextMenu "Send to ShareX"" Local $Active_title = WinGetTitle(@GUI_WinHandle) PicToClip($Active_title) Sleep(100) Local $strLen = StringLen(@ScriptDir & "\tmp\image_") If StringLeft($Active_title, $strLen) = @ScriptDir & "\tmp\image_" Then GUIDelete(@GUI_WinHandle) FileDelete($Active_title) NoteGui_Delete(@GUI_WinHandle) EndIf ShellExecute("C:\Program Files\ShareX\ShareX.exe", "-imageeditor ") ; ℹ️ Give your path * <- Local $hShareXImageEd = WinWait("[TITLE:ShareX - Image editor; REGEXPCLASS:WindowsForms10\.Window\..\.app\.0\..+_r\d+_ad1]", "", 2) While WinExists($hShareXImageEd) ControlClick($hShareXImageEd, "", "[NAME:btnLoadImageFromClipboard]") Sleep(300) WEnd $hShareXImageEd = WinWait("[TITLE:ShareX - Image editor; REGEXPCLASS:WindowsForms10\.Window\..\.app\.0\..+_r\d+_ad1]", "", 2) WinActivate($hShareXImageEd) WinSetState($hShareXImageEd, "", @SW_MAXIMIZE) EndFunc ;==>cm_ShareX ;---------------------------------------------------------------------------------------- Func cm_SaveAs() ; ContextMenu "Save as..." Local $Active_title = WinGetTitle(@GUI_WinHandle) SaveFileDlg($Active_title) EndFunc ;==>cm_SaveAs ;---------------------------------------------------------------------------------------- Func cm_Open() ; ContextMenu "Open" Local $Active_title = WinGetTitle(@GUI_WinHandle) ShellExecute($Active_title) EndFunc ;==>cm_Open ;---------------------------------------------------------------------------------------- Func cm_OCR_Eng() ; ContextMenu "OCR - eng" Local $Active_title = WinGetTitle(@GUI_WinHandle) TesseracOCR($Active_title, "eng") EndFunc ;==>cm_OCR_Eng ;---------------------------------------------------------------------------------------- Func cm_OCR_EngEll() ; ContextMenu "OCR - eng+ell" Local $Active_title = WinGetTitle(@GUI_WinHandle) TesseracOCR($Active_title, "eng+ell") EndFunc ;==>cm_OCR_EngEll ;---------------------------------------------------------------------------------------- Func cm_Close() ; ContextMenu "Close" Local $Active_title = WinGetTitle(@GUI_WinHandle) Local $strLen = StringLen(@ScriptDir & "\tmp\image_") If StringLeft($Active_title, $strLen) = @ScriptDir & "\tmp\image_" Then GUIDelete(@GUI_WinHandle) FileDelete($Active_title) NoteGui_Delete(@GUI_WinHandle) ;ConsoleWrite("- WinClose " & @GUI_WinHandle & " & FileDelete " & $Active_title & @CRLF) EndIf EndFunc ;==>cm_Close ;---------------------------------------------------------------------------------------- Func _Array_Gui_display() ; *** Debug _ArrayDisplay($NoteGui) _ArrayDisplay($NoteGui, "$NoteGui") EndFunc ;==>NoteGui_display ;---------------------------------------------------------------------------------------- Please, every comment is appreciated! leave your comments and experiences here! Thank you very much Edited April 13 by ioa747 UpDate to 0.0.5.20240413 Danyfirex and itchiTrigger 2 I know that I know nothing Link to comment Share on other sites More sharing options...
ioa747 Posted September 26, 2023 Author Share Posted September 26, 2023 On 7/31/2022 at 7:33 PM, ioa747 said: UpDate to Version 0.0.3.20230924 I know that I know nothing Link to comment Share on other sites More sharing options...
ioa747 Posted March 31 Author Share Posted March 31 (edited) SmartNote UWPOCR Edition: For those who don't want to install the tesseract . Using only the Windows Optical character recognition API (at least Windows 10 ) and the UWPOCR UDF ( Thanks to @Danyfirex ) from: uwpocr-windows-platform-optical-character-recognition-api-implementation otherwise it is a clone of the above SmartNote_UWPOCR.au3 expandcollapse popup; https://www.autoitscript.com/forum/topic/208600-smartnote/?do=findComment&comment=1532353 ;---------------------------------------------------------------------------------------- ; Title...........: SmartNote_UWPOCR.au3 ; Description.....: SmartNote is a screen snip tool to take Screenshot with OCR ability from UWPOCR ; AutoIt Version..: 3.3.16.1 Author: ioa747 ;---------------------------------------------------------------------------------------- #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=mmcndmgr-106.ico #AutoIt3Wrapper_Res_Description=SmartNote is a screen snip tool to take Screenshot with OCR ability from UWPOCR #AutoIt3Wrapper_Res_Fileversion=0.0.2.20240331 #AutoIt3Wrapper_Res_ProductName=SmartNote_UWPOCR.au3 #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #NoTrayIcon If WinExists(StringTrimRight(@ScriptName, 4) & "_STUB") Then Exit 5 AutoItWinSetTitle(StringTrimRight(@ScriptName, 4) & "_STUB") If @AutoItX64 Then Exit MsgBox(262144 + 64, StringTrimRight(@ScriptName, 4), "Please run as 32bit", 60) #include <MsgBoxConstants.au3> #include <ScreenCapture.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StaticConstants.au3> #include <TrayConstants.au3> #include <Misc.au3> #include <Array.au3> #include <GDIPlus.au3> #include <Clipboard.au3> #include <String.au3> #include "UWPOCR.au3" ; * < -"https://www.autoitscript.com/forum/topic/207324-uwpocr-windows-platform-optical-character-recognition-api-implementation" ; Initialization DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", "int", -4) ; -4=PerMonitorAwareV2 Opt("MouseCoordMode", 1) ; 1=absolute, 0=relative, 2=client Opt("TrayMenuMode", 3) ; 0=append, 1=no default menu, 2=no automatic check, 4=menuitemID not return Opt("TrayOnEventMode", 1) ; Enable TrayOnEventMode. Opt("GUIOnEventMode", 1) ; 0=disabled, 1=OnEvent mode enabled ; tray entry to exit script Global $TRAY_ExitScript = TrayCreateItem("Exit") TrayItemSetOnEvent(-1, "TRAY_EVENT") ; separator TrayCreateItem("") ; tray entry to capture Global $TRAY_NewCapture = TrayCreateItem("Capture") TrayItemSetOnEvent(-1, "TRAY_EVENT") TraySetOnEvent($TRAY_EVENT_PRIMARYDOUBLE, "TRAY_EVENT") TraySetIcon("mmcndmgr.dll", -106) TraySetClick(16) ; $TRAY_CLICK_SECONDARYUP = 16 TraySetState($TRAY_ICONSTATE_SHOW) TraySetToolTip("SmartNote" & @CRLF & "Double Click to take new note") Global $mPos, $aRecPos[4], $hGUICapture, $block_gui Global $hDLL = DllOpen("user32.dll") ; array to hold the Contextmenu data Global $NoteGui[1][18] $NoteGui[0][0] = 0 ; cnt, Note_Handle $NoteGui[0][1] = "jpgPath" $NoteGui[0][2] = "Gui_Size" $NoteGui[0][3] = "ID_PicCtrl" $NoteGui[0][4] = "ID_ContextMenu" $NoteGui[0][5] = "ID_cMenuCopy" $NoteGui[0][6] = "ID_cMenuShareX" $NoteGui[0][7] = "ID_cMenuSave" $NoteGui[0][8] = "ID_cMenuOpen" $NoteGui[0][9] = "ID_FutureUse" $NoteGui[0][10] = "ID_FutureUse" $NoteGui[0][11] = "ID_Lang1" $NoteGui[0][12] = "ID_Lang2" $NoteGui[0][13] = "ID_Lang3" $NoteGui[0][14] = "ID_Lang4" $NoteGui[0][15] = "ID_cMenuClose" $NoteGui[0][16] = "ID_Dummy_DeleteKey" $NoteGui[0][17] = "ID_Dummy_EnterKey" ; Check for leftover files Global $iFileExists = FileExists(@ScriptDir & "\tmp") If $iFileExists Then FileDelete(@ScriptDir & "\tmp\*.*") Else DirCreate(@ScriptDir & "\tmp") EndIf Global $aSupportedLanguages = _UWPOCR_GetSupportedLanguages() Global $iLanguagesCnt = UBound($aSupportedLanguages) - 1 ;~ HotKeySet("{PGUP}", "_Array_Gui_display") ; *** Debug _ArrayDisplay($NoteGui, "$NoteGui") <<- HotKey ; ℹ️ While Left Windows Key IsPressed, tap 2 times the Left SHIFT key to start NewCapture, ; is useful when Capture menu or contex menu. ; While start NewCapture point click anywhere to escape. (does not catch smaller than 9*9 px) ; While start NewCapture escape with ESC Global $iShift ; loop until program exit ;************************************************ While Sleep(100) $iShift = 0 While _IsPressed("5B", $hDLL) ; 5B Left Windows key Sleep(100) If _IsPressed("A0", $hDLL) Then ; A0 Left SHIFT key While _IsPressed("A1", $hDLL) Sleep(100) WEnd $iShift += 1 EndIf If $iShift = 2 Then NewCapture() ExitLoop EndIf WEnd WEnd ;************************************************ ;---------------------------------------------------------------------------------------- Func NewCapture() ; NewCapture Local $aRecPos[4], $aMPos[2], $tPos ;, $aTipPos[4], $iX, $iY Local $iDeskWidth, $iDeskHeight, $iDeskLeft, $iDeskTop Local $sDevice, $hMonitor, $sCurDevice, $aData, $Status = 0 ; make Capture gui $hGUICapture = GUICreate("Capture_gui", 1, 1, 1, 1, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) GUISetBkColor("0xFFFF00", $hGUICapture) ; $COLOR_YELLOW WinSetTrans($hGUICapture, "", 50) ; make mouse block gui $block_gui = GUICreate("block_gui", 1, 1, 1, 1, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) WinSetTrans($block_gui, "", 1) GUISetState(@SW_SHOW, $block_gui) GUISetCursor($MCID_CROSS, 1, $block_gui) Sleep(200) Local $iMaxLoop = 1200, $iCntLoop = 0 While Sleep(10) $iCntLoop += 1 If $iCntLoop = $iMaxLoop Then ExitLoop ; get mouse coordinates $tPos = _WinAPI_GetMousePos() $aMPos[0] = DllStructGetData($tPos, 1) $aMPos[1] = DllStructGetData($tPos, 2) ; get $hMonitor from previously defined Mouse coordinates $hMonitor = _WinAPI_MonitorFromPoint($tPos) ; get monitor $aData appropriate for previously defined coordinates $aData = _WinAPI_GetMonitorInfo($hMonitor) If Not @error Then $sDevice = $aData[3] $iDeskLeft = DllStructGetData($aData[0], 1) $iDeskTop = DllStructGetData($aData[0], 2) $iDeskWidth = DllStructGetData($aData[0], 3) $iDeskHeight = DllStructGetData($aData[0], 4) EndIf ;move the $block_gui to active monitor If $sCurDevice <> $sDevice Then $sCurDevice = $sDevice ;ConsoleWrite("- $sCurDevice=" & $sCurDevice & @CRLF) WinMove($block_gui, "", $iDeskLeft, $iDeskTop, $iDeskWidth, $iDeskHeight) EndIf ; whait Left_mouse_button _IsPressed If _IsPressed("01", $hDLL) Then $Status = 1 $aMPos = MouseGetPos() $aRecPos[0] = $aMPos[0] $aRecPos[1] = $aMPos[1] ; Wait until key is released. While _IsPressed("01", $hDLL) Sleep(50) $aMPos = MouseGetPos() $aRecPos[2] = $aMPos[0] $aRecPos[3] = $aMPos[1] ; show Capture gui GUISetState(@SW_SHOW, $hGUICapture) WinMove($hGUICapture, "", $aRecPos[0], $aRecPos[1], $aRecPos[2] - $aRecPos[0], $aRecPos[3] - $aRecPos[1]) WEnd ElseIf _IsPressed("1B", $hDLL) Then ;1B=ESC key - emergency exit GUIDelete($hGUICapture) GUIDelete($block_gui) Return SetError(1, 1, 0) EndIf If $Status = 1 Then ExitLoop WEnd GUIDelete($hGUICapture) GUIDelete($block_gui) ;ConsoleWrite($aRecPos[0] & ";" & $aRecPos[1] & ";" & $aRecPos[2] - $aRecPos[0] & ";" & $aRecPos[3] - $aRecPos[1] & @CRLF) ; if bigger from 9*9 px then create note If ($aRecPos[2] - $aRecPos[0]) > 9 And ($aRecPos[3] - $aRecPos[1]) > 9 Then CreateNew_NoteGui($aRecPos) ; create new note ;Return $FilePath EndFunc ;==>NewCapture ;---------------------------------------------------------------------------------------- Func CreateNew_NoteGui($aRecPos) ; create new note gui Local $n, $aSize[2] ReDim $NoteGui[UBound($NoteGui) + 1][18] $NoteGui[0][0] += 1 $n = $NoteGui[0][0] $aSize[0] = $aRecPos[2] - $aRecPos[0] ; width $aSize[1] = $aRecPos[3] - $aRecPos[1] ; height ; create note GUI $NoteGui[$n][0] = GUICreate($NoteGui[$n][1], $aSize[0], $aSize[1], $aRecPos[0], $aRecPos[1], $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) GUISetOnEvent($GUI_EVENT_RESIZED, "GUI_EVENT", $NoteGui[$n][0]) ; jpg Path for _ScreenCapture_Capture $NoteGui[$n][1] = @ScriptDir & "\tmp\image_" & $NoteGui[$n][0] & ".jpg" _ScreenCapture_Capture($NoteGui[$n][1], $aRecPos[0], $aRecPos[1], $aRecPos[2], $aRecPos[3]) ; save the Gui_Size $NoteGui[$n][2] = $aSize ; set jpg Path as GUI title WinSetTitle($NoteGui[$n][0], "", $NoteGui[$n][1]) ; Creates a Picture control $NoteGui[$n][3] = GUICtrlCreatePic($NoteGui[$n][1], 0, 0, 0, 0, -1, $GUI_WS_EX_PARENTDRAG) ; Creates a Label control just for $SS_GRAYFRAME GUICtrlCreateLabel("", 0, 0, $aSize[0], $aSize[1], $SS_GRAYFRAME) ; Creates a context menu $NoteGui[$n][4] = GUICtrlCreateContextMenu($NoteGui[$n][3]) ; MenuItem for the context menu "Copy to Clipboard" $NoteGui[$n][5] = GUICtrlCreateMenuItem("Copy to Clipboard" & @TAB & "ENTER", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_CopyToClipboard") ; MenuItem for the context menu "ID_cMenuShareX" $NoteGui[$n][6] = GUICtrlCreateMenuItem("Send to ShareX", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_ShareX") ; MenuItem for the context menu "Save as..." $NoteGui[$n][7] = GUICtrlCreateMenuItem("Save as...", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_SaveAs") ; MenuItem for the context menu "Open" $NoteGui[$n][8] = GUICtrlCreateMenuItem("Open", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_Open") ; separator GUICtrlCreateMenuItem("", $NoteGui[$n][4]) ; Check for Language (maximal 4) ; $NoteGui[0][11] = "ID_Lang1" ; $NoteGui[0][12] = "ID_Lang2" ; $NoteGui[0][13] = "ID_Lang3" ; $NoteGui[0][14] = "ID_Lang4" For $i = 0 To $iLanguagesCnt ;UBound($aSupportedLanguages) - 1 If $i > 4 Then ExitLoop ; MenuItem for the context menu "OCR - Language $i" $NoteGui[$n][11 + $i] = GUICtrlCreateMenuItem("OCR - " & $aSupportedLanguages[$i][1], $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_OCR_Lang_" & $i + 1) ;ConsoleWrite($i & " - Language: " & $aSupportedLanguages[$i][1] & " - " & $aSupportedLanguages[$i][0] & @CRLF) Next ; separator GUICtrlCreateMenuItem("", $NoteGui[$n][4]) ; MenuItem for the context menu "Close" $NoteGui[$n][15] = GUICtrlCreateMenuItem("Close" & @TAB & "DELETE", $NoteGui[$n][4]) GUICtrlSetOnEvent(-1, "cm_Close") ; Display the GUI. GUISetState(@SW_SHOW, $NoteGui[$n][0]) $NoteGui[$n][16] = GUICtrlCreateDummy() $NoteGui[$n][17] = GUICtrlCreateDummy() Local $aAccelKeys[2][2] = [["{DELETE}", $NoteGui[$n][16]], ["{ENTER}", $NoteGui[$n][17]]] GUISetAccelerators($aAccelKeys) GUICtrlSetOnEvent($NoteGui[$n][16], "cm_Close") GUICtrlSetOnEvent($NoteGui[$n][17], "cm_CopyToClipboard") Return $NoteGui[$n][0] EndFunc ;==>CreateNew_NoteGui ;---------------------------------------------------------------------------------------- Func SaveFileDlg($Active_title) ; Save file Dialog ; Create a constant variable in Local scope of the message to display in FileSaveDialog. Local Const $sMessage = "Choose a filename." ; Display a save dialog to select a file. Local $sFileSaveDialog = FileSaveDialog($sMessage, @ScriptDir & "\SET\", "image (*.jpg)", $FD_PATHMUSTEXIST) If @error Then ; Display the error message. MsgBox($MB_SYSTEMMODAL, "", "No file was saved.") Else ; Retrieve the filename from the filepath e.g. Example.jpg Local $sFileName = StringTrimLeft($sFileSaveDialog, StringInStr($sFileSaveDialog, "\", $STR_NOCASESENSEBASIC, -1)) ; Check if the extension .jpg is appended to the end of the filename. Local $iExtension = StringInStr($sFileName, ".", $STR_NOCASESENSEBASIC) ; If a period (dot) is found then check whether or not the extension is equal to .jpg If $iExtension Then ; If the extension isn't equal to .jpg then append to the end of the filepath. If Not (StringTrimLeft($sFileName, $iExtension - 1) = ".jpg") Then $sFileSaveDialog &= ".jpg" Else ; If no period (dot) was found then append to the end of the file. $sFileSaveDialog &= ".jpg" EndIf ; Display the saved file. ;ConsoleWrite("You saved the following file:" & @CRLF & $sFileSaveDialog & @CRLF) FileCopy($Active_title, $sFileSaveDialog, $FC_OVERWRITE + $FC_CREATEPATH) EndIf EndFunc ;==>SaveFileDlg ;---------------------------------------------------------------------------------------- Func NoteGui_Delete($hWnd) ; NoteGui_Delete For $i = 1 To $NoteGui[0][0] If $NoteGui[$i][0] = $hWnd Then _ArrayDelete($NoteGui, $i) $NoteGui[0][0] -= 1 ExitLoop EndIf Next EndFunc ;==>NoteGui_Delete ;---------------------------------------------------------------------------------------- Func PicToClip($Path) ; put image to clipboard (Thanks to @Nine) _GDIPlus_Startup() Local $hImage = _GDIPlus_ImageLoadFromFile($Path) Local $hBitmap1 = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) _GDIPlus_ImageDispose($hImage) Local $hBitmap2 = _WinAPI_CopyImage($hBitmap1, $IMAGE_BITMAP, 0, 0, $LR_COPYDELETEORG + $LR_COPYRETURNORG) _WinAPI_DeleteObject($hBitmap1) _GDIPlus_Shutdown() _ClipBoard_Open(0) _ClipBoard_Empty() _ClipBoard_SetDataEx($hBitmap2, $CF_BITMAP) _ClipBoard_Close() _WinAPI_DeleteObject($hBitmap2) EndFunc ;==>PicToClip ;---------------------------------------------------------------------------------------- Func PerformOCR($ImagePath, $lang = Default) ; perform ocr (Thanks to @Danyfirex) ;_GetTextFromFile($sFileName, $iBorder = 20, $dScale = 1, $sLanguageTagToUse = Default, $bUseOcrLine = False) Local $Result = _GetTextFromFile($ImagePath, 20, 1, $lang) Local $Msg = @CRLF & @CRLF & _StringRepeat(@TAB, 4) & "Copy to ClipBoard ?" Local $iMsgBoxAnswer = MsgBox(4, "OCR Result", $Result & $Msg) If $iMsgBoxAnswer = 6 Then ;Yes ClipPut($Result) ToolTip("The text was copied to the clipboard") Sleep(1000) ToolTip("") EndIf EndFunc ;==>PerformOCR ;---------------------------------------------------------------------------------------- Func TRAY_EVENT() ; TRAY_Event Switch @TRAY_ID ; Check the last tray item identifier. Case $TRAY_EVENT_PRIMARYDOUBLE, $TRAY_NewCapture NewCapture() Case $TRAY_ExitScript DllClose($hDLL) Exit EndSwitch EndFunc ;==>TRAY_EVENT ;---------------------------------------------------------------------------------------- Func GUI_EVENT() ; GUI_EVENT Select Case @GUI_CtrlId = $GUI_EVENT_RESIZED Local $aSize For $i = 1 To $NoteGui[0][0] If $NoteGui[$i][0] = @GUI_WinHandle Then $aSize = $NoteGui[$i][2] WinMove(@GUI_WinHandle, "", Default, Default, $aSize[0], $aSize[1]) ControlMove(@GUI_WinHandle, "", "Static1", 0, 0, $aSize[0], $aSize[1]) ControlMove(@GUI_WinHandle, "", "Static2", 0, 0, $aSize[0], $aSize[1]) ExitLoop EndIf Next EndSelect EndFunc ;==>GUI_EVENT ;---------------------------------------------------------------------------------------- Func cm_CopyToClipboard() ; ContextMenu "Copy to Clipboard" Local $Active_title = WinGetTitle(@GUI_WinHandle) ToolTip("Copied to clipboard") PicToClip($Active_title) Sleep(500) ToolTip("") EndFunc ;==>cm_CopyToClipboard ;---------------------------------------------------------------------------------------- Func cm_ShareX() ; ContextMenu "Send to ShareX"" Local $Active_title = WinGetTitle(@GUI_WinHandle) PicToClip($Active_title) Sleep(100) Local $strLen = StringLen(@ScriptDir & "\tmp\image_") If StringLeft($Active_title, $strLen) = @ScriptDir & "\tmp\image_" Then GUIDelete(@GUI_WinHandle) FileDelete($Active_title) NoteGui_Delete(@GUI_WinHandle) EndIf ShellExecute("C:\Program Files\ShareX\ShareX.exe", "-imageeditor ") ; ℹ️ Give your path * <- Local $hShareXImageEd = WinWait("[TITLE:ShareX - Image editor; REGEXPCLASS:WindowsForms10\.Window\..\.app\.0\..+_r\d+_ad1]", "", 2) While WinExists($hShareXImageEd) ControlClick($hShareXImageEd, "", "[NAME:btnLoadImageFromClipboard]") Sleep(300) WEnd $hShareXImageEd = WinWait("[TITLE:ShareX - Image editor; REGEXPCLASS:WindowsForms10\.Window\..\.app\.0\..+_r\d+_ad1]", "", 2) WinActivate($hShareXImageEd) WinSetState($hShareXImageEd, "", @SW_MAXIMIZE) EndFunc ;==>cm_ShareX ;---------------------------------------------------------------------------------------- Func cm_SaveAs() ; ContextMenu "Save as..." Local $Active_title = WinGetTitle(@GUI_WinHandle) SaveFileDlg($Active_title) EndFunc ;==>cm_SaveAs ;---------------------------------------------------------------------------------------- Func cm_Open() ; ContextMenu "Open" Local $Active_title = WinGetTitle(@GUI_WinHandle) ShellExecute($Active_title) EndFunc ;==>cm_Open ;---------------------------------------------------------------------------------------- Func cm_OCR_Lang_1() ; ContextMenu "OCR - Language 0" Local $Active_title = WinGetTitle(@GUI_WinHandle) PerformOCR($Active_title, $aSupportedLanguages[0][0]) EndFunc ;==>cm_OCR_Lang_1 ;---------------------------------------------------------------------------------------- Func cm_OCR_Lang_2() ; ContextMenu "OCR - Language 1" Local $Active_title = WinGetTitle(@GUI_WinHandle) If $iLanguagesCnt > 1 Then PerformOCR($Active_title, $aSupportedLanguages[1][0]) EndFunc ;==>cm_OCR_Lang_2 ;---------------------------------------------------------------------------------------- Func cm_OCR_Lang_3() ; ContextMenu "OCR - Language 2" Local $Active_title = WinGetTitle(@GUI_WinHandle) If $iLanguagesCnt > 2 Then PerformOCR($Active_title, $aSupportedLanguages[2][0]) EndFunc ;==>cm_OCR_Lang_3 ;---------------------------------------------------------------------------------------- Func cm_OCR_Lang_4() ; ContextMenu "OCR - Language 3" Local $Active_title = WinGetTitle(@GUI_WinHandle) If $iLanguagesCnt > 3 Then PerformOCR($Active_title, $aSupportedLanguages[3][0]) EndFunc ;==>cm_OCR_Lang_4 ;---------------------------------------------------------------------------------------- Func cm_Close() ; ContextMenu "Close" Local $Active_title = WinGetTitle(@GUI_WinHandle) Local $strLen = StringLen(@ScriptDir & "\tmp\image_") If StringLeft($Active_title, $strLen) = @ScriptDir & "\tmp\image_" Then GUIDelete(@GUI_WinHandle) FileDelete($Active_title) NoteGui_Delete(@GUI_WinHandle) ;ConsoleWrite("- WinClose " & @GUI_WinHandle & " & FileDelete " & $Active_title & @CRLF) EndIf EndFunc ;==>cm_Close ;---------------------------------------------------------------------------------------- Func _Array_Gui_display() ; *** Debug _ArrayDisplay($NoteGui) _ArrayDisplay($NoteGui, "$NoteGui") EndFunc ;==>_Array_Gui_display ; #FUNCTION# -------------------------------------------------------------------------------------------------------------------- ; Name...........: _GetTextFromFile ; Description ...: reading text from a picture file ; Syntax.........: _GetText($sFileName [, $iBorder = 20 [, $dScale = 1 [, $sLanguageTagToUse = Default [, $bUseOcrLine = False]]]]) ; Parameters ....: $sFileName Full path and extension of the image file ; $iBorder [optional] Draw a border araunt, The color is taken from first pixel ; $dScale [optional] Scale factor ; $sLanguageTagToUse [optional] Gets the language being used for text recognition ; $bUseOcrLine [optional] Represents a single line of text recognized by the OCR engine and returned as part of the OcrResult. ; Return value...: Success: Contains the String results of Optical Character Recognition (OCR). ; Failure: "" Empty String otherwise. ; On Error: false ; ; Author ........: ioa747 ; Notes .........: https://www.autoitscript.com/forum/topic/211521-ocr-from-a-small-area ;-------------------------------------------------------------------------------------------------------------------------------- Func _GetTextFromFile($sFileName, $iBorder = 20, $dScale = 1, $sLanguageTagToUse = Default, $bUseOcrLine = False) Local $hHBitmap, $hBitmap, $hImage, $hImageCtxt, $sOCRTextResult, $iBmpW, $iBmpH, $iBorderColor _GDIPlus_Startup() $hBitmap = _GDIPlus_BitmapCreateFromFile($sFileName) $iBmpW = $dScale * _GDIPlus_ImageGetWidth($hBitmap) $iBmpH = $dScale * _GDIPlus_ImageGetHeight($hBitmap) ; Add Border If $iBorder > 0 Then $iBorderColor = _GDIPlus_BitmapGetPixel($hBitmap, 1, 1) ;get pixel color from 1,1 $hImage = _GDIPlus_BitmapCreateFromScan0($iBmpW + (2 * $iBorder), $iBmpH + (2 * $iBorder)) ;create an empty bitmap If @error Then Return SetError(3, 0, False) $hImageCtxt = _GDIPlus_ImageGetGraphicsContext($hImage) ;get the graphics context of the bitmap _GDIPlus_GraphicsSetSmoothingMode($hImageCtxt, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hImageCtxt, $iBorderColor) ;clear bitmap with color white _GDIPlus_GraphicsDrawImage($hImageCtxt, $hBitmap, $iBorder, $iBorder) _GDIPlus_ImageDispose($hBitmap) Else $hImage = $hBitmap EndIf $sOCRTextResult = _UWPOCR_GetText($hImage, $sLanguageTagToUse, $bUseOcrLine) If @error Then Return SetError(4, 0, False) _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hImage) _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_Shutdown() Return $sOCRTextResult EndFunc ;==>_GetTextFromFile ;-------------------------------------------------------------------------------------------------------------------------------- Snipe new note Double Click the tray icon to start NewCapture or While Left Windows Key IsPressed, tap 2 times the Left Shift key (is useful when Capture menu or context menu). While start NewCapture point click anywhere to escape. (Does not catch smaller than 9*9 px) While start NewCapture escape with ESC Please, every comment is appreciated! leave your comments and experiences here! Thank you very much Edited March 31 by ioa747 UpDate to 0.0.2.20240331 AutoBert, Danyfirex and argumentum 1 2 I know that I know nothing Link to comment Share on other sites More sharing options...
argumentum Posted March 31 Share Posted March 31 (edited) My keyboard does not have a RWin key, so I set it to the left side of the keyboard. In any case is better for me as I hold the mouse on my right hand. Even as I type this I should let go of the mouse but I don't. Now my mouse aside, this script is just beautiful. This is soooo nice. Like, so very nice And, this I'll use daily to get a memory aid for my daily's. Used to use printscreen and paint. This is cool. Spoiler Again, very nice !. Edit: #NoTrayIcon ... ... If WinExists(StringTrimRight(@ScriptName, 4) & "_STUB") Then Exit 5 AutoItWinSetTitle(StringTrimRight(@ScriptName, 4) & "_STUB") If @AutoItX64 Then Exit MsgBox(262144 + 64, StringTrimRight(@ScriptName, 4), "Please run as 32bit", 60) ... ... TraySetClick(16) ; $TRAY_CLICK_SECONDARYUP = 16 ... ... Switch @TRAY_ID ; Check the last tray item identifier. Case $TRAY_EVENT_PRIMARYDOUBLE, $TRAY_NewCapture ; <-- that works too NewCapture() ... ... adding those makes it better. Edited March 31 by argumentum nicer than nice ioa747 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
argumentum Posted March 31 Share Posted March 31 (edited) I have a complain. Take your own monitor and set a scale to something greater than 100% and you'll see that the capture is not working as it should. Edit #2: Run as x86. x64 fails as coded. Edit #3: We saw this before. Edited March 31 by argumentum ioa747 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
ioa747 Posted March 31 Author Share Posted March 31 @argumentum I'm glad you like it, I enjoyed it too Thank you very much for your useful suggestions. argumentum 1 I know that I know nothing Link to comment Share on other sites More sharing options...
ioa747 Posted March 31 Author Share Posted March 31 UpDate both Editions I added all of @argumentum suggestions and it got better ! argumentum 1 I know that I know nothing Link to comment Share on other sites More sharing options...
Acts432 Posted September 20 Share Posted September 20 Solution without accessing drive (except of running tesseract.exe). Whole operation is processed in memory. OCRScreenCaptureToText.au3 expandcollapse popup;#Include <WinAPI.au3> #include <WinAPISys.au3> #include <WindowsConstants.au3> ;#include <WinAPIvkeysConstants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <Memory.au3> #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 --- ioa747 and argumentum 2 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now