Jump to content

Recommended Posts

Posted (edited)

Happy New Year everyone, this is a successor thread of sorts to one from a few months ago, I've now tested @Werty's latest solution from that thread:
 

;Be sure $posx and $posy is pointing at the correct spot!
Global $posx = 1718, $posy = 699, $result = "", $code[3]
;Lookup table to avoid searching
Global $digit[115] = [1,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, _
                      0,0,0,0,0,0,0,0,0,0,6,0,0,0,3,2,0,0,0,0, _
                      0,0,0,0,0,0,0,0,9,0,0,0,0,0,8,0,0,0,0,0, _
                      0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, _
                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, _
                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,5]

;Instead of screencapture_capture()
    $hDDC = _WinAPI_GetDC(0)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBmp = _WinAPI_CreateCompatibleBitmap($hDDC, 34, 20)
            _WinAPI_SelectObject($hCDC, $hBmp)
            _WinAPI_BitBlt($hCDC, 0, 0, 34, 20, $hDDC, $posx, $posy, 0x00CC0020)
            _WinAPI_DeleteDC($hCDC)

    $result = Getnumber($result)

Func Getnumber($result)
   
    Local $code[3] = [0,0,0], $value = 64, $pixels = DllStructCreate('dword[680]')
    DllCall('gdi32.dll', 'dword', 'GetBitmapBits', 'ptr', $hBmp, 'dword', DllStructGetSize($pixels), 'ptr', DllStructGetPtr($pixels))

For $loop = 1 To 680 Step 102
    $code[0] += DllStructGetData($pixels, 1, $loop   ) = 4278255360 ? $value:0
    $code[1] += DllStructGetData($pixels, 1, $loop+16) = 4278255360 ? $value:0
    $code[2] += DllStructGetData($pixels, 1, $loop+32) = 4278255360 ? $value:0
    $value /= 2
Next
    Return String($digit[$code[0]]) & String($digit[$code[1]]) & String($digit[$code[2]])
EndFunc

 

I can confirm it works as well for that tool as his original lockbits solution, and is beautifully concise compared to it. I don't have the time to test on the whole dataset so can't confirm how much faster it is but on the few thousand results I did check it definitely doesn't seem slower or less accurate, so I'll take his word for it that this is now the best solution. The problem now is that I need to do the same thing for a similar but newer internal tool, which seems to have been built by the same dev but uses a completely different bitmap font for its results, and the results are also 4 digits instead of 3. It also seems to be in "italics" so I'm not sure whether this makes the solution impossible or if the bitmaps are still uniform enough for the maths to work. The only really good news is that the font is larger than in the original tool.

Would it possible to adapt the maths of this solution to these new bitmaps? If I understood how it worked I'd do it myself, but it's way over my head and so was @AndyG's explanation of it, but I have provided all of the possible digits below and can provide more examples if needed.

1.png

2.png

3.png

4.png

Edited by Hashim
Posted (edited)

Anyone at all? Here's the full script I'm using along with my best-guess attempts to adapt the results and constants for a 4-digit result - like changing $value from 64 to 128 and adding loop+64. The program seems to run fine without errors, but the digits are all being recognised as either 1s or 0s (the first two digits always as 1s).

I'm happy to buy a drink or five for anyone that can figure this out since management have realised I'm the only person in the department that can extract the data from these old tools.

#include <WinAPI.au3>

Run("tool.exe")
Local $tool = WinWaitActive("tool", "", 3)

$db = FileOpen(@ScriptDir & "\serials.csv", 1)

;Be sure $posx and $posy is pointing at the correct spot!
Global $posx = 829, $posy = 456, $result = "", $code[4]
;Lookup table to avoid searching
Global $digit[115] = [1,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, _
                      0,0,0,0,0,0,0,0,0,0,6,0,0,0,3,2,0,0,0,0, _
                      0,0,0,0,0,0,0,0,9,0,0,0,0,0,8,0,0,0,0,0, _
                      0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, _
                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, _
                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,5]

For $loop = 0 To 999999

    Do
        $serial = StringFormat('%06i', $loop)
        ControlClick($tool, "", "TTabSheet1", "primary", 1, 100, 100)
        $hDDC = _WinAPI_GetDC(0)
        $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
        $hBmp = _WinAPI_CreateCompatibleBitmap($hDDC, 34, 20)
        _WinAPI_SelectObject($hCDC, $hBmp)
        _WinAPI_BitBlt($hCDC, 0, 0, 34, 20, $hDDC, $posx, $posy, 0x00CC0020)
        _WinAPI_DeleteDC($hCDC)
        $result = GetNumber($result)
    Until ((StringLen($result) = 4) and StringIsDigit($result))

    FileWrite($db, $serial & "," & $result & @LF)

Next

FileClose($db)
Exit

Func GetNumber($result)

    Local $code[4] = [0,0,0,0], $value = 128, $pixels = DllStructCreate('dword[680]')
    DllCall('gdi32.dll', 'dword', 'GetBitmapBits', 'ptr', $hBmp, 'dword', DllStructGetSize($pixels), 'ptr', DllStructGetPtr($pixels))

For $loop = 1 To 680 Step 102
    $code[0] += DllStructGetData($pixels, 1, $loop   ) = 4278255360 ? $value:0
    $code[1] += DllStructGetData($pixels, 1, $loop+16) = 4278255360 ? $value:0
    $code[2] += DllStructGetData($pixels, 1, $loop+32) = 4278255360 ? $value:0
    $code[3] += DllStructGetData($pixels, 1, $loop+64) = 4278255360 ? $value:0
    $value /= 2
Next
    Return String($digit[$code[0]]) & String($digit[$code[1]]) & String($digit[$code[2]]) & String($digit[$code[3]])
EndFunc

 

Edited by Hashim
Posted (edited)

 

Maybe this helps a little in understanding. 
Its just manipulation of pixels in a certan layout (PNG). 
Look at the output and zoom in/out, you can see almost the numbers yourself 

#Region includes
Opt('MustDeclareVars', 1)
;#include <GUIConstants.au3>
#include <GDIPlus.au3>
#Include <ScreenCapture.au3>
#include <string.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#EndRegion

_GDIPlus_Startup()

Dim $BitmapFilename
Dim $BMPData="", $BMPWidth=0, $BMPHeight=0, $BMPLineWidth=0, $imgBytes=1
dim $binaryLine

for $i=1 to 4
    $BitmapFilename = @TempDir & "\" & "pic" & string($i) & ".png"
        $BMPData=""
        $BMPWidth=0
        $BMPHeight=0
        $BMPLineWidth=0
        $imgBytes=1
        consolewrite($bitmapFileName)

; Load the bitmap to find
    getImage($BitmapFilename, $BMPData, $BMPWidth, $BMPHeight, $BMPLineWidth, $imgBytes)

    ;~ See the height and width and dump the data on screen
    consolewrite($BMPHeight & " ; ")
    consolewrite($BMPWidth &@CRLF )
    consolewrite("0         1         2         3         4         5         6         7         8         9         x         x         x         x         " & @CRLF)
    consolewrite("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" & @CRLF)
    For $iLine = 11 To $BMPHeight-12

    ;~  From the screenshots we can ignore the first 16 bytes (remember in text its 2 characters
    ;~  $binaryLine=BinaryMid($bmp1Data,($i*$BMP1LineWidth)+16,$BMP1LineWidth)
    ;~  and we only need 4 digits which takes about 28 characters and 1 character separator =
        $binaryLine=BinaryMid($bmpData,($iLine *$BMPLineWidth)+16,60)
;~ Lets make it readable
        $binaryLine=StringReplace($binaryLine,"0",".")

        consolewrite($iLine & " : " & $binaryLine & @CRLF)
    next

;~  lets recognise
    for $iNumber=1 to 4

        consolewrite(@crlf)
            consolewrite("0         1         2         3         4         5         6         7         8         9         x         x         x         x         " & @CRLF)
    consolewrite("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" & @CRLF)

        For $iLine = 11 To $BMPHeight-12
            $binaryLine=BinaryMid($bmpData,($iLine *$BMPLineWidth)+16+(($iNumber-1)*15),14)
            $binaryLine=StringReplace($binaryLine,"0",".")
            consolewrite($iLine & " : " & $binaryLine & @CRLF)
        next
    Next

Next

_GDIPlus_Shutdown()

Func GetImage($BMPFile, byref $BMPDataStart, byref $Width, byRef $Height, byref $Stride, $imgBytes=3)
local $Scan0, $pixelData, $hbScreen, $pBitmap, $pBitmapCap, $handle, $bitMapdata, $pixelFormat

; Load the bitmap to search in
    If $BMPFile="SCREEN" Then
        $hbScreen=_ScreenCapture_Capture("",0,0,-1,-1,False)
        $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    Else
;try to get a handle
        $handle = WinGetHandle($BMPFile)
        If @error Then
;Assume its an unknown handle so correct filename should be given
            $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
;~          $hBitmap = _GDIPlus_ImageLoadFromFile($BMPFile)
        Else
            $hbScreen=_ScreenCapture_CaptureWnd("",$handle,0,0,-1,-1,False)
            $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
        EndIf
    EndIf

;Get $tagGDIPBITMAPDATA structure
  ConsoleWrite("Bitmap Width:    " & _GDIPlus_ImageGetWidth($pBitmap) & @CRLF )
  ConsoleWrite("Bitmap Height:      " & _GDIPlus_ImageGetHeight($pBitmap) & @CRLF)

;~  24 bits (3 bytes) or 16 bits (2 bytes) comparison
    if ($imgBytes=1) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD,  $GDIP_PXF04INDEXED)
    Endif
    if ($imgBytes=2) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF16RGB555)
