Hashim Posted November 6 Share Posted November 6 (edited) I'm working with a proprietary in-house tool that takes a 6-digit serial number and displays 3-digit output (actually it expects a 7-digit input but the first digit is a check digit that it isn't necessary to change for my purposes). I've been tasked with outputting 1 million serial number inputs in the range 000000-999999 to a CSV file with their corresponding outputs. Thanks to ioa747 I now have a bitmap-based solution that accurately detects the output from the application for this purpose, which I've wrapped in a (non-Functional but perfectly functional) loop. The whole script works without issue except for a really weird bug that throws a fatal but completely empty error on the 9964th (or possibly 9965th) iteration of the loop. I've reproduced this at least 6 times while incrementing the start of the loop each time (and successfully written the first ~60,000 lines to the file in this way), so the problem is definitely the nth iteration of the loop rather than any particular serial number. Adding a file exists condition prevents the program from crashing with the useless error, so this tells me the issue is the GDI functions suddenly not saving screenshots, maybe because of memory usage, but all the functions using GDI seem to have clean up functions and the system I'm working on has 16GB of RAM, so I'd be surprised if it's running out unless there's a memory leak somewhere. Also, at its current rate the script will take a few days to output the entire dataset, so I'd also welcome any optimisations that anyone can think of to make it more efficient. Here's the code for my own script, which also contains ioa747's custom _ScreenCapture function: expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.16.1 Author: Hashim Script Function: Template AutoIt script. #ce ---------------------------------------------------------------------------- #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <ScreenCapture.au3> #include <WindowsConstants.au3> #include "UWPOCR.au3" ; * <-"https://www.autoitscript.com/forum/topic/207324-uwpocr-windows-platform-optical-character-recognition-api-implementation" #include "Bitmap Digit Identifier.au3" ; https://www.autoitscript.com/forum/topic/211521-ocr-from-a-small-area/?do=findComment&comment=1538057 Run("Tool.exe"); Local $tool = WinWaitActive("Tool", "", 3) ControlClick($tool, "", "TTabSheet1", "primary", 1, 210, 50) ControlCommand($tool, "" , "TFlatComboBox1" , "SelectString" , "Old") $db = FileOpen(@ScriptDir & "\tool-db.txt", 1) DirRemove ("Bitmap ID Failed", 1) DirCreate ("Bitmap ID Failed") For $loop = 0 To 999999 $serial = StringFormat('%06i', $loop) ControlSetText($tool, "", "TFlatMaskEdit3", "S.N: 9" & $serial) ; Enter serial number prefixed with the check digit ControlClick($tool, "", "TTabSheet1", "primary", 1, 69, 50) ; Press "Generate" $sImageResult = _ScreenCapture(@ScriptDir & "\Bitmap ID Failed\" & $serial & ".png", 792, 450, 927, 480) If Not FileExists($sImageResult) Then MsgBox(0, "Error encountered...", "No image found for serial of " & $serial) Exit EndIf Local $code = _GetNumber($sImageResult) If (StringLen($code) = 3 or StringIsDigit($code)) Then FileDelete($sImageResult) FileWrite($db, $serial & "," & $output & @LF) Next FileClose($db) ; #FUNCTION# -------------------------------------------------------------------------------------------------------------------- ; Name...........: _ScreenCapture ; Description ...: Captures a region of the screen ; Syntax.........: _ScreenCapture($sFileName [, $iLeft = 0 [, $iTop = 0 [, $iRight = -1 [, $iBottom = -1 [, $iNegative = 0 [, $iBorder = 0 [, $dScale = 1 [, $iBrightness = 0 [, $iContrast = 0]]]]]]]]]) ; Parameters ....: $sFileName Full path and extension of the image file ; $iLeft [optional] X coordinate of the upper left corner of the rectangle ; $iTop [optional] Y coordinate of the upper left corner of the rectangle ; $iRight [optional] X coordinate of the lower right corner of the rectangle. If this is -1, the current screen width will be used ; $iBottom [optional] Y coordinate of the lower right corner of the rectangle. If this is -1, the current screen height will be used. ; $iNegative [optional] 1 = Negative color, 0 = Normal color ; $iBorder [optional] Draw a border araunt, The color is taken from first pixel ; $dScale [optional] Scale factor ; $iBrightness [optional] Integer in the range -255 through 255 that specifies the brightness level. ; $iContrast [optional] Integer in the range -100 through 100 that specifies the contrast level. ; Return value...: Filepath of the image If the image is successfully saved. ; False If the image is Not successfully saved. ; ; Author ........: ; Notes .........: ;-------------------------------------------------------------------------------------------------------------------------------- Func _ScreenCapture($sFileName, $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $iNegative = 0, $iBorder = 0, $dScale = 1, $iBrightness = 0, $iContrast = 0) Local $hHBitmap, $hBitmap, $hImage, $hImageCtxt, $vRet, $iBmpW, $iBmpH, $iBorderColor _GDIPlus_Startup() $hHBitmap = _ScreenCapture_Capture("", $iLeft, $iTop, $iRight, $iBottom, False) If @error Then Return SetError(1, 0, False) Local $tSIZE = _WinAPI_GetBitmapDimension($hHBitmap) $iBmpW = $dScale * DllStructGetData($tSIZE, 'X') $iBmpH = $dScale * DllStructGetData($tSIZE, 'Y') ;Default ;$iFlags=0,$iIlluminant=0,$iGammaR=10000,$iGammaG=10000,$iGammaB=10000,$iBlack=0,$iWhite=10000,$iContrast=0,$iBrightness=0,$iColorfulness=0,$iTint=0 Local $iIlluminant = 0, $iGammaR = 10000, $iGammaG = 10000, $iGammaB = 10000, $iBlack = 0, $iWhite = 10000, $iColorfulness = 0, $iTint = 0 Local $tAdj = 0 $tAdj = _WinAPI_CreateColorAdjustment($iNegative, $iIlluminant, $iGammaR, $iGammaG, $iGammaB, $iBlack, $iWhite, $iContrast, $iBrightness, $iColorfulness, $iTint) $hBitmap = _WinAPI_AdjustBitmap($hHBitmap, $iBmpW, $iBmpH, $HALFTONE, $tAdj) If @error Then Return SetError(2, 0, False) $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($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 $vRet = _GDIPlus_ImageSaveToFile($hImage, $sFileName) ;save bitmap to disk If @error Then Return SetError(4, 0, False) If $vRet Then $vRet = $sFileName _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hImage) _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_GraphicsDispose($hImageCtxt) _GDIPlus_Shutdown() Return $vRet EndFunc ;==>_ScreenCapture ; #FUNCTION# -------------------------------------------------------------------------------------------------------------------- ; Name...........: _GetText ; Description ...: reading text from a region of the screen ; Syntax.........: _GetText([$iLeft = 0 [, $iTop = 0 [, $iRight = -1 [, $iBottom = -1 [, $iNegative = 0 [, $iBorder = 0 [, $dScale = 1 [, $iBrightness = 0 [, $iContrast = 0 [, $sLanguageTagToUse = Default [, $bUseOcrLine = False]]]]]]]]]]]) ; Parameters ....: $iLeft [optional] X coordinate of the upper left corner of the rectangle ; $iTop [optional] Y coordinate of the upper left corner of the rectangle ; $iRight [optional] X coordinate of the lower right corner of the rectangle. If this is -1, the current screen width will be used ; $iBottom [optional] Y coordinate of the lower right corner of the rectangle. If this is -1, the current screen height will be used. ; $iNegative [optional] 1 = Negative color, 0 = Normal color ; $iBorder [optional] Draw a border araunt, The color is taken from first pixel ; $dScale [optional] Scale factor ; $iBrightness [optional] Integer in the range -255 through 255 that specifies the brightness level. ; $iContrast [optional] Integer in the range -100 through 100 that specifies the contrast level. ; $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 results of Optical Character Recognition (OCR). ; Failure: "" Empty String otherwise. ; On Error: false ; ; Author ........: ; Notes .........: ;-------------------------------------------------------------------------------------------------------------------------------- Exit And here is ioa747's bitmap script, it's basically untouched except I removed the test() and main() functions, instead I just call _getNumber() directly from within my loop above. expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.16.1 Author: ioa747 (https://www.autoitscript.com/forum/topic/211521-ocr-from-a-small-area/?do=findComment&comment=1538057) Version: 4.0 Script Function: Template AutoIt script. #ce ---------------------------------------------------------------------------- #include <GDIPlus.au3> #include <Array.au3> #include <File.au3> ;-------------------------------------------------------------------------------------------------------------------------------- Func _GetNumber($sFileName, $hColor = 0x00FF00) ; Main Program ; Capture the color map for the specified area Local $aColorMap = CaptureAreaColorMap($sFileName) ;~ _ArrayDisplay($aColorMap) Local $Result = FindNumberUsingColorMap($aColorMap, $hColor) ;~ MsgBox($MB_SYSTEMMODAL, "$Result", $Result) Return $Result EndFunc ;==>_GetNumber ;-------------------------------------------------------------------------------------------------------------------------------- Func CaptureAreaColorMap($sFileName) ; create color map array ; Initialize GDI+ to work with bitmaps _GDIPlus_Startup() ; Capture the screen area as a bitmap Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sFileName) ; Get the width and height of the captured area Local $width = _GDIPlus_ImageGetWidth($hBitmap) Local $height = _GDIPlus_ImageGetHeight($hBitmap) ;~ ConsoleWrite("Image: $width=" & $width & ", $height=" & $height & @CRLF) ; Create an array to store color values Local $aColorMap[$width][$height] ; Loop through each pixel in the bitmap and retrieve its color For $y = 0 To $height - 1 For $x = 0 To $width - 1 ; Get the pixel color from the bitmap in ARGB format Local $argbColor = _GDIPlus_BitmapGetPixel($hBitmap, $x, $y) ; Convert ARGB to BGR for comparison (ignore the alpha channel) Local $bgrColor = BitAND($argbColor, 0x00FFFFFF) $aColorMap[$x][$y] = $bgrColor Next Next ; Cleanup resources _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_Shutdown() Return $aColorMap EndFunc ;==>CaptureAreaColorMap ;-------------------------------------------------------------------------------------------------------------------------------- Func FindNumberUsingColorMap($aColorMap, $hColor = 0x00FF00) ; find number in color map array Local $width = UBound($aColorMap, 1) Local $height = UBound($aColorMap, 2) Local $firstRow = -1, $lastRow = -1, $firstCol = -1, $lastCol = -1 ; Scan for the first and last rows and columns with $hColor pixels For $y = 0 To $height - 1 For $x = 0 To $width - 1 If $aColorMap[$x][$y] = $hColor Then If $firstRow = -1 Then $firstRow = $y $lastRow = $y If $firstCol = -1 Or $x < $firstCol Then $firstCol = $x If $lastCol = -1 Or $x > $lastCol Then $lastCol = $x EndIf Next Next If $firstRow = -1 Or $lastRow = -1 Or $firstCol = -1 Or $lastCol = -1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "No color found" & @TAB & @TAB) Exit EndIf ; each number Display is a matrix of 14x20 pixels Local $numberWidth = 14 ; set number width per digit Local $numberSpace = 2 ; set Space between digits Local $Empty = 0, $Corection = 0 ; Corection for boundaries if 1st digit = 1 For $x = $firstCol To $lastCol - 1 If $aColorMap[$x][$firstRow] = 0x000000 Then $Empty += 1 If $Empty = 3 Then ;found 1st Space between digits $Corection = $firstCol - 1 - Abs($x - $numberWidth - $numberSpace) ExitLoop EndIf Else $Empty = 0 EndIf Next If $Corection > 0 Then $firstCol = $firstCol - $Corection Local $numberStart = $firstCol ;~ ConsoleWrite("$Corection=" & $Corection & @CRLF) ;~ ConsoleWrite("Display_boundaries firstRow:" & $firstRow & " lastRow:" & $lastRow & " firstCol:" & $firstCol & " lastCol:" & $lastCol & @CRLF) ;~ ConsoleWrite("" & @CRLF) Local $aNum[11][3] ; Define boundaries for each number position For $i = 1 To 10 $aNum[$i][0] = $numberStart $aNum[$i][1] = $numberStart + $numberWidth If $numberStart + $numberWidth + $numberSpace > $lastCol Then ExitLoop $numberStart += $numberWidth + $numberSpace $aNum[0][0] = $i + 1 Next Local $sNumber ; Generate patterns for each found number For $i = 1 To $aNum[0][0] Local $sPattern = "" For $y = $firstRow To $lastRow For $x = $aNum[$i][0] To $aNum[$i][1] - 1 If $aColorMap[$x][$y] = $hColor Then $sPattern &= "1" Else $sPattern &= "." EndIf Next $sPattern &= @CRLF Next $sNumber &= _GetPattern($sPattern) Next Return $sNumber EndFunc ;==>FindNumberUsingColorMap ;-------------------------------------------------------------------------------------------------------------------------------- Func _GetPattern($sPattern) ; patterns for each digit ;~ ConsoleWrite("**************" & @CRLF & $sPattern & @CRLF) Local $aNumber[10] ; Define simplified patterns for each digit $aNumber[0] = "" ; Pattern for '0' $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11.......11.11" & @CRLF $aNumber[0] &= "11.......11.11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11....11....11" & @CRLF $aNumber[0] &= "11....11....11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11.11.......11" & @CRLF $aNumber[0] &= "11.11.......11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[1] = "" ; Pattern for '1' $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "...11.11......" & @CRLF $aNumber[1] &= "...11.11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "...11.11.11..." & @CRLF $aNumber[1] &= "...11.11.11..." & @CRLF $aNumber[2] = "" ; Pattern for '2' $aNumber[2] &= "...11.11.11..." & @CRLF $aNumber[2] &= "...11.11.11..." & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "11..........11" & @CRLF $aNumber[2] &= "11..........11" & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "............11" & @CRLF $aNumber[2] &= "............11" & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "......11.11..." & @CRLF $aNumber[2] &= "......11.11..." & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "...11........." & @CRLF $aNumber[2] &= "...11........." & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "11............" & @CRLF $aNumber[2] &= "11............" & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "11.11.11.11.11" & @CRLF $aNumber[2] &= "11.11.11.11.11" & @CRLF $aNumber[3] = "" ; Pattern for '3' $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "......11.11..." & @CRLF $aNumber[3] &= "......11.11..." & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[4] = "" ; Pattern for '4' $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "......11.11..." & @CRLF $aNumber[4] &= "......11.11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "...11....11..." & @CRLF $aNumber[4] &= "...11....11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "11.......11..." & @CRLF $aNumber[4] &= "11.......11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "11.11.11.11.11" & @CRLF $aNumber[4] &= "11.11.11.11.11" & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[5] = "" ; Pattern for '5' $aNumber[5] &= "11.11.11.11.11" & @CRLF $aNumber[5] &= "11.11.11.11.11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "11............" & @CRLF $aNumber[5] &= "11............" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "11.11.11.11..." & @CRLF $aNumber[5] &= "11.11.11.11..." & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "11..........11" & @CRLF $aNumber[5] &= "11..........11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "...11.11.11..." & @CRLF $aNumber[5] &= "...11.11.11..." & @CRLF $aNumber[6] = "" ; Pattern for '6' $aNumber[6] &= "......11.11..." & @CRLF $aNumber[6] &= "......11.11..." & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "...11........." & @CRLF $aNumber[6] &= "...11........." & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11............" & @CRLF $aNumber[6] &= "11............" & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11.11.11.11..." & @CRLF $aNumber[6] &= "11.11.11.11..." & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "...11.11.11..." & @CRLF $aNumber[6] &= "...11.11.11..." & @CRLF $aNumber[7] = "" ; Pattern for '7' $aNumber[7] &= "11.11.11.11.11" & @CRLF $aNumber[7] &= "11.11.11.11.11" & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "............11" & @CRLF $aNumber[7] &= "............11" & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= ".........11..." & @CRLF $aNumber[7] &= ".........11..." & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "......11......" & @CRLF $aNumber[7] &= "......11......" & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[8] = "" ; Pattern for '8' $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[9] = "" ; Pattern for '9' $aNumber[9] &= "...11.11.11..." & @CRLF $aNumber[9] &= "...11.11.11..." & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "...11.11.11.11" & @CRLF $aNumber[9] &= "...11.11.11.11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "............11" & @CRLF $aNumber[9] &= "............11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= ".........11..." & @CRLF $aNumber[9] &= ".........11..." & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "...11.11......" & @CRLF $aNumber[9] &= "...11.11......" & @CRLF Switch $sPattern Case $aNumber[0] Return 0 Case $aNumber[1] Return 1 Case $aNumber[2] Return 2 Case $aNumber[3] Return 3 Case $aNumber[4] Return 4 Case $aNumber[5] Return 5 Case $aNumber[6] Return 6 Case $aNumber[7] Return 7 Case $aNumber[8] Return 8 Case $aNumber[9] Return 9 Case Else Return SetError(1, 0, "") EndSwitch EndFunc ;==>_GetPattern Edited November 6 by Hashim Link to comment Share on other sites More sharing options...
Werty Posted November 6 Share Posted November 6 Could you post a screenshot of Tools.exe, so we can see what it looks like. (blur out any secrets). Shouldnt be necessary with all the screengrab, files and color conversions, or checking for the whole pattern of each number, instead of just a small unique part. But please, screenshot of tools.exe. Some guy's script + some other guy's script = my script! Link to comment Share on other sites More sharing options...
Nine Posted November 6 Share Posted November 6 Something looks wrong in the _ScreenCapture. You are reusing the same variable for 2 different purposes (without cleaning up the memory) : Here : $hBitmap = _WinAPI_AdjustBitmap($hHBitmap, $iBmpW, $iBmpH, $HALFTONE, $tAdj) and there : $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) That must create major memory leak, IMO. Hashim and ioa747 2 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
argumentum Posted November 7 Share Posted November 7 (edited) For $n = 0 To 100 $aProcessMemoryInfo = _WinAPI_GetProcessMemoryInfo() ConsoleWrite( _GetNumber(@ScriptDir & "\code__51" & StringRight($n, 1) & "___.png") & @TAB & 'The peak working set: ' & $aProcessMemoryInfo[1] / 1024 / 1024 & ' MB'& @CRLF) Next expandcollapse popup510 The peak working set: 29.23046875 MB 511 The peak working set: 30.31640625 MB 512 The peak working set: 30.4375 MB 513 The peak working set: 30.47265625 MB 514 The peak working set: 30.484375 MB 515 The peak working set: 30.5 MB 516 The peak working set: 30.50390625 MB 517 The peak working set: 30.5078125 MB 518 The peak working set: 30.515625 MB 519 The peak working set: 30.5234375 MB 510 The peak working set: 30.5234375 MB 511 The peak working set: 30.5234375 MB 512 The peak working set: 30.53125 MB 513 The peak working set: 30.53125 MB 514 The peak working set: 30.54296875 MB 515 The peak working set: 30.54296875 MB 516 The peak working set: 30.546875 MB 517 The peak working set: 30.5546875 MB 518 The peak working set: 30.5546875 MB 519 The peak working set: 30.5546875 MB 510 The peak working set: 30.5546875 MB 511 The peak working set: 30.5546875 MB 512 The peak working set: 30.5546875 MB 513 The peak working set: 30.5546875 MB 514 The peak working set: 30.5546875 MB 515 The peak working set: 30.5546875 MB 516 The peak working set: 30.5546875 MB 517 The peak working set: 30.5546875 MB 518 The peak working set: 30.5546875 MB 519 The peak working set: 30.5546875 MB 510 The peak working set: 30.5546875 MB 511 The peak working set: 30.5546875 MB 512 The peak working set: 30.5703125 MB 513 The peak working set: 30.57421875 MB 514 The peak working set: 30.57421875 MB 515 The peak working set: 30.578125 MB 516 The peak working set: 30.578125 MB 517 The peak working set: 30.59375 MB 518 The peak working set: 30.59375 MB 519 The peak working set: 30.59375 MB 510 The peak working set: 30.59375 MB 511 The peak working set: 30.59375 MB 512 The peak working set: 30.59375 MB 513 The peak working set: 30.59375 MB 514 The peak working set: 30.59375 MB 515 The peak working set: 30.59375 MB 516 The peak working set: 30.59375 MB 517 The peak working set: 30.59375 MB 518 The peak working set: 30.59375 MB 519 The peak working set: 30.59375 MB 510 The peak working set: 30.59765625 MB 511 The peak working set: 30.59765625 MB 512 The peak working set: 30.6015625 MB 513 The peak working set: 30.6015625 MB 514 The peak working set: 30.6015625 MB 515 The peak working set: 30.6015625 MB 516 The peak working set: 30.609375 MB 517 The peak working set: 30.61328125 MB 518 The peak working set: 30.62109375 MB 519 The peak working set: 30.62109375 MB 510 The peak working set: 30.625 MB 511 The peak working set: 30.62890625 MB 512 The peak working set: 30.62890625 MB 513 The peak working set: 30.63671875 MB 514 The peak working set: 30.640625 MB 515 The peak working set: 30.640625 MB 516 The peak working set: 30.64453125 MB 517 The peak working set: 30.65234375 MB 518 The peak working set: 30.65234375 MB 519 The peak working set: 30.65234375 MB 510 The peak working set: 30.671875 MB 511 The peak working set: 30.68359375 MB 512 The peak working set: 30.6875 MB 513 The peak working set: 30.6875 MB 514 The peak working set: 30.69140625 MB 515 The peak working set: 30.6953125 MB 516 The peak working set: 30.6953125 MB 517 The peak working set: 30.6953125 MB 518 The peak working set: 30.6953125 MB 519 The peak working set: 30.6953125 MB 510 The peak working set: 30.6953125 MB 511 The peak working set: 30.6953125 MB 512 The peak working set: 30.6953125 MB 513 The peak working set: 30.6953125 MB 514 The peak working set: 30.6953125 MB 515 The peak working set: 30.6953125 MB 516 The peak working set: 30.6953125 MB 517 The peak working set: 30.6953125 MB 518 The peak working set: 30.6953125 MB 519 The peak working set: 30.6953125 MB 510 The peak working set: 30.6953125 MB 511 The peak working set: 30.6953125 MB 512 The peak working set: 30.6953125 MB 513 The peak working set: 30.6953125 MB 514 The peak working set: 30.6953125 MB 515 The peak working set: 30.6953125 MB 516 The peak working set: 30.6953125 MB 517 The peak working set: 30.6953125 MB 518 The peak working set: 30.6953125 MB 519 The peak working set: 30.6953125 MB 510 The peak working set: 30.6953125 MB ..in just 100 _GetNumber() the memory increases 2 MB. It's got sporadic jumps in memory usage ? Edited November 7 by argumentum reviewed Hashim 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...
Hashim Posted November 7 Author Share Posted November 7 3 hours ago, Werty said: Could you post a screenshot of Tools.exe, so we can see what it looks like. (blur out any secrets). Shouldnt be necessary with all the screengrab, files and color conversions, or checking for the whole pattern of each number, instead of just a small unique part. But please, screenshot of tools.exe. Unfortunately not, I've already revealed too much just to get this working and the client is known to be litigious so I'd rather not risk that. However I don't think a screenshot of the application is needed to fix this issue as the issue doesn't lie elsewhere in the application - the necessary part of it is being screenshotted fine right up until the moment it's not. I've also verified the loop carries on without issue when not taking screenshots, so it seems increasingly likely the issue is GDI failing to take/save a screenshot on the 9664th iteration. The current version is actually not doing any colour conversions or scaling so I don't actually need that custom function anymore, I've decided to replace it with the underlying _ScreenCapture UDF. It's true a memory-only solution that doesn't save every image to the filesystem would be a lot faster, but it will probably be easier to get it working this way first before refactoring to an even more memory-intensive version. 3 hours ago, Nine said: Something looks wrong in the _ScreenCapture. You are reusing the same variable for 2 different purposes (without cleaning up the memory) : Here : $hBitmap = _WinAPI_AdjustBitmap($hHBitmap, $iBmpW, $iBmpH, $HALFTONE, $tAdj) and there : $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) That must create major memory leak, IMO. Good shout, unfortunately changing the first one to $hBitmapAdj and replacing the reference on the second line still doesn't fix this, so it doesn't look like the 9664 bug is being caused by this. However I have now removed that custom function entirely so that should simplify things quite a bit. Link to comment Share on other sites More sharing options...
Hashim Posted November 7 Author Share Posted November 7 (edited) 49 minutes ago, argumentum said: For $n = 0 To 100 $aProcessMemoryInfo = _WinAPI_GetProcessMemoryInfo() ConsoleWrite( _GetNumber(@ScriptDir & "\code__51" & StringRight($n, 1) & "___.png") & @TAB & 'The peak working set: ' & $aProcessMemoryInfo[1] / 1024 / 1024 & ' MB'& @CRLF) Next expandcollapse popup510 The peak working set: 29.23046875 MB 511 The peak working set: 30.31640625 MB 512 The peak working set: 30.4375 MB 513 The peak working set: 30.47265625 MB 514 The peak working set: 30.484375 MB 515 The peak working set: 30.5 MB 516 The peak working set: 30.50390625 MB 517 The peak working set: 30.5078125 MB 518 The peak working set: 30.515625 MB 519 The peak working set: 30.5234375 MB 510 The peak working set: 30.5234375 MB 511 The peak working set: 30.5234375 MB 512 The peak working set: 30.53125 MB 513 The peak working set: 30.53125 MB 514 The peak working set: 30.54296875 MB 515 The peak working set: 30.54296875 MB 516 The peak working set: 30.546875 MB 517 The peak working set: 30.5546875 MB 518 The peak working set: 30.5546875 MB 519 The peak working set: 30.5546875 MB 510 The peak working set: 30.5546875 MB 511 The peak working set: 30.5546875 MB 512 The peak working set: 30.5546875 MB 513 The peak working set: 30.5546875 MB 514 The peak working set: 30.5546875 MB 515 The peak working set: 30.5546875 MB 516 The peak working set: 30.5546875 MB 517 The peak working set: 30.5546875 MB 518 The peak working set: 30.5546875 MB 519 The peak working set: 30.5546875 MB 510 The peak working set: 30.5546875 MB 511 The peak working set: 30.5546875 MB 512 The peak working set: 30.5703125 MB 513 The peak working set: 30.57421875 MB 514 The peak working set: 30.57421875 MB 515 The peak working set: 30.578125 MB 516 The peak working set: 30.578125 MB 517 The peak working set: 30.59375 MB 518 The peak working set: 30.59375 MB 519 The peak working set: 30.59375 MB 510 The peak working set: 30.59375 MB 511 The peak working set: 30.59375 MB 512 The peak working set: 30.59375 MB 513 The peak working set: 30.59375 MB 514 The peak working set: 30.59375 MB 515 The peak working set: 30.59375 MB 516 The peak working set: 30.59375 MB 517 The peak working set: 30.59375 MB 518 The peak working set: 30.59375 MB 519 The peak working set: 30.59375 MB 510 The peak working set: 30.59765625 MB 511 The peak working set: 30.59765625 MB 512 The peak working set: 30.6015625 MB 513 The peak working set: 30.6015625 MB 514 The peak working set: 30.6015625 MB 515 The peak working set: 30.6015625 MB 516 The peak working set: 30.609375 MB 517 The peak working set: 30.61328125 MB 518 The peak working set: 30.62109375 MB 519 The peak working set: 30.62109375 MB 510 The peak working set: 30.625 MB 511 The peak working set: 30.62890625 MB 512 The peak working set: 30.62890625 MB 513 The peak working set: 30.63671875 MB 514 The peak working set: 30.640625 MB 515 The peak working set: 30.640625 MB 516 The peak working set: 30.64453125 MB 517 The peak working set: 30.65234375 MB 518 The peak working set: 30.65234375 MB 519 The peak working set: 30.65234375 MB 510 The peak working set: 30.671875 MB 511 The peak working set: 30.68359375 MB 512 The peak working set: 30.6875 MB 513 The peak working set: 30.6875 MB 514 The peak working set: 30.69140625 MB 515 The peak working set: 30.6953125 MB 516 The peak working set: 30.6953125 MB 517 The peak working set: 30.6953125 MB 518 The peak working set: 30.6953125 MB 519 The peak working set: 30.6953125 MB 510 The peak working set: 30.6953125 MB 511 The peak working set: 30.6953125 MB 512 The peak working set: 30.6953125 MB 513 The peak working set: 30.6953125 MB 514 The peak working set: 30.6953125 MB 515 The peak working set: 30.6953125 MB 516 The peak working set: 30.6953125 MB 517 The peak working set: 30.6953125 MB 518 The peak working set: 30.6953125 MB 519 The peak working set: 30.6953125 MB 510 The peak working set: 30.6953125 MB 511 The peak working set: 30.6953125 MB 512 The peak working set: 30.6953125 MB 513 The peak working set: 30.6953125 MB 514 The peak working set: 30.6953125 MB 515 The peak working set: 30.6953125 MB 516 The peak working set: 30.6953125 MB 517 The peak working set: 30.6953125 MB 518 The peak working set: 30.6953125 MB 519 The peak working set: 30.6953125 MB 510 The peak working set: 30.6953125 MB ..in just 100 _GetNumber() the memory increases 2 MB. It's got sporadic jumps in memory usage ? Thanks for this, these results look stable to me but I suppose that's expected for a simple loop. I'll implement in my own loop after all the GDI disposal and see what the results look like. Edited November 7 by Hashim Link to comment Share on other sites More sharing options...
Nine Posted November 7 Share Posted November 7 (edited) 51 minutes ago, Hashim said: unfortunately changing the first one to $hBitmapAdj and replacing the reference on the second line still doesn't fix this You need to delete the object otherwise it is just as useless as using the same variable ps. next time, post a runable script that we actually can run that shows the issue, otherwise it is just a guessing game Edited November 7 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Hashim Posted November 7 Author Share Posted November 7 21 minutes ago, Nine said: You need to delete the object otherwise it is just as useless as using the same variable ps. next time, post a runable script that we actually can run that shows the issue, otherwise it is just a guessing game Good point, I completely forgot about disposal. This may well have been the issue as I've just tested again after replacing the _GetCapture wrapper function with using _ScreenCapture directly, and have managed to successfully get past 15,000 iterations! Either way it seems the bug was somewhere in that wrapper function, which isn't surprising since ioa747 didn't write it with this level of abuse in mind, but good to know anyway for anyone that does actually need its scaling and adjustment functions. Link to comment Share on other sites More sharing options...
ioa747 Posted November 7 Share Posted November 7 (edited) if the "\Bitmap ID Failed\" folder is placed on a ram drive the process will speed up significantly expandcollapse popup; Version: 5.0 #include <GDIPlus.au3> #include <Array.au3> #include <File.au3> ;~ Local $Result = _GetNumber(@ScriptDir & "\100num\152.png") ;~ MsgBox($MB_SYSTEMMODAL, "_GetNumber", $Result) Test() ;-------------------------------------------------------------------------------------------------------------------------------- Func _Exit() ; Cleanup & exit ; Cleanup resources _GDIPlus_Shutdown() Exit EndFunc ;-------------------------------------------------------------------------------------------------------------------------------- Func _GetNumber($sFileName, $hColor = 0x00FF00) ; Main Program ; Initialize GDI+ to work with bitmaps _GDIPlus_Startup() ; Capture the color map for the specified area Local $aColorMap = CaptureAreaColorMap($sFileName) If @error = 1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "Path was invalid.") _Exit() EndIf ;~ _ArrayDisplay($aColorMap) Local $Result = FindNumberUsingColorMap($aColorMap, $hColor) ;~ MsgBox($MB_SYSTEMMODAL, "$Result", $Result) ; Cleanup resources _GDIPlus_Shutdown() Return $Result EndFunc ;==>_GetNumber ;-------------------------------------------------------------------------------------------------------------------------------- Func CaptureAreaColorMap($sFileName) ; create color map array ; Capture the screen area as a bitmap Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sFileName) If @error Then Return SetError(1, 0, "") ; because the user ( me ) might do the unexpected ;) ; Get the width and height of the captured area Local $width = _GDIPlus_ImageGetWidth($hBitmap) Local $height = _GDIPlus_ImageGetHeight($hBitmap) ;~ ConsoleWrite("Image: $width=" & $width & ", $height=" & $height & @CRLF) ; Create an array to store color values Local $aColorMap[$width][$height] ; Loop through each pixel in the bitmap and retrieve its color For $y = 0 To $height - 1 For $x = 0 To $width - 1 ; Get the pixel color from the bitmap in ARGB format Local $argbColor = _GDIPlus_BitmapGetPixel($hBitmap, $x, $y) ; Convert ARGB to BGR for comparison (ignore the alpha channel) Local $bgrColor = BitAND($argbColor, 0x00FFFFFF) $aColorMap[$x][$y] = $bgrColor Next Next ; Cleanup resources _GDIPlus_BitmapDispose($hBitmap) Return $aColorMap EndFunc ;==>CaptureAreaColorMap ;-------------------------------------------------------------------------------------------------------------------------------- Func FindNumberUsingColorMap($aColorMap, $hColor = 0x00FF00) ; find number in color map array Local $width = UBound($aColorMap, 1) Local $height = UBound($aColorMap, 2) Local $firstRow = -1, $lastRow = -1, $firstCol = -1, $lastCol = -1 ; Scan for the first and last rows and columns with $hColor pixels For $y = 0 To $height - 1 For $x = 0 To $width - 1 If $aColorMap[$x][$y] = $hColor Then If $firstRow = -1 Then $firstRow = $y $lastRow = $y If $firstCol = -1 Or $x < $firstCol Then $firstCol = $x If $lastCol = -1 Or $x > $lastCol Then $lastCol = $x EndIf Next Next If $firstRow = -1 Or $lastRow = -1 Or $firstCol = -1 Or $lastCol = -1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "No color found" & @TAB & @TAB) _Exit() EndIf ; each number Display is a matrix of 14x20 pixels Local $numberWidth = 14 ; set number width per digit Local $numberSpace = 2 ; set Space between digits Local $Empty = 0, $Corection = 0 ; Corection for boundaries if 1st digit = 1 For $x = $firstCol To $lastCol - 1 If $aColorMap[$x][$firstRow] = 0x000000 Then $Empty += 1 If $Empty = 3 Then ;found 1st Space between digits $Corection = $firstCol - 1 - Abs($x - $numberWidth - $numberSpace) ExitLoop EndIf Else $Empty = 0 EndIf Next If $Corection > 0 Then $firstCol = $firstCol - $Corection Local $numberStart = $firstCol ;~ ConsoleWrite("$Corection=" & $Corection & @CRLF) ;~ ConsoleWrite("Display_boundaries firstRow:" & $firstRow & " lastRow:" & $lastRow & " firstCol:" & $firstCol & " lastCol:" & $lastCol & @CRLF) ;~ ConsoleWrite("" & @CRLF) Local $aNum[11][3] ; Define boundaries for each number position For $i = 1 To 10 $aNum[$i][0] = $numberStart $aNum[$i][1] = $numberStart + $numberWidth If $numberStart + $numberWidth + $numberSpace > $lastCol Then ExitLoop $numberStart += $numberWidth + $numberSpace $aNum[0][0] = $i + 1 Next ;~ _ArrayDisplay($aNum) Local $sNumber ; Generate patterns for each found number For $i = 1 To $aNum[0][0] Local $sPattern = "" For $y = $firstRow To $lastRow For $x = $aNum[$i][0] To $aNum[$i][1] - 1 If $aColorMap[$x][$y] = $hColor Then $sPattern &= "1" Else $sPattern &= "." EndIf Next $sPattern &= @CRLF Next $sNumber &= _GetPattern($sPattern) Next Return $sNumber EndFunc ;==>FindNumberUsingColorMap ;-------------------------------------------------------------------------------------------------------------------------------- Func _GetPattern($sPattern) ; patterns for each digit ;~ ConsoleWrite("**************" & @CRLF & $sPattern & @CRLF) Local $aNumber[10] ; Define simplified patterns for each digit $aNumber[0] = "" ; Pattern for '0' $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11.......11.11" & @CRLF $aNumber[0] &= "11.......11.11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11....11....11" & @CRLF $aNumber[0] &= "11....11....11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11.11.......11" & @CRLF $aNumber[0] &= "11.11.......11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[1] = "" ; Pattern for '1' $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "...11.11......" & @CRLF $aNumber[1] &= "...11.11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "...11.11.11..." & @CRLF $aNumber[1] &= "...11.11.11..." & @CRLF $aNumber[2] = "" ; Pattern for '2' $aNumber[2] &= "...11.11.11..." & @CRLF $aNumber[2] &= "...11.11.11..." & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "11..........11" & @CRLF $aNumber[2] &= "11..........11" & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "............11" & @CRLF $aNumber[2] &= "............11" & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "......11.11..." & @CRLF $aNumber[2] &= "......11.11..." & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "...11........." & @CRLF $aNumber[2] &= "...11........." & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "11............" & @CRLF $aNumber[2] &= "11............" & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "11.11.11.11.11" & @CRLF $aNumber[2] &= "11.11.11.11.11" & @CRLF $aNumber[3] = "" ; Pattern for '3' $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "......11.11..." & @CRLF $aNumber[3] &= "......11.11..." & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[4] = "" ; Pattern for '4' $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "......11.11..." & @CRLF $aNumber[4] &= "......11.11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "...11....11..." & @CRLF $aNumber[4] &= "...11....11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "11.......11..." & @CRLF $aNumber[4] &= "11.......11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "11.11.11.11.11" & @CRLF $aNumber[4] &= "11.11.11.11.11" & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[5] = "" ; Pattern for '5' $aNumber[5] &= "11.11.11.11.11" & @CRLF $aNumber[5] &= "11.11.11.11.11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "11............" & @CRLF $aNumber[5] &= "11............" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "11.11.11.11..." & @CRLF $aNumber[5] &= "11.11.11.11..." & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "11..........11" & @CRLF $aNumber[5] &= "11..........11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "...11.11.11..." & @CRLF $aNumber[5] &= "...11.11.11..." & @CRLF $aNumber[6] = "" ; Pattern for '6' $aNumber[6] &= "......11.11..." & @CRLF $aNumber[6] &= "......11.11..." & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "...11........." & @CRLF $aNumber[6] &= "...11........." & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11............" & @CRLF $aNumber[6] &= "11............" & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11.11.11.11..." & @CRLF $aNumber[6] &= "11.11.11.11..." & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "...11.11.11..." & @CRLF $aNumber[6] &= "...11.11.11..." & @CRLF $aNumber[7] = "" ; Pattern for '7' $aNumber[7] &= "11.11.11.11.11" & @CRLF $aNumber[7] &= "11.11.11.11.11" & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "............11" & @CRLF $aNumber[7] &= "............11" & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= ".........11..." & @CRLF $aNumber[7] &= ".........11..." & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "......11......" & @CRLF $aNumber[7] &= "......11......" & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[8] = "" ; Pattern for '8' $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[9] = "" ; Pattern for '9' $aNumber[9] &= "...11.11.11..." & @CRLF $aNumber[9] &= "...11.11.11..." & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "...11.11.11.11" & @CRLF $aNumber[9] &= "...11.11.11.11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "............11" & @CRLF $aNumber[9] &= "............11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= ".........11..." & @CRLF $aNumber[9] &= ".........11..." & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "...11.11......" & @CRLF $aNumber[9] &= "...11.11......" & @CRLF Switch $sPattern Case $aNumber[0] Return 0 Case $aNumber[1] Return 1 Case $aNumber[2] Return 2 Case $aNumber[3] Return 3 Case $aNumber[4] Return 4 Case $aNumber[5] Return 5 Case $aNumber[6] Return 6 Case $aNumber[7] Return 7 Case $aNumber[8] Return 8 Case $aNumber[9] Return 9 Case Else Return SetError(1, 0, "") EndSwitch EndFunc ;==>_GetPattern ;-------------------------------------------------------------------------------------------------------------------------------- Func Test() ; _GetNumber for all Run("Tool.exe") ; Local $tool = WinWaitActive("Tool", "", 3) ControlClick($tool, "", "TTabSheet1", "primary", 1, 210, 50) ControlCommand($tool, "", "TFlatComboBox1", "SelectString", "Old") Local $db = FileOpen(@ScriptDir & "\tool-db.txt", 1) DirRemove("Bitmap ID Failed", 1) DirCreate("Bitmap ID Failed") ; Initialize GDI+ to work with bitmaps _GDIPlus_Startup() For $loop = 0 To 999999 $serial = StringFormat('%06i', $loop) ControlSetText($tool, "", "TFlatMaskEdit3", "S.N: 9" & $serial) ; Enter serial number prefixed with the check digit ControlClick($tool, "", "TTabSheet1", "primary", 1, 69, 50) ; Press "Generate" ; Captures a region of the screen $sImageFile = @ScriptDir & "\Bitmap ID Failed\" & $serial & ".png" _ScreenCapture_Capture($sImageFile, 792, 450, 927, 480, False) ; Capture the color map for the specified area Local $aColorMap = CaptureAreaColorMap($sImageFile) If @error = 1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "File:" & @CRLF & $sImageResult & @CRLF & " not found") _Exit() EndIf Local $output = FindNumberUsingColorMap($aColorMap) If (StringLen($output) = 3 And StringIsDigit($output)) Then FileDelete($sImageResult) FileWrite($db, $serial & "," & $output & @LF) Next FileClose($db) ; Cleanup resources _GDIPlus_Shutdown() EndFunc ;==>Test ;-------------------------------------------------------------------------------------------------------------------------------- I modified the script so that it calls _GDIPlus_Startup() once at the beginning, and _GDIPlus_Shutdown() once at the end instead of calling her for every number I replaced the _ScreenCapture function (although I believe I fixed it after @Nine 's comments), with _ScreenCapture_Capture (since you didn't need the extras staff of _ScreenCapture) I did a test with Test("M:\TEMP\100num") where M: is my ram disk, and 100num is a folder with 17 .png files expandcollapse popupFunc Test($sFolderPath, $hColor = 0x00FF00) ; _GetNumber for all the *.png files in $sFolderPath directory ; List all the *.png files in $sFolderPath directory Local $aFileList = _FileListToArray($sFolderPath, "*.png", $FLTA_FILES) If @error = 1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "Path was invalid.") Exit EndIf If @error = 4 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "No file(s) were found.") Exit EndIf _ArrayColInsert($aFileList, 1) ; add 1 column to hold the numbers ; Initialize GDI+ to work with bitmaps _GDIPlus_Startup() Local $cnt = 0 Local $CleanTime = 0 For $j = 1 To 1000 For $i = 1 To $aFileList[0][0] $cnt += 1 ConsoleWrite("$cnt: " & $cnt & @CRLF) ; Capture the color map for the specified area Local $aColorMap = CaptureAreaColorMap($sFolderPath & "\" & $aFileList[$i][0]) If @error = 1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "Path was invalid.") Exit EndIf $aFileList[$i][1] = FindNumberUsingColorMap($aColorMap, $hColor) ; Rename a file using FileMove and overwrite the new file if it exists. ;~ FileMove($sFolderPath & "\" & $aFileList[$i][0], $sFolderPath & "\" & $aFileList[$i][1] & ".png", $FC_OVERWRITE) ;~ $aProcessMemoryInfo = _WinAPI_GetProcessMemoryInfo() ;~ ConsoleWrite('The peak working set: ' & $aProcessMemoryInfo[1] / 1024 / 1014 & ' MB' & @CRLF) Next Next _ArrayDisplay($aFileList, "$aFileList") ; Cleanup resources _GDIPlus_Shutdown() EndFunc ;==>Test Edited November 7 by ioa747 I know that I know nothing Link to comment Share on other sites More sharing options...
argumentum Posted November 7 Share Posted November 7 7 minutes ago, ioa747 said: on a ram drive I use ImDisk. Make the ramdisk any size. ioa747 and Hashim 2 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...
Werty Posted November 7 Share Posted November 7 4 hours ago, ioa747 said: $aNumber[0] = "" ; Pattern for '0' $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11.......11.11" & @CRLF $aNumber[0] &= "11.......11.11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11....11....11" & @CRLF $aNumber[0] &= "11....11....11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11.11.......11" & @CRLF $aNumber[0] &= "11.11.......11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF You dont need to check the whole pattern, the first column in each digit is unique... ioa747, Danyfirex and Hashim 3 Some guy's script + some other guy's script = my script! Link to comment Share on other sites More sharing options...
argumentum Posted November 7 Share Posted November 7 6 hours ago, Werty said: the first column and 2nd, as the number one could be just empty. 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...
Werty Posted November 7 Share Posted November 7 37 minutes ago, argumentum said: as the number one could be just empty. Doesnt matter, it'll work fine as the numbers are always 3 digits with a leading zero when the number is less than 100, like "......043......", as per his other thread where he posts examples of numbers. Hashim 1 Some guy's script + some other guy's script = my script! Link to comment Share on other sites More sharing options...
Nine Posted November 7 Share Posted November 7 True, but you must be careful about the order you are looking for a match (ex : don't look for 4 before 6, don't look for 3 before 8 ) because you may end up for false positive. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
ioa747 Posted November 7 Share Posted November 7 (edited) @Werty just for information the first column actually are 2 columns (2 pixels) I did a test on a sample of 1700 images (1700 * 3 = 5100 numbers) with 1 columns processed in: 103.986 seconds with 2 columns processed in: 104.018 seconds with 14 columns processed in: 105.922 seconds in the 17 numbers I have, they didn't make any mistakes Edited November 7 by ioa747 add with 1 columns I know that I know nothing Link to comment Share on other sites More sharing options...
Werty Posted November 7 Share Posted November 7 (edited) @Nine How so, they are unique so how can they give a false positive? You check both the lit and unlit pixels. We could store them in one byte each, they are 7 pixels tall (yes, i know they are actually taller but we only use those we need), and 7 bits fits a byte they would become (reading from top to bottom in little-endian)... 0 = 62 1 = 0 2 = 35 3 = 34 4 = 12 5 = 114 6 = 30 7 = 64 8 = 54 9 = 48 Edited November 8 by Werty Hashim 1 Some guy's script + some other guy's script = my script! Link to comment Share on other sites More sharing options...
Werty Posted November 7 Share Posted November 7 1 minute ago, ioa747 said: the first column actually are 2 columns Yes, but you are supposed to skip those second ones, and only read the needed ones, i'll see if I can mock up an example later using pixelgetcolor, dinner time now. 😛 ioa747 1 Some guy's script + some other guy's script = my script! Link to comment Share on other sites More sharing options...
Nine Posted November 7 Share Posted November 7 Ok, I understand what you mean now. Adding all the pixels from the first column will give a unique value. Werty 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
argumentum Posted November 7 Share Posted November 7 1 hour ago, Werty said: Doesnt matter, it'll work fine as the numbers are always 3 digits with a leading zero when... Don't know about that. The OP shares bits and pieces. The extra millisecond saved is not that important. Producing an unequivocal output is**. We should see if the OP fixed the high loop count crush. That merits attention. ** Not saying that your trend of thought is wrong Hashim 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 November 7 Share Posted November 7 (edited) Here it is the edition with a single column patern expandcollapse popup; https://www.autoitscript.com/forum/topic/211521-ocr-from-a-small-area/?do=findComment&comment=1538057 ; Version: 5.0.2 #include <GDIPlus.au3> #include <Array.au3> #include <File.au3> #include <WinAPIProc.au3> ;~ Local $Result = _GetNumber(@ScriptDir & "\100num\040.png") ;~ MsgBox($MB_SYSTEMMODAL, "_GetNumber", $Result) Test("M:\TEMP\100num") ;-------------------------------------------------------------------------------------------------------------------------------- Func _GetNumber($sFileName, $hColor = 0x00FF00) ; Main Program ; Initialize GDI+ to work with bitmaps _GDIPlus_Startup() ; Capture the color map for the specified area Local $aColorMap = CaptureAreaColorMap($sFileName) If @error = 1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "Path was invalid.") Exit EndIf ;~ _ArrayDisplay($aColorMap) Local $Result = FindNumberUsingColorMap($aColorMap, $hColor) ;~ MsgBox($MB_SYSTEMMODAL, "$Result", $Result) ; Cleanup resources _GDIPlus_Shutdown() Return $Result EndFunc ;==>_GetNumber ;-------------------------------------------------------------------------------------------------------------------------------- Func CaptureAreaColorMap($sFileName) ; create color map array ; Initialize GDI+ to work with bitmaps ;_GDIPlus_Startup() ; Capture the screen area as a bitmap Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sFileName) If @error Then Return SetError(1, 0, "") ; because the user ( me ) might do the unexpected ;) ; Get the width and height of the captured area Local $width = _GDIPlus_ImageGetWidth($hBitmap) Local $height = _GDIPlus_ImageGetHeight($hBitmap) ;~ ConsoleWrite("Image: $width=" & $width & ", $height=" & $height & @CRLF) ; Create an array to store color values Local $aColorMap[$width][$height] ; Loop through each pixel in the bitmap and retrieve its color For $y = 0 To $height - 1 For $x = 0 To $width - 1 ; Get the pixel color from the bitmap in ARGB format Local $argbColor = _GDIPlus_BitmapGetPixel($hBitmap, $x, $y) ; Convert ARGB to BGR for comparison (ignore the alpha channel) Local $bgrColor = BitAND($argbColor, 0x00FFFFFF) $aColorMap[$x][$y] = $bgrColor Next Next ; Cleanup resources _GDIPlus_BitmapDispose($hBitmap) ;_GDIPlus_Shutdown() Return $aColorMap EndFunc ;==>CaptureAreaColorMap ;-------------------------------------------------------------------------------------------------------------------------------- Func FindNumberUsingColorMap($aColorMap, $hColor = 0x00FF00) ; find number in color map array Local $width = UBound($aColorMap, 1) Local $height = UBound($aColorMap, 2) Local $firstRow = -1, $lastRow = -1, $firstCol = -1, $lastCol = -1 ; Scan for the first and last rows and columns with $hColor pixels For $y = 0 To $height - 1 For $x = 0 To $width - 1 If $aColorMap[$x][$y] = $hColor Then If $firstRow = -1 Then $firstRow = $y $lastRow = $y If $firstCol = -1 Or $x < $firstCol Then $firstCol = $x If $lastCol = -1 Or $x > $lastCol Then $lastCol = $x EndIf Next Next If $firstRow = -1 Or $lastRow = -1 Or $firstCol = -1 Or $lastCol = -1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "No color found" & @TAB & @TAB) Exit EndIf ; each number Display is a matrix of 14x20 pixels Local $numberWidth = 14 ; set number width per digit Local $numberSpace = 2 ; set Space between digits Local $Empty = 0, $Corection = 0 ; Corection for boundaries if 1st digit = 1 For $x = $firstCol To $lastCol - 1 If $aColorMap[$x][$firstRow] = 0x000000 Then $Empty += 1 If $Empty = 3 Then ;found 1st Space between digits $Corection = $firstCol - 1 - Abs($x - $numberWidth - $numberSpace) ExitLoop EndIf Else $Empty = 0 EndIf Next If $Corection > 0 Then $firstCol = $firstCol - $Corection Local $numberStart = $firstCol ;~ ConsoleWrite("$Corection=" & $Corection & @CRLF) ;~ ConsoleWrite("Display_boundaries firstRow:" & $firstRow & " lastRow:" & $lastRow & " firstCol:" & $firstCol & " lastCol:" & $lastCol & @CRLF) ;~ ConsoleWrite("" & @CRLF) Local $aNum[11][3] ; Define boundaries for each number position For $i = 1 To 10 $aNum[$i][0] = $numberStart $aNum[$i][1] = $numberStart + $numberWidth If $numberStart + $numberWidth + $numberSpace > $lastCol Then ExitLoop $numberStart += $numberWidth + $numberSpace $aNum[0][0] = $i + 1 Next ;~ _ArrayDisplay($aNum) Local $sNumber ; Generate patterns for each found number For $i = 1 To $aNum[0][0] Local $sPattern = "" For $y = $firstRow To $lastRow $x = $aNum[$i][0] If $aColorMap[$x][$y] = $hColor Then $sPattern &= "1" Else $sPattern &= "." EndIf $sPattern &= @CRLF Next $sNumber &= _GetPattern($sPattern) Next Return $sNumber EndFunc ;==>FindNumberUsingColorMap ;-------------------------------------------------------------------------------------------------------------------------------- Func _GetPattern($sPattern) ; patterns for each digit ;~ ConsoleWrite("**************" & @CRLF & $sPattern & @CRLF) Local Static $aPNum ; Define simplified patterns for each digit If Not IsArray($aPNum) Then Local $aNumber[10] $aNumber[0] = "" ; Pattern for '0' $aNumber[0] &= "." & @CRLF $aNumber[0] &= "." & @CRLF $aNumber[0] &= "." & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "." & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "." & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "." & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "." & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "1" & @CRLF $aNumber[0] &= "." & @CRLF $aNumber[0] &= "." & @CRLF $aNumber[0] &= "." & @CRLF $aNumber[1] = "" ; Pattern for '1' $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[1] &= "." & @CRLF $aNumber[2] = "" ; Pattern for '2' $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "1" & @CRLF $aNumber[2] &= "1" & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "1" & @CRLF $aNumber[2] &= "1" & @CRLF $aNumber[2] &= "." & @CRLF $aNumber[2] &= "1" & @CRLF $aNumber[2] &= "1" & @CRLF $aNumber[3] = "" ; Pattern for '3' $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "1" & @CRLF $aNumber[3] &= "1" & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "1" & @CRLF $aNumber[3] &= "1" & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[3] &= "." & @CRLF $aNumber[4] = "" ; Pattern for '4' $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "1" & @CRLF $aNumber[4] &= "1" & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "1" & @CRLF $aNumber[4] &= "1" & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[4] &= "." & @CRLF $aNumber[5] = "" ; Pattern for '5' $aNumber[5] &= "1" & @CRLF $aNumber[5] &= "1" & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "1" & @CRLF $aNumber[5] &= "1" & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "1" & @CRLF $aNumber[5] &= "1" & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "1" & @CRLF $aNumber[5] &= "1" & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[5] &= "." & @CRLF $aNumber[6] = "" ; Pattern for '6' $aNumber[6] &= "." & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "1" & @CRLF $aNumber[6] &= "1" & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "1" & @CRLF $aNumber[6] &= "1" & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "1" & @CRLF $aNumber[6] &= "1" & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "1" & @CRLF $aNumber[6] &= "1" & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[6] &= "." & @CRLF $aNumber[7] = "" ; Pattern for '7' $aNumber[7] &= "1" & @CRLF $aNumber[7] &= "1" & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[7] &= "." & @CRLF $aNumber[8] = "" ; Pattern for '8' $aNumber[8] &= "." & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "1" & @CRLF $aNumber[8] &= "1" & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "1" & @CRLF $aNumber[8] &= "1" & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "1" & @CRLF $aNumber[8] &= "1" & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "1" & @CRLF $aNumber[8] &= "1" & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[8] &= "." & @CRLF $aNumber[9] = "" ; Pattern for '9' $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "1" & @CRLF $aNumber[9] &= "1" & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "1" & @CRLF $aNumber[9] &= "1" & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aNumber[9] &= "." & @CRLF $aPNum = $aNumber EndIf Switch $sPattern Case $aPNum[0] Return 0 Case $aPNum[1] Return 1 Case $aPNum[2] Return 2 Case $aPNum[3] Return 3 Case $aPNum[4] Return 4 Case $aPNum[5] Return 5 Case $aPNum[6] Return 6 Case $aPNum[7] Return 7 Case $aPNum[8] Return 8 Case $aPNum[9] Return 9 Case Else Return SetError(1, 0, "") EndSwitch EndFunc ;==>_GetPattern ;-------------------------------------------------------------------------------------------------------------------------------- Func Test($sFolderPath, $hColor = 0x00FF00) ; _GetNumber for all the *.png files in $sFolderPath directory ; List all the *.png files in $sFolderPath directory Local $aFileList = _FileListToArray($sFolderPath, "*.png", $FLTA_FILES) If @error = 1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "Path was invalid.") Exit EndIf If @error = 4 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "No file(s) were found.") Exit EndIf _ArrayColInsert($aFileList, 1) ; add 1 column to hold the numbers ; Initialize GDI+ to work with bitmaps _GDIPlus_Startup() Local $cnt = 0 Local $CleanTime = 0 Local $hTimer = TimerInit() For $j = 1 To 100 For $i = 1 To $aFileList[0][0] $cnt += 1 ConsoleWrite("$cnt: " & $cnt & @CRLF) ; Capture the color map for the specified area Local $aColorMap = CaptureAreaColorMap($sFolderPath & "\" & $aFileList[$i][0]) If @error = 1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "Path was invalid.") Exit EndIf $aFileList[$i][1] = FindNumberUsingColorMap($aColorMap, $hColor) ; Rename a file using FileMove and overwrite the new file if it exists. ;~ FileMove($sFolderPath & "\" & $aFileList[$i][0], $sFolderPath & "\" & $aFileList[$i][1] & ".png", $FC_OVERWRITE) ;~ $aProcessMemoryInfo = _WinAPI_GetProcessMemoryInfo() ;~ ConsoleWrite('The peak working set: ' & $aProcessMemoryInfo[1] / 1024 / 1014 & ' MB' & @CRLF) Next Next ConsoleWrite("processed in: " & Round(TimerDiff($hTimer) / 1000, 3) & " seconds " & @LF) _ArrayDisplay($aFileList, "$aFileList") ; Cleanup resources _GDIPlus_Shutdown() EndFunc ;==>Test ;-------------------------------------------------------------------------------------------------------------------------------- Edited November 7 by ioa747 Update to Version: 5.0.2 Hashim and Werty 2 I know that I know nothing 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