Jump to content

ioa747
 Share

Recommended Posts

SmartNote.png  SmartNote tesseract  Edition:

SmartNote is a screen snip tool to snip screen area with OCR ability from tesseract  100+ languages

230926-045455-977_SciTE_tVhrE.png

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

; 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 by ioa747
UpDate to 0.0.5.20240413

I know that I know nothing

Link to comment
Share on other sites

  • ioa747 changed the title to SmartNote
Posted (edited)

SmartNote.png  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

; 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 by ioa747
UpDate to 0.0.2.20240331

I know that I know nothing

Link to comment
Share on other sites

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

image.png.c4217812fcf593d8ef324144295f8f81.png  image.png.021868feecae7ee4cd68c1e325b60cde.png

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 by argumentum
nicer than nice

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

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 by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

  • 5 months later...

Solution without accessing drive (except of running tesseract.exe).

Whole operation is processed in memory.

OCRScreenCaptureToText.au3

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

 

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...