;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    EndIf
    if ($imgBytes=3) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB)
;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    endIf

    If @ERROR Then MsgBox(0,"","Error locking region " & @error)

    $Stride = DllStructGetData($BitmapData, "Stride");Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
    $Width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap.
    $Height = DllStructGetData($BitmapData, "Height");Image height - Number of scan lines in the bitmap.
    $PixelFormat = DllStructGetData($BitmapData, "PixelFormat");Pixel format - Integer that specifies the pixel format of the bitmap
    $Scan0 = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap.

    $pixelData = DllStructCreate("ubyte lData[" & (abs($Stride) * $Height-1) & "]", $Scan0)
    $BMPDataStart = $BMPDataStart & DllStructGetData($pixeldata,"lData")

    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
    _GDIPlus_ImageDispose ($pBitmap)
    _WinAPI_DeleteObject ($pBitmap)

EndFunc;==>GetImage
; Draw rectangle on screen.
Func _UIA_DrawRect($tLeft, $tRight, $tTop, $tBottom, $color = 0xFF, $PenWidth = 4)
    Local $hDC, $hPen, $obj_orig, $x1, $x2, $y1, $y2
    $x1 = $tLeft
    $x2 = $tRight
    $y1 = $tTop
    $y2 = $tBottom
    $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop)
    $hPen = _WinAPI_CreatePen($PS_SOLID, $PenWidth, $color)
    $obj_orig = _WinAPI_SelectObject($hDC, $hPen)

    _WinAPI_DrawLine($hDC, $x1, $y1, $x2, $y1) ; horizontal to right
    _WinAPI_DrawLine($hDC, $x2, $y1, $x2, $y2) ; vertical down on right
    _WinAPI_DrawLine($hDC, $x2, $y2, $x1, $y2) ; horizontal to left right
    _WinAPI_DrawLine($hDC, $x1, $y2, $x1, $y1) ; vertical up on left

    ; clear resources
    _WinAPI_SelectObject($hDC, $obj_orig)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_ReleaseDC(0, $hDC)
EndFunc   ;==>_UIA_DrawRect
#EndRegion



I assume you refer to 

 

Edited by junkew
updated script to have 8 bits per pixel for easier seeing
Posted

You should get some output like below, copy pasted to a texteditor (replaced 0 with a dot) you can find out the width of the numbers somewhere around 28 (depending on your colordepth)
 

.x................................................................................................................................................................................
.x....................................................BBB.....................BBB..BBB................BBB..BBB..BBB.....................BBB.......................................
.x...................................................B222B...................B222BB222B..............B222BB222BB222B...................B222B......................................
.x...................................................B222B...................B222BB222B..............B222BB222BB222B...................B222B......................................
.x....................................................BBB.....................BBB..BBB................BBB..BBB..BBB.....................BBB.......................................
.x................................................................................................................................................................................
.x..............................................BBB..BBB................BBB.....................BBB.................BBB...........BBB..BBB........................................
.x.............................................B222BB222B..............B222B...................B222B...............B222B.........B222BB222B.......................................
.x.............................................B222BB222B..............B222B...................B222B...............B222B.........B222BB222B.......................................
.x..............................................BBB..BBB................BBB.....................BBB.................BBB...........BBB..BBB........................................
.x................................................................................................................................................................................
.x.........................................BBB.......BBB...........BBB..........................BBB.................BBB................BBB........................................
.x........................................B222B.....B222B.........B222B........................B222B...............B222B..............B222B.......................................
.x........................................B222B.....B222B.........B222B........................B222B...............B222B..............B222B.......................................
.x.........................................BBB.......BBB...........BBB..........................BBB.................BBB................BBB........................................
.x................................................................................................................................................................................
.x...................................BBB............BBB...........BBB..BBB..BBB..BBB................BBB..BBB..BBB..BBB................BBB.........................................
.x..................................B222B..........B222B.........B222BB222BB222BB222B..............B222BB222BB222BB222B..............B222B........................................
.x..................................B222B..........B222B.........B222BB222BB222BB222B..............B222BB222BB222BB222B..............B222B........................................
.x...................................BBB............BBB...........BBB..BBB..BBB..BBB................BBB..BBB..BBB..BBB................BBB.........................................
.x................................................................................................................................................................................
.x..................................BBB..BBB..BBB..BBB..BBB......BBB.................BBB..........................BBB................BBB..........................................
.x.................................B222BB222BB222BB222BB222B....B222B...............B222B........................B222B..............B222B.........................................
.x.................................B222BB222BB222BB222BB222B....B222B...............B222B........................B222B..............B222B.........................................
.x..................................BBB..BBB..BBB..BBB..BBB......BBB.................BBB..........................BBB................BBB..........................................
.x................................................................................................................................................................................
.x................................................BBB...........BBB.................BBB.....................BBB.....................BBB...........................................
.x...............................................B222B.........B222B...............B222B...................B222B...................B222B..........................................
.x...............................................B222B.........B222B...............B222B...................B222B...................B222B..........................................
.x................................................BBB...........BBB.................BBB.....................BBB.....................BBB...........................................
.x................................................................................................................................................................................
.x................................................BBB................BBB..BBB..BBB................BBB..BBB.....................BBB..BBB..BBB......................................
.x...............................................B222B..............B222BB222BB222B..............B222BB222B...................B222BB222BB222B.....................................
.x...............................................B222B..............B222BB222BB222B..............B222BB222B...................B222BB222BB222B.....................................
.x................................................BBB................BBB..BBB..BBB................BBB..BBB.....................BBB..BBB..BBB......................................

 

Posted

I enhanced the script of my first answer.
Based on that you can see the patterns and identify the differences between the numbers 0-9

It depends if your are "reading" bitblt from the screen you should basically iterate per character.

If you save them all as png files its like the given script needs to be enhanced and add the pattern later onwards.
 

 

Posted (edited)

So here some partial recognition based on the png files. As its italic it will be more complicated to properly first cut the characters nicely.

I hope the script gives you some insights on how to do the analysis.

When thats done you could directly bitblit line11 and 27 and 41 from the screen as that seems to be a proper discriminator to identify the number.
From the screen you can probably directly bitblt with black/white pixels directly which should speed up even more.

Due to italic it seems a little harder to calculate the exact position for each digit calculated (maybe even easier to just hardcode them as it seems to be off by 1 or 2 bytes for each digit.

#Region includes
Opt('MustDeclareVars', 1)
;#include <GUIConstants.au3>
#include <GDIPlus.au3>
#Include <ScreenCapture.au3>
#include <string.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#EndRegion

_GDIPlus_Startup()

Dim $BitmapFilename
Dim $BMPData="", $BMPWidth=0, $BMPHeight=0, $BMPLineWidth=0, $imgBytes=2
dim $binaryLine, $startColumn

;~ for each picture file
for $i=1 to 4
    $BitmapFilename = @TempDir & "\" & "pic" & string($i) & ".png"
        $BMPData=""
        $BMPWidth=0
        $BMPHeight=0
        $BMPLineWidth=0
        $imgBytes=1
        consolewrite($bitmapFileName)

; Load the bitmap to find
    getImage($BitmapFilename, $BMPData, $BMPWidth, $BMPHeight, $BMPLineWidth, $imgBytes)

    ;~ See the height and width and dump the data on screen
    consolewrite($BMPHeight & " ; ")
    consolewrite($BMPWidth &@CRLF )
    consolewrite("       0         1         2         3         4         5         6         7         8         9         x         x         x         x         " & @CRLF)
    consolewrite("       01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" & @CRLF)
    For $iLine = 11 To $BMPHeight-12

    ;~  From the screenshots we can ignore the first 16 bytes (remember in text its 2 characters
    ;~  $binaryLine=BinaryMid($bmp1Data,($i*$BMP1LineWidth)+16,$BMP1LineWidth)
    ;~  and we only need 4 digits which takes about 28 characters and 1 character separator =
        $binaryLine=BinaryMid($bmpData,($iLine *$BMPLineWidth)+16,60)
;~      $binaryLine=$bmpData
;~ Lets make it readable
        $binaryLine=StringReplace($binaryLine,"0",".")

        consolewrite($iLine & " : " & $binaryLine & @CRLF)
    next

;~  lets recognise
    for $iNumber=1 to 4

        consolewrite(@crlf)
            consolewrite("0         1         2         3         4         5         6         7         8         9         x         x         x         x         " & @CRLF)
    consolewrite("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" & @CRLF)
    
;~  Its hard to determine the column for each digit in a formula 
        if $iNumber=1 then $startColumn=16
        if $iNumber=2 then $startColumn=30
        if $iNumber=3 then $startColumn=45
        if $iNumber=4 then $startColumn=59

;~ Only a few lines in the png are of interest

        For $iLine = 11 To $BMPHeight-12
;~          $binaryLine=BinaryMid($bmpData,($iLine *$BMPLineWidth)+16+(($iNumber-1)*14),15)
            $binaryLine=BinaryMid($bmpData,($iLine *$BMPLineWidth)+$startColumn,15)


            $binaryLine=StringReplace($binaryLine,"0"," ")
            consolewrite($iLine & " : " & $binaryLine & @CRLF)
        next
;~      if on line 11 at position 28 I have a B it can be a 4

;~ It seems to be easier to revert back to a string when we have the data
        local $lineData11=stringstripws(StringRegExpReplace(binaryMid($bmpData,(11*$BMPLineWidth)+$startColumn,15),"[x0]"," "),3)
        local $lineData27=stringstripws(StringRegExpReplace(binaryMid($bmpData,(27*$BMPLineWidth)+$startColumn,15),"[x0]"," "),3)
        local $lineData41=stringstripws(StringRegExpReplace(binaryMid($bmpData,(41*$BMPLineWidth)+$startColumn,15),"[x0]"," "),3)

        consolewrite(string($lineData11) & " - ")
        consolewrite(string($lineData27) & " - ")
        consolewrite(string($lineData41) & @crlf)

;~ And here determine the magic lines

        if (($lineData11="BBB")                     and ($lineData27="B222B          B222B")) then consolewrite("Ita a 4" & @CRLF)
        if (($lineData11="BBB  BBB")                and ($lineData27="B222BB222BB222BB222B")) then consolewrite("Ita a 6" & @CRLF)
        if (($lineData11="BBB  BBB  BBB")           and ($lineData27="B222BB222BB222BB222B")) then consolewrite("Ita a 9" & @CRLF)
        if (($lineData11="BBB")                     and ($lineData27="B222B")) then consolewrite("Ita a 1" & @CRLF)

        if (($lineData11="BBB  BBB  BBB")           and ($lineData27="B222BB222BB222B")) then consolewrite("Ita a 8" & @CRLF)
        if (($lineData11="BBB  BBB  BBB")           and ($lineData27="B222B     B222B     B222B")) then consolewrite("Ita a 0" & @CRLF)

        if (($lineData11="BBB  BBB  BBB")           and ($lineData27="B222BB222B") and ($lineData41="BBB  BBB  BBB")) then consolewrite("Ita a 3" & @CRLF)
        if (($lineData11="BBB  BBB  BBB")           and ($lineData27="B222BB222B") and ($lineData41="BBB  BBB  BBB  BBB  BBB")) then consolewrite("Ita a 2" & @CRLF)

        if (($lineData11="BBB  BBB  BBB  BBB  BBB")           and ($lineData27="B222B") and ($lineData41="BBB")) then consolewrite("Ita a 7" & @CRLF)
        if (($lineData11="BBB  BBB  BBB  BBB  BBB")           and ($lineData27="B222B") and ($lineData41="BBB  BBB  BBB")) then consolewrite("Ita a 5" & @CRLF)
    Next

Next

_GDIPlus_Shutdown()

Func GetImage($BMPFile, byref $BMPDataStart, byref $Width, byRef $Height, byref $Stride, $imgBytes=3)
local $Scan0, $pixelData, $hbScreen, $pBitmap, $pBitmapCap, $handle, $bitMapdata, $pixelFormat

; Load the bitmap to search in
    If $BMPFile="SCREEN" Then
        $hbScreen=_ScreenCapture_Capture("",0,0,-1,-1,False)
        $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    Else
;try to get a handle
        $handle = WinGetHandle($BMPFile)
        If @error Then
;Assume its an unknown handle so correct filename should be given
            $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
;~          $hBitmap = _GDIPlus_ImageLoadFromFile($BMPFile)
        Else
            $hbScreen=_ScreenCapture_CaptureWnd("",$handle,0,0,-1,-1,False)
            $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
        EndIf
    EndIf

;Get $tagGDIPBITMAPDATA structure
  ConsoleWrite("Bitmap Width:    " & _GDIPlus_ImageGetWidth($pBitmap) & @CRLF )
  ConsoleWrite("Bitmap Height:      " & _GDIPlus_ImageGetHeight($pBitmap) & @CRLF)

;~  24 bits (3 bytes) or 16 bits (2 bytes) comparison
    if ($imgBytes=1) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD,    $GDIP_PXF04INDEXED)
    Endif
    if ($imgBytes=2) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF16RGB555)
;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    EndIf
    if ($imgBytes=3) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB)
;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    endIf

    If @ERROR Then MsgBox(0,"","Error locking region " & @error)

    $Stride = DllStructGetData($BitmapData, "Stride");Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
    $Width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap.
    $Height = DllStructGetData($BitmapData, "Height");Image height - Number of scan lines in the bitmap.
    $PixelFormat = DllStructGetData($BitmapData, "PixelFormat");Pixel format - Integer that specifies the pixel format of the bitmap
    $Scan0 = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap.

    $pixelData = DllStructCreate("ubyte lData[" & (abs($Stride) * $Height-1) & "]", $Scan0)
    $BMPDataStart = $BMPDataStart & DllStructGetData($pixeldata,"lData")

    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
    _GDIPlus_ImageDispose ($pBitmap)
    _WinAPI_DeleteObject ($pBitmap)

EndFunc;==>GetImage
; Draw rectangle on screen.
Func _UIA_DrawRect($tLeft, $tRight, $tTop, $tBottom, $color = 0xFF, $PenWidth = 4)
    Local $hDC, $hPen, $obj_orig, $x1, $x2, $y1, $y2
    $x1 = $tLeft
    $x2 = $tRight
    $y1 = $tTop
    $y2 = $tBottom
    $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop)
    $hPen = _WinAPI_CreatePen($PS_SOLID, $PenWidth, $color)
    $obj_orig = _WinAPI_SelectObject($hDC, $hPen)

    _WinAPI_DrawLine($hDC, $x1, $y1, $x2, $y1) ; horizontal to right
    _WinAPI_DrawLine($hDC, $x2, $y1, $x2, $y2) ; vertical down on right
    _WinAPI_DrawLine($hDC, $x2, $y2, $x1, $y2) ; horizontal to left right
    _WinAPI_DrawLine($hDC, $x1, $y2, $x1, $y1) ; vertical up on left

    ; clear resources
    _WinAPI_SelectObject($hDC, $obj_orig)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_ReleaseDC(0, $hDC)
EndFunc   ;==>_UIA_DrawRect
#EndRegion

 

Edited by junkew
Posted
On 1/22/2025 at 3:14 AM, Hashim said:

and can provide more examples if needed

Some examples where the first digit is 1, preferable 10 images where all 0 through 9 is the first digit, now that they are cursive.

The loop probably wont be as simple as in the old thread, but need the images to be sure.

Some guy's script + some other guy's script = my script!

Posted (edited)

Here another way based on relative pixel location from the first (left/top most) pixel using my ScreenScraping UDF.  Coordinates are screen absolute location.

#include "C:\Apps\AutoIt\GetScreen\GetScreen.au3"
#include <Color.au3>

Local $hWnd = WinActivate("Microsoft Office Picture Manager")
WinWaitActive($hWnd)

Global Const $LINE = 423, $COLUMN = 550, $ENDX = 690, $ENDY = 465, $NDIGIT = 4
Global $aDigit = DefineNum()
_GetScreen_Initialize($ENDX, $ENDY)

Local $hTimer = TimerInit()
_GetScreen_GetScreen()

Local $iPos = $COLUMN, $vValue
For $i = 1 To $NDIGIT
  $vValue &= GetDigit($iPos)
  $iPos = @extended
Next
ConsoleWrite($vValue & @CRLF)
ConsoleWrite(TimerDiff($hTimer) & @CRLF)

Func GetDigit($iStart)
  Local $aTmp
  For $i = $iStart To $ENDX
    If IsColor(_GetScreen_GetPixel($i, $LINE)) Then
      For $j = 0 To UBound($aDigit) - 1
        $aTmp = $aDigit[$j][2]
        For $k = 0 To UBound($aTmp) - 1
          If Not IsColor(_GetScreen_GetPixel($i + $aTmp[$k][0], $LINE + $aTmp[$k][1])) Then ContinueLoop 2
        Next
        Return SetExtended($i + $aDigit[$j][1], $aDigit[$j][0])
      Next
      ConsoleWrite("error" & @CRLF)
      Return SetError(1)
    EndIf
  Next
EndFunc   ;==>GetDigit

Func DefineNum()
  Local $aNum[10][3] = [[0, 14, 0], [1, 4, 0], [2, 14, 0], [8, 14, 0], [3, 14, 0], [5, 24, 0], [7, 24, 0], [4, 4, 0], [9, 24, 0], [6, 10, 0]]
  Local $aTmp = [[13, 15], [-3, 20], [9, 10]]         ; 0
  $aNum[0][2] = $aTmp
  Local $aTmp = [[-1, 10], [-2, 15], [-9, 30]]        ; 1
  $aNum[1][2] = $aTmp
  Local $aTmp = [[-3, 20], [-9, 30], [11, 30]]        ; 2
  $aNum[2][2] = $aTmp
  Local $aTmp = [[-4, 10], [-8, 20], [-2, 15]]        ; 8
  $aNum[3][2] = $aTmp
  Local $aTmp = [[8, 15], [3, 15], [-6, 5], [11, 25]] ; 3
  $aNum[4][2] = $aTmp
  Local $aTmp = [[20, 0], [4, 10], [9, 10]]           ; 5
  $aNum[5][2] = $aTmp
  Local $aTmp = [[20, 0], [19, 5], [2, 20]]           ; 7
  $aNum[6][2] = $aTmp
  Local $aTmp = [[2, 20], [-18, 20], [-4, 25]]        ; 4
  $aNum[7][2] = $aTmp
  Local $aTmp = [[-6, 10], [-2, 15], [6, 25]]         ; 9
  $aNum[8][2] = $aTmp
  Local $aTmp = [[-12, 15], [-14, 25], [6, 25]]       ; 6
  $aNum[9][2] = $aTmp
  Return $aNum
EndFunc   ;==>DefineNum

Func IsColor($nColor)
  Return Not _ColorGetRed($nColor) And Not _ColorGetBlue($nColor) And _ColorGetGreen($nColor) > Dec("FA")
EndFunc

$LINE must be the first line (top most) where the bright green color appears
$COLUMN can be located somewhere before
$ENDX can be anywhere right after the 4 digits
$ENDY can be anywhere below under the 4 digits

Tested on your 4 pics and it is working fine (and quite fast under 40ms)

Edited by Nine
Posted

ChatGPT nows how to crunch this😀

Upload the pictures
Question: In each picture there are 4 numbers can you recognize them?

Answer:    Here are the numbers I recognize from the images:

  1. Image 1 (pic1.png): The number is 2409.
  2. Image 2 (pic2.png): The number is 0257.
  3. Image 3 (pic3.png): The number is 8035.
  4. Image 4 (pic4.png): The number is 4691.
  • 2 weeks later...
Posted (edited)
On 1/22/2025 at 8:18 PM, junkew said:

 

Maybe this helps a little in understanding. 
Its just manipulation of pixels in a certan layout (PNG). 
Look at the output and zoom in/out, you can see almost the numbers yourself 

#Region includes
Opt('MustDeclareVars', 1)
;#include <GUIConstants.au3>
#include <GDIPlus.au3>
#Include <ScreenCapture.au3>
#include <string.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#EndRegion

_GDIPlus_Startup()

Dim $BitmapFilename
Dim $BMPData="", $BMPWidth=0, $BMPHeight=0, $BMPLineWidth=0, $imgBytes=1
dim $binaryLine

for $i=1 to 4
    $BitmapFilename = @TempDir & "\" & "pic" & string($i) & ".png"
        $BMPData=""
        $BMPWidth=0
        $BMPHeight=0
        $BMPLineWidth=0
        $imgBytes=1
        consolewrite($bitmapFileName)

; Load the bitmap to find
    getImage($BitmapFilename, $BMPData, $BMPWidth, $BMPHeight, $BMPLineWidth, $imgBytes)

    ;~ See the height and width and dump the data on screen
    consolewrite($BMPHeight & " ; ")
    consolewrite($BMPWidth &@CRLF )
    consolewrite("0         1         2         3         4         5         6         7         8         9         x         x         x         x         " & @CRLF)
    consolewrite("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" & @CRLF)
    For $iLine = 11 To $BMPHeight-12

    ;~  From the screenshots we can ignore the first 16 bytes (remember in text its 2 characters
    ;~  $binaryLine=BinaryMid($bmp1Data,($i*$BMP1LineWidth)+16,$BMP1LineWidth)
    ;~  and we only need 4 digits which takes about 28 characters and 1 character separator =
        $binaryLine=BinaryMid($bmpData,($iLine *$BMPLineWidth)+16,60)
;~ Lets make it readable
        $binaryLine=StringReplace($binaryLine,"0",".")

        consolewrite($iLine & " : " & $binaryLine & @CRLF)
    next

;~  lets recognise
    for $iNumber=1 to 4

        consolewrite(@crlf)
            consolewrite("0         1         2         3         4         5         6         7         8         9         x         x         x         x         " & @CRLF)
    consolewrite("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" & @CRLF)

        For $iLine = 11 To $BMPHeight-12
            $binaryLine=BinaryMid($bmpData,($iLine *$BMPLineWidth)+16+(($iNumber-1)*15),14)
            $binaryLine=StringReplace($binaryLine,"0",".")
            consolewrite($iLine & " : " & $binaryLine & @CRLF)
        next
    Next

Next

_GDIPlus_Shutdown()

Func GetImage($BMPFile, byref $BMPDataStart, byref $Width, byRef $Height, byref $Stride, $imgBytes=3)
local $Scan0, $pixelData, $hbScreen, $pBitmap, $pBitmapCap, $handle, $bitMapdata, $pixelFormat

; Load the bitmap to search in
    If $BMPFile="SCREEN" Then
        $hbScreen=_ScreenCapture_Capture("",0,0,-1,-1,False)
        $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    Else
;try to get a handle
        $handle = WinGetHandle($BMPFile)
        If @error Then
;Assume its an unknown handle so correct filename should be given
            $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
;~          $hBitmap = _GDIPlus_ImageLoadFromFile($BMPFile)
        Else
            $hbScreen=_ScreenCapture_CaptureWnd("",$handle,0,0,-1,-1,False)
            $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
        EndIf
    EndIf

;Get $tagGDIPBITMAPDATA structure
  ConsoleWrite("Bitmap Width:    " & _GDIPlus_ImageGetWidth($pBitmap) & @CRLF )
  ConsoleWrite("Bitmap Height:      " & _GDIPlus_ImageGetHeight($pBitmap) & @CRLF)

;~  24 bits (3 bytes) or 16 bits (2 bytes) comparison
    if ($imgBytes=1) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD,  $GDIP_PXF04INDEXED)
    Endif
    if ($imgBytes=2) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF16RGB555)
;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    EndIf
    if ($imgBytes=3) then
        $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB)
;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    endIf

    If @ERROR Then MsgBox(0,"","Error locking region " & @error)

    $Stride = DllStructGetData($BitmapData, "Stride");Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
    $Width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap.
    $Height = DllStructGetData($BitmapData, "Height");Image height - Number of scan lines in the bitmap.
    $PixelFormat = DllStructGetData($BitmapData, "PixelFormat");Pixel format - Integer that specifies the pixel format of the bitmap
    $Scan0 = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap.

    $pixelData = DllStructCreate("ubyte lData[" & (abs($Stride) * $Height-1) & "]", $Scan0)
    $BMPDataStart = $BMPDataStart & DllStructGetData($pixeldata,"lData")

    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
    _GDIPlus_ImageDispose ($pBitmap)
    _WinAPI_DeleteObject ($pBitmap)

EndFunc;==>GetImage
; Draw rectangle on screen.
Func _UIA_DrawRect($tLeft, $tRight, $tTop, $tBottom, $color = 0xFF, $PenWidth = 4)
    Local $hDC, $hPen, $obj_orig, $x1, $x2, $y1, $y2
    $x1 = $tLeft
    $x2 = $tRight
    $y1 = $tTop
    $y2 = $tBottom
    $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop)
    $hPen = _WinAPI_CreatePen($PS_SOLID, $PenWidth, $color)
    $obj_orig = _WinAPI_SelectObject($hDC, $hPen)

    _WinAPI_DrawLine($hDC, $x1, $y1, $x2, $y1) ; horizontal to right
    _WinAPI_DrawLine($hDC, $x2, $y1, $x2, $y2) ; vertical down on right
    _WinAPI_DrawLine($hDC, $x2, $y2, $x1, $y2) ; horizontal to left right
    _WinAPI_DrawLine($hDC, $x1, $y2, $x1, $y1) ; vertical up on left

    ; clear resources
    _WinAPI_SelectObject($hDC, $obj_orig)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_ReleaseDC(0, $hDC)
EndFunc   ;==>_UIA_DrawRect
#EndRegion



I assume you refer to 

 

Yes, that's the original thread

Thank you for your in-depth explanations, I sort of  understand how this particular method of creating each bitmap and comparing them works, which how Werty's earlier script worked, but the part that's way over my head is the latest iteration of his script in my OP, which seems to use a different method entirely and do everything using `DllStructGetData()` and constants like 680 and 16 and 32.

On 1/23/2025 at 10:16 PM, junkew said:

ChatGPT nows how to crunch this😀

Upload the pictures
Question: In each picture there are 4 numbers can you recognize them?

Answer:    Here are the numbers I recognize from the images:

  1. Image 1 (pic1.png): The number is 2409.
  2. Image 2 (pic2.png): The number is 0257.
  3. Image 3 (pic3.png): The number is 8035.
  4. Image 4 (pic4.png): The number is 4691.

I think you might be misunderstanding, the images are just examples, I'm trying to do this using a tool that generates its result in a bitmap font.

On 1/23/2025 at 3:35 AM, Werty said:

Some examples where the first digit is 1, preferable 10 images where all 0 through 9 is the first digit, now that they are cursive.

The loop probably wont be as simple as in the old thread, but need the images to be sure.

Apologies for the late reply, but now done and uploaded, thank you!

On 1/23/2025 at 5:55 PM, Nine said:

Here another way based on relative pixel location from the first (left/top most) pixel using my ScreenScraping UDF.  Coordinates are screen absolute location.

#include "C:\Apps\AutoIt\GetScreen\GetScreen.au3"
#include <Color.au3>

Local $hWnd = WinActivate("Microsoft Office Picture Manager")
WinWaitActive($hWnd)

Global Const $LINE = 423, $COLUMN = 550, $ENDX = 690, $ENDY = 465, $NDIGIT = 4
Global $aDigit = DefineNum()
_GetScreen_Initialize($ENDX, $ENDY)

Local $hTimer = TimerInit()
_GetScreen_GetScreen()

Local $iPos = $COLUMN, $vValue
For $i = 1 To $NDIGIT
  $vValue &= GetDigit($iPos)
  $iPos = @extended
Next
ConsoleWrite($vValue & @CRLF)
ConsoleWrite(TimerDiff($hTimer) & @CRLF)

Func GetDigit($iStart)
  Local $aTmp
  For $i = $iStart To $ENDX
    If IsColor(_GetScreen_GetPixel($i, $LINE)) Then
      For $j = 0 To UBound($aDigit) - 1
        $aTmp = $aDigit[$j][2]
        For $k = 0 To UBound($aTmp) - 1
          If Not IsColor(_GetScreen_GetPixel($i + $aTmp[$k][0], $LINE + $aTmp[$k][1])) Then ContinueLoop 2
        Next
        Return SetExtended($i + $aDigit[$j][1], $aDigit[$j][0])
      Next
      ConsoleWrite("error" & @CRLF)
      Return SetError(1)
    EndIf
  Next
EndFunc   ;==>GetDigit

Func DefineNum()
  Local $aNum[10][3] = [[0, 14, 0], [1, 4, 0], [2, 14, 0], [8, 14, 0], [3, 14, 0], [5, 24, 0], [7, 24, 0], [4, 4, 0], [9, 24, 0], [6, 10, 0]]
  Local $aTmp = [[13, 15], [-3, 20], [9, 10]]         ; 0
  $aNum[0][2] = $aTmp
  Local $aTmp = [[-1, 10], [-2, 15], [-9, 30]]        ; 1
  $aNum[1][2] = $aTmp
  Local $aTmp = [[-3, 20], [-9, 30], [11, 30]]        ; 2
  $aNum[2][2] = $aTmp
  Local $aTmp = [[-4, 10], [-8, 20], [-2, 15]]        ; 8
  $aNum[3][2] = $aTmp
  Local $aTmp = [[8, 15], [3, 15], [-6, 5], [11, 25]] ; 3
  $aNum[4][2] = $aTmp
  Local $aTmp = [[20, 0], [4, 10], [9, 10]]           ; 5
  $aNum[5][2] = $aTmp
  Local $aTmp = [[20, 0], [19, 5], [2, 20]]           ; 7
  $aNum[6][2] = $aTmp
  Local $aTmp = [[2, 20], [-18, 20], [-4, 25]]        ; 4
  $aNum[7][2] = $aTmp
  Local $aTmp = [[-6, 10], [-2, 15], [6, 25]]         ; 9
  $aNum[8][2] = $aTmp
  Local $aTmp = [[-12, 15], [-14, 25], [6, 25]]       ; 6
  $aNum[9][2] = $aTmp
  Return $aNum
EndFunc   ;==>DefineNum

Func IsColor($nColor)
  Return Not _ColorGetRed($nColor) And Not _ColorGetBlue($nColor) And _ColorGetGreen($nColor) > Dec("FA")
EndFunc

$LINE must be the first line (top most) where the bright green color appears
$COLUMN can be located somewhere before
$ENDX can be anywhere right after the 4 digits
$ENDY can be anywhere below under the 4 digits

Tested on your 4 pics and it is working fine (and quite fast under 40ms)

Thanks for the new solution, I had a go at implementing it but can't seem to get it recognising anything, possibly because I don't really understand `$line` and `$column` and how to get them. I'm using the Finder Tool to get mouse position of the topmost line of green pixels, but this gives an X and Y. If I use Y for `$line` (assuming it's a horizontal line), do I use x for `$column`? You said `$column` should be before `$line` but your `$column` value seems to be higher than your `$line` value. No matter what value I experiment with I always seem to get zeroes back:

000000,0000,50.0049 elapsed
000001,0000,54.0431 elapsed
000002,0000,54.8198 elapsed
000003,0000,53.7282 elapsed
000004,0000,56.0365 elapsed
000005,0000,61.0202 elapsed
000006,0000,47.72 elapsed
000007,0000,55.0063 elapsed
000008,0000,53.913 elapsed
000009,0000,54.7191 elapsed
000010,0000,54.0476 elapsed
000011,0000,55.3895 elapsed
000012,0000,55.3364 elapsed
000013,0000,53.8888 elapsed
000014,0000,54.61 elapsed
000015,0000,57.5293 elapsed
000016,0000,52.4981 elapsed
000017,0000,54.5434 elapsed
000018,0000,54.3221 elapsed
000019,0000,55.6746 elapsed
000020,0000,55.1158 elapsed
000021,0000,52.4392 elapsed
000022,0000,73.5602 elapsed
000023,0000,56.2109 elapsed
000024,0000,49.5609 elapsed
000025,0000,56.3362 elapsed
000026,0000,53.4462 elapsed
000027,0000,55.8478 elapsed
000028,0000,53.6302 elapsed
000029,0000,63.1837 elapsed
000030,0000,53.3006 elapsed
000031,0000,59.3485 elapsed
000032,0000,48.4816 elapsed
000033,0000,53.8227 elapsed
000034,0000,54.4319 elapsed
000035,0000,50.9141 elapsed
000036,0000,55.2572 elapsed
000037,0000,53.6521 elapsed
000038,0000,53.3899 elapsed
000039,0000,63.4227 elapsed
000040,0000,48.0815 elapsed
000041,0000,52.6406 elapsed
000042,0000,56.4394 elapsed
000043,0000,54.0514 elapsed
000044,0000,53.8471 elapsed
000045,0000,64.8552 elapsed
000046,0000,63.9074 elapsed
000047,0000,52.5829 elapsed
000048,0000,54.945 elapsed
000049,0000,54.3817 elapsed
000050,0000,55.7925 elapsed

 

examples.zip

Edited by Hashim
Posted (edited)

I get perfect match with the new files you gave us.  The problem you have to solve is "where those images are located in your real world".  You need to help yourself.   Ok maybe my explaination was not good enough :

$LINE must be the first line (top most) where the bright green color appears (the Y value)
$COLUMN can be located somewhere before the digits (the X value)
$ENDX can be anywhere right after the 4 digits (...)
$ENDY can be anywhere below under the 4 digits (...)

ps. only important value is $LINE, rest does not need to be precise : $COLUMN can be 0, $ENDX can be @DESKTOPwIDTH, $ENDY can be @desktopHEIGHT

Here a picture of the pixel you want : $LINE is the Y and $COLUMN is the X (in absolute screen coordinates)

image.png.17ea1d0106ddf1418300582e25a97840.png

Edited by Nine
Posted
3 hours ago, Hashim said:

...but can't seem to get...

I butcher the heck out of it

Spoiler
#Region includes
Opt('MustDeclareVars', 1)
;#include <GUIConstants.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <string.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#EndRegion includes

_GDIPlus_Startup() ;;; https://www.autoitscript.com/forum/topic/212651-another-bitmap-brute-forcing-thread/#findComment-1540438

Global $hTimer = TimerInit()
Dim $BitmapFilename
Dim $BMPData = "", $BMPWidth = 0, $BMPHeight = 0, $BMPLineWidth = 0, $imgBytes = 2
Dim $binaryLine, $startColumn
Dim $lineData11, $lineData27, $lineData41, $NumberWidth = 15, $NumberCount = 4 ; added by argumentum
;~ for each picture file
For $i = 0 To 9
;~  $BitmapFilename = @TempDir & "\" & "pic" & String($i) & ".png"
    $BitmapFilename = @ScriptDir & "\" & String($i) & ".png"
    $BMPData = ""
    $BMPWidth = 0
    $BMPHeight = 0
    $BMPLineWidth = 0
    $imgBytes = 1
    ConsoleWrite(@CRLF & $BitmapFilename & @TAB)

    ; Load the bitmap to find
    GetImage($BitmapFilename, $BMPData, $BMPWidth, $BMPHeight, $BMPLineWidth, $imgBytes)

;~ See the height and width and dump the data on screen
;~  ConsoleWrite($BMPHeight & " ; " & $BMPWidth & @CRLF)
;~  ConsoleWrite("       0         1         2         3         4         5         6         7         8         9         x         x         x         x         " & @CRLF)
;~  ConsoleWrite("       01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" & @CRLF)
;~  For $iLine = 11 To $BMPHeight - 12
    For $iLine = 0 To $BMPHeight - $NumberWidth

;~  From the screenshots we can ignore the first 16 bytes (remember in text its 2 characters
;~  $binaryLine=BinaryMid($bmp1Data,($i*$BMP1LineWidth)+16,$BMP1LineWidth)
;~  and we only need 4 digits which takes about 28 characters and 1 character separator =
        $binaryLine = BinaryMid($BMPData, ($iLine * $BMPLineWidth) + $NumberWidth, $NumberWidth * $NumberCount)
;~      $binaryLine=$bmpData
;~ Lets make it readable
        $binaryLine = StringReplace($binaryLine, "0", ".")

;~      ConsoleWrite($iLine & " : " & $binaryLine & @CRLF)
    Next

;~  lets recognise
    For $iNumber = 1 To $NumberCount

;~      ConsoleWrite(@CRLF)
;~          ConsoleWrite("0   -     1         2         3         4         5         6         7         8         9         x         x         x         x         " & @CRLF)
;~          ConsoleWrite("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" & @CRLF)

;~  Its hard to determine the column for each digit in a formula
;~      If $iNumber = 1 Then $startColumn = 16
;~      If $iNumber = 2 Then $startColumn = 30
;~      If $iNumber = 3 Then $startColumn = 45
;~      If $iNumber = 4 Then $startColumn = 59

        $startColumn = $NumberWidth * $iNumber

;~ Only a few lines in the png are of interest

;~          For $iLine = 11 To $BMPHeight - 12
;~  ;~          $binaryLine=BinaryMid($bmpData,($iLine *$BMPLineWidth)+16+(($iNumber-1)*14),15)
;~              $binaryLine = BinaryMid($BMPData, ($iLine * $BMPLineWidth) + $startColumn, 15)


;~              $binaryLine = StringReplace($binaryLine, "0", " ")
;~              ConsoleWrite($iLine & " : " & $binaryLine & @CRLF)
;~          Next
;~      if on line 11 at position 28 I have a B it can be a 4

;~ It seems to be easier to revert back to a string when we have the data
        $lineData11 = StringStripWS(StringRegExpReplace(BinaryMid($BMPData, (11 * $BMPLineWidth) + $startColumn, $NumberWidth), "[x0]", " "), 3)
        $lineData27 = StringStripWS(StringRegExpReplace(BinaryMid($BMPData, (27 * $BMPLineWidth) + $startColumn, $NumberWidth), "[x0]", " "), 3)
        $lineData41 = StringStripWS(StringRegExpReplace(BinaryMid($BMPData, (41 * $BMPLineWidth) + $startColumn, $NumberWidth), "[x0]", " "), 3)

;~      ConsoleWrite(String($lineData11) & " - ")
;~      ConsoleWrite(String($lineData27) & " - ")
;~      ConsoleWrite(String($lineData41) & @CRLF)

;~ And here determine the magic lines

        If (($lineData11 = "BBB") And ($lineData27 = "B222B          B222B")) Then ConsoleWrite("4")
        If (($lineData11 = "BBB  BBB") And ($lineData27 = "B222BB222BB222BB222B")) Then ConsoleWrite("6")
        If (($lineData11 = "BBB  BBB  BBB") And ($lineData27 = "B222BB222BB222BB222B")) Then ConsoleWrite("9")
        If (($lineData11 = "BBB") And ($lineData27 = "B222B")) Then ConsoleWrite("1")

        If (($lineData11 = "BBB  BBB  BBB") And ($lineData27 = "B222BB222BB222B")) Then ConsoleWrite("8")
        If (($lineData11 = "BBB  BBB  BBB") And ($lineData27 = "B222B     B222B     B222B")) Then ConsoleWrite("0")

        If (($lineData11 = "BBB  BBB  BBB") And ($lineData27 = "B222BB222B") And ($lineData41 = "BBB  BBB  BBB")) Then ConsoleWrite("3")
        If (($lineData11 = "BBB  BBB  BBB") And ($lineData27 = "B222BB222B") And ($lineData41 = "BBB  BBB  BBB  BBB  BBB")) Then ConsoleWrite("2")

        If (($lineData11 = "BBB  BBB  BBB  BBB  BBB") And ($lineData27 = "B222B") And ($lineData41 = "BBB")) Then ConsoleWrite("7")
        If (($lineData11 = "BBB  BBB  BBB  BBB  BBB") And ($lineData27 = "B222B") And ($lineData41 = "BBB  BBB  BBB")) Then ConsoleWrite("5")
    Next
;~  ConsoleWrite(@CRLF)
Next


ConsoleWrite(@CRLF & "TimerDiff: " & TimerDiff($hTimer) & @CRLF)
_GDIPlus_Shutdown()

Func GetImage($BMPFile, ByRef $BMPDataStart, ByRef $Width, ByRef $Height, ByRef $Stride, $imgBytes = 3)
    Local $Scan0, $pixelData, $hbScreen, $pBitmap, $pBitmapCap, $handle, $bitMapdata, $pixelFormat

    ; Load the bitmap to search in
    If $BMPFile = "SCREEN" Then
        $hbScreen = _ScreenCapture_Capture("", 0, 0, -1, -1, False)
        $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen) ; returns memory bitmap
    Else
        ;try to get a handle
        $handle = WinGetHandle($BMPFile)
        If @error Then
            ;Assume its an unknown handle so correct filename should be given
            $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
;~          $hBitmap = _GDIPlus_ImageLoadFromFile($BMPFile)
        Else
            $hbScreen = _ScreenCapture_CaptureWnd("", $handle, 0, 0, -1, -1, False)
            $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen) ; returns memory bitmap
        EndIf
    EndIf

    ;Get $tagGDIPBITMAPDATA structure
;~  ConsoleWrite("Bitmap Width:    " & _GDIPlus_ImageGetWidth($pBitmap) & @CRLF)
;~  ConsoleWrite("Bitmap Height:      " & _GDIPlus_ImageGetHeight($pBitmap) & @CRLF)

;~  24 bits (3 bytes) or 16 bits (2 bytes) comparison
    If ($imgBytes = 1) Then
        $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF04INDEXED)
    EndIf
    If ($imgBytes = 2) Then
        $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF16RGB555)
;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    EndIf
    If ($imgBytes = 3) Then
        $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB)
;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    EndIf

    If @error Then MsgBox(0, "", "Error locking region " & @error)

    $Stride = DllStructGetData($BitmapData, "Stride") ;Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
    $Width = DllStructGetData($BitmapData, "Width") ;Image width - Number of pixels in one scan line of the bitmap.
    $Height = DllStructGetData($BitmapData, "Height") ;Image height - Number of scan lines in the bitmap.
    $PixelFormat = DllStructGetData($BitmapData, "PixelFormat") ;Pixel format - Integer that specifies the pixel format of the bitmap
    $Scan0 = DllStructGetData($BitmapData, "Scan0") ;Scan0 - Pointer to the first (index 0) scan line of the bitmap.

    $pixelData = DllStructCreate("ubyte lData[" & (Abs($Stride) * $Height - 1) & "]", $Scan0)
    $BMPDataStart = $BMPDataStart & DllStructGetData($pixelData, "lData")

    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
    _GDIPlus_ImageDispose($pBitmap)
    _WinAPI_DeleteObject($pBitmap)

EndFunc   ;==>GetImage
; Draw rectangle on screen.
Func _UIA_DrawRect($tLeft, $tRight, $tTop, $tBottom, $color = 0xFF, $PenWidth = 4)
    Local $hDC, $hPen, $obj_orig, $x1, $x2, $y1, $y2
    $x1 = $tLeft
    $x2 = $tRight
    $y1 = $tTop
    $y2 = $tBottom
    $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop)
    $hPen = _WinAPI_CreatePen($PS_SOLID, $PenWidth, $color)
    $obj_orig = _WinAPI_SelectObject($hDC, $hPen)

    _WinAPI_DrawLine($hDC, $x1, $y1, $x2, $y1) ; horizontal to right
    _WinAPI_DrawLine($hDC, $x2, $y1, $x2, $y2) ; vertical down on right
    _WinAPI_DrawLine($hDC, $x2, $y2, $x1, $y2) ; horizontal to left right
    _WinAPI_DrawLine($hDC, $x1, $y2, $x1, $y1) ; vertical up on left

    ; clear resources
    _WinAPI_SelectObject($hDC, $obj_orig)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_ReleaseDC(0, $hDC)
EndFunc   ;==>_UIA_DrawRect
#EndRegion

and I hope that by doing so, it makes more sense. Maybe.

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

Posted
17 hours ago, Hashim said:

done and uploaded

Well, appears it would be as simple a loop as the first one...

Func Getnumber($result)
    
    Local $code[4] = [0,0,0,0], $value = 64, $pixels = DllStructCreate('dword[2816]')
    DllCall('gdi32.dll', 'dword', 'GetBitmapBits', 'ptr', $capture, 'dword', DllStructGetSize($pixels), 'ptr', DllStructGetPtr($pixels))

For $loop = 1 To 2816 Step 440
    $code[0] += DllStructGetData($pixels, 1, $loop   ) > 4278190080 ? $value:0
    $code[1] += DllStructGetData($pixels, 1, $loop+29) > 4278190080 ? $value:0
    $code[2] += DllStructGetData($pixels, 1, $loop+58) > 4278190080 ? $value:0
    $code[3] += DllStructGetData($pixels, 1, $loop+87) > 4278190080 ? $value:0
    $value /= 2
Next
    Return String($digit[$code[0]]) & String($digit[$code[1]]) & String($digit[$code[2]]) & String($digit[$code[3]])
EndFunc

Runable example (requires the images from above)...

#include <GDIPlus.au3>
#include <WinAPI.au3>
HotKeySet("{ESC}", "_exit")


;Be sure $posx and $posy is pointing at the correct spot!
Global $posx = 1715, $posy = 705, $result = "", $code[4], $capture
;Lookup table to avoid searching
Global $digit[115] = [1,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0, _
                      0,0,0,0,0,0,0,0,0,0,6,0,0,0,3,2,0,0,0,0, _
                      0,0,0,0,0,0,0,0,9,0,0,0,0,0,8,0,0,0,0,0, _
                      0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, _
                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, _
                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,5]
;Test section
;--------------------------------------------------------------
$gui = GUICreate("Getnumber", 640, 480, -1, -1)
       GUISetState()
       WinWaitActive($gui); <--- necessary or screencapture fails

            _GDIPlus_Startup()
$graphics = _GDIPlus_GraphicsCreateFromHWND($gui)
   $image = _GDIPlus_BitmapCreateFromFile("9.png")
            _GDIPlus_GraphicsDrawImageRect($graphics, $image, 280, 200, 176, 56)
Sleep(10); <------- necessary because drawimagerect() is too slow, script occasionally fails without
;--------------------------------------------------------------
;/Test section

    $hDDC = _WinAPI_GetDC(0)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
 $capture = _WinAPI_CreateCompatibleBitmap($hDDC, 88, 32)
            _WinAPI_SelectObject($hCDC, $capture)
            _WinAPI_BitBlt($hCDC, 0, 0, 88, 32, $hDDC, $posx, $posy, 0x00CC0020)
            _WinAPI_DeleteDC($hCDC)

$result = Getnumber($result)


Consolewrite("Result: " & $result & @crlf)

While 1
   Sleep(10)
WEnd

Func Getnumber($result)
    
    Local $code[4] = [0,0,0,0], $value = 64, $pixels = DllStructCreate('dword[2816]')
    DllCall('gdi32.dll', 'dword', 'GetBitmapBits', 'ptr', $capture, 'dword', DllStructGetSize($pixels), 'ptr', DllStructGetPtr($pixels))

For $loop = 1 To 2816 Step 440
    $code[0] += DllStructGetData($pixels, 1, $loop   ) > 4278190080 ? $value:0
    $code[1] += DllStructGetData($pixels, 1, $loop+29) > 4278190080 ? $value:0
    $code[2] += DllStructGetData($pixels, 1, $loop+58) > 4278190080 ? $value:0
    $code[3] += DllStructGetData($pixels, 1, $loop+87) > 4278190080 ? $value:0
    $value /= 2
Next
    Return String($digit[$code[0]]) & String($digit[$code[1]]) & String($digit[$code[2]]) & String($digit[$code[3]])
EndFunc

Func _exit()
    _GDIPlus_Shutdown()
    Exit
 EndFunc

And as in the previous thread and as Nine posted above, the $Posx and $Posy must point at the correct spot, which in this case is here (red spot)...

 

 

5.png

Some guy's script + some other guy's script = my script!

Posted (edited)
Quote

If I understood how it worked I'd do it myself

@Hashim Some try to give you more understanding

There are different approaches to "read" from a screen

  1. Have access to the sourcecode or internals of the program (probably Delphi) and based on that you can define your strategy
  2. Intercept Win32 API calls like drawtext (win 32 hooks)
  3. Check the default functions like ControlGetText see Faq 31,34,40 and helpfile. 
  4. Take the more difficult route pixelmanipulation (with GDI32 functions)
    1. @Nine has made a nice library for that which he used on above answer
  5. Use OCR and AI tools like ChatGPT API: https://dorik.com/blog/how-to-use-chatgpt-api
  6. ..... 

Looking at the thread(s) and screenshots approach 4 looks the most realistic one 😉 

The theory around this you can learn here (and google offcourse)

You should start with:

 

your constants misunderstanding

Quote

constants like 680 and 16 and 32

That was for a 3 digit approach to identify the matrix where your digits are.


You shared pictures of 176 width and 56 height and we have to guess where they are on the screen

  • How did you make the screenshots of the numbers? by hand? automated?
    • In your previous thread with 3 digits it was TTabsheet1
  • Share a full screenshot of the application that can help
  • Share information when you hover over the application with au3inf or other spy tools.
    Based on what you shared before it looks like a delphi application

The matrix

The bitblt function takes an x,y and height, width to create a matrix of pixels. Based on that height and width you get the magic constants like 680.

We can only assume with 4 digits of 176 width and 56 height that 4*176=704 width in pixels total matrix and if a pixel takes 2 bytes you come to 1 line of 2816.
Then this can be hard to read but basically says look at the (First) line 7 times and do a calculation

For $loop = 1 To 2816 Step 440
    $code[0] += DllStructGetData($pixels, 1, $loop   ) > 4278190080 ? $value:0
    $code[1] += DllStructGetData($pixels, 1, $loop+29) > 4278190080 ? $value:0
    $code[2] += DllStructGetData($pixels, 1, $loop+58) > 4278190080 ? $value:0
    $code[3] += DllStructGetData($pixels, 1, $loop+87) > 4278190080 ? $value:0
    $value /= 2
Next

So look at these pixels (the algorithm that was determined to be enough to discriminate numbers from each other): 
[1 30 59 88], [441 470 499 528],[881 910 939 968],[1321 1350 1379 1408],[1761 1790 1819 1848],[2201 2230 2259 2288],[2641 2670 2699 2728]

1 pixel can be described in multiple bits (black/white/monochrome, grey, colour, 16 bits color, 24 bits color, ....) so far we take the approach 16 bits per pixelcolor.

 

The algorithm

Maybe this helps from long ago when I started to learn bitblt and pixelmanipulation. If you merge all 10 numbers in this thread you will know which (minimum number of) pixels you need to check to discriminate 0-9 and the other examples given above are alternative algorithms.

 

 

 

Edited by junkew
Posted (edited)

Here a more comprehensive version of the script I made above.  I may add the following as an additional example of my UDF.  With this new version, you do not have to find the top line of the bright-green color, it will do it for you.  You just need to provide the top, left, right, bottom of the whole black square, along with the number of digits to read.  (in absolute screen coordinates)

#include "C:\Apps\AutoIt\GetScreen\GetScreen.au3"
#include <Color.au3>

Opt("MustDeclareVars", True)

Local $hWnd = WinActivate("Microsoft Office Picture Manager")
WinWaitActive($hWnd)
Global $aDigit = DefineNum()
_GetScreen_Initialize(@DesktopWidth, @DesktopHeight)
For $i = 1 To 10  ; number of pictures I test
  ReadNumber(535, 397, 710, 451, 4)  ; top-left of the square .. bottom-right of the square .. Number of digits to read
  Send("{RIGHT}")  ; move to the next picture
  Sleep(500)
Next

Func ReadNumber($iLeft, $iTop, $iRight, $iBottom, $iNumDigit)
  Local $hTimer = TimerInit()
  _GetScreen_GetScreen()
  ; Static will execute this only once, since top bright-green pixel is always located on the same top Y
  Local Static $iPosY = SearchColor($iLeft, $iTop, $iRight, $iBottom)
  Local $iPosX = $iLeft, $sValue
  For $i = 1 To $iNumDigit
    $sValue &= GetDigit($iPosX, $iPosY, $iRight)
    $iPosX = @extended
  Next
  ConsoleWrite($sValue & @CRLF)
  ConsoleWrite(TimerDiff($hTimer) & @CRLF)
  Return Int($sValue) ; in case you want to return the integer read
EndFunc   ;==>ReadNumber

Func GetDigit($iStart, $iTop, $iEndX)
  For $i = $iStart To $iEndX
    If IsColor(_GetScreen_GetPixel($i, $iTop)) Then
      For $j = 0 To UBound($aDigit) - 1
        For $k = 0 To UBound($aDigit[$j][2]) - 1
          If Not IsColor(_GetScreen_GetPixel($i + ($aDigit[$j][2])[$k][0], $iTop + ($aDigit[$j][2])[$k][1])) Then ContinueLoop 2
        Next
        Return SetExtended($i + $aDigit[$j][1], $aDigit[$j][0])
      Next
      Return SetError(1) ; no digit found
    EndIf
  Next
  Return SetError(2) ; no green bright color found
EndFunc   ;==>GetDigit

Func DefineNum()
  Local $aNum[10][3] = [[0, 14, 0], [1, 4, 0], [2, 14, 0], [8, 14, 0], [3, 14, 0], [5, 24, 0], [7, 24, 0], [4, 4, 0], [9, 24, 0], [6, 10, 0]]
  Local $aTmp = [[13, 15], [-3, 20], [9, 10]]         ; 0
  $aNum[0][2] = $aTmp
  Local $aTmp = [[-1, 10], [-2, 15], [-9, 30]]        ; 1
  $aNum[1][2] = $aTmp
  Local $aTmp = [[-3, 20], [-9, 30], [11, 30]]        ; 2
  $aNum[2][2] = $aTmp
  Local $aTmp = [[-4, 10], [-8, 20], [-2, 15]]        ; 8
  $aNum[3][2] = $aTmp
  Local $aTmp = [[8, 15], [3, 15], [-6, 5], [11, 25]] ; 3
  $aNum[4][2] = $aTmp
  Local $aTmp = [[20, 0], [4, 10], [9, 10]]           ; 5
  $aNum[5][2] = $aTmp
  Local $aTmp = [[20, 0], [19, 5], [2, 20]]           ; 7
  $aNum[6][2] = $aTmp
  Local $aTmp = [[2, 20], [-18, 20], [-4, 25]]        ; 4
  $aNum[7][2] = $aTmp
  Local $aTmp = [[-6, 10], [-2, 15], [6, 25]]         ; 9
  $aNum[8][2] = $aTmp
  Local $aTmp = [[-12, 15], [-14, 25], [6, 25]]       ; 6
  $aNum[9][2] = $aTmp
  Return $aNum
EndFunc   ;==>DefineNum

Func IsColor($nColor)
  Return Not _ColorGetRed($nColor) And Not _ColorGetBlue($nColor) And _ColorGetGreen($nColor) > Dec("FA")
EndFunc   ;==>IsColor

Func SearchColor($iX1, $iY1, $iX2, $iY2)
  Local $nColor, $iMin = 99999, $aPos
  For $i = 251 To 255
    $nColor = Dec(Hex($i) & "00")
    $aPos = _GetScreen_SearchArea($iX1, $iY1, $iX2, $iY2, $nColor)
    If @error Then ContinueLoop
    If $aPos[1] < $iMin Then $iMin = $aPos[1]
  Next
  If $iMin = 99999 Then Return SetError(1)
  Return $iMin
EndFunc   ;==>SearchColor

It now reads many pictures one at a time.  All results match.

Edited by Nine

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...