Jump to content
Sign in to follow this  
Brickoneer

Finding a picture/bmp/sprite on the screen

Recommended Posts

Brickoneer

Hiya.

My goal was to make a decently-fast function to find a picture on the screen. (Sprite, bmp, whatever.)

The example below runs about 28 milliseconds. If you refine your search more it can be under 20. Searching the entire screen took about 160 milliseconds. (Many things factor into the speed... including the size of the pic, size of the search field, tolerance, and popularity of the first color.)

I kept it for my own personal use for a few months, but finally decided to share it. I'm not that great of a programmer, so what I've done is the quickest, sleaziest possible method that I could come up with.

WARNING: I KNOW VERY LITTLE ABOUT UDF MAKING... THIS IS JUST A SNIPPET TAKEN FROM MY CODE. ITS PROBABLY FULL OF BUGS AND LEAKS. I DIDN'T MAKE IT USER-FRIENDLY... I ASSUMED THE USER WOULD KNOW HOW TO USE IT.

... just so you guys know.

Here is a basic description:

It takes in an array of each pixel color (in hex) and finds that on the screen.

;===============================================================================
; Description:            _PixelSearchPic
; Parameter(s):         $picture - A 2 dimensional array of the hex colors in your "picture"
;                       $transparent - The HEX color used as a 'pallate' color. (i.e. the specified color becomes transparent... it skips that color.)
;                       $ishade - Optional: 0-255 value of the tolerance for the search. WARNING: This magnifies the search time exponentially... use sparingly.
;                       $xTop - Optional: The x-coord of the top-left corner of the search filed. Default is 0.
;                       $yTop - Optional: The y-coord of the top-left corner of the search filed. Default is 0.
;                       $xBottom - Optional: The x-coord of the bottom-right corner of the search filed. Default is @DesktopWidth.
;                       $yBottom - Optional: The y-coord of the bottom-right corner of the search filed. Default is @DesktopHeight.

; Requirement:          ??-Don't know-??

; Return Value(s):    Success: Returns a 2 dimensional array - the x and y coordinates of the upper-left corner of the found picture.
;                       (For example: If the picture is found starting on pixel 123,124 it will return 123,124 in a 2dim array.)
;                     Failure: Returns 0
;                           Sets @ERROR to: 1 - Picture not found on screen
;                                           2 - "Picture" passed to function is not array
;                                           3 - Failed to find beginning pixel in array
;                            
; Author(s):            Many. Compiler of code is Brickoneer... several snippets taken from various others.
;===============================================================================oÝ÷ Ù8Z·­§(§&§v¬µæ§w·ö·¬zÒ!j·¡×­è¦j¬ºË­¢Æ¯z·¬¢êÜzÃh¦§¶)ì*ix-ëæ槭©ÞÅæ§v·v)දz¼Åç.¶*'êÞƪº'${¦¦W¢Ú-殶­¥¨jwkº{aÂ-Â)eµëaz«¨·z®¢Ø§¶ºÚ"¶Z ¡©Ý­ën®{ayÊ(­Ø§j׬jëh×6#include<pixelsearchpic.au3>
Sleep(2000) ;time to let you click over to the autoit homepage.
findpic()

Func findpic()
    $now = TimerInit()
    Local $picture[7][15]
    $picture[0][0] = 0xCECCCD
    $picture[0][1] = 0x181818
    $picture[0][2] = 0x181818
    $picture[0][3] = 0x1F1F1F
    $picture[0][4] = 0x212121
    $picture[0][5] = 0xE6E6E6
    $picture[0][6] = 0xE5E5E5
    $picture[0][7] = 0xE4E4E4
    $picture[0][8] = 0xE4E4E4
    $picture[0][9] = 0xE3E3E3
    $picture[0][10] = 0x080808
    $picture[0][11] = 0x171717
    $picture[0][12] = 0x202020
    $picture[0][13] = 0x2C2C2C
    $picture[0][14] = 0xC4C4C4
    $picture[1][0] = 0xB1AFB0
    $picture[1][1] = 0x1F1F21
    $picture[1][2] = 0x4A4A4A
    $picture[1][3] = 0x606060
    $picture[1][4] = 0x626262
    $picture[1][5] = 0xE6E6E6
    $picture[1][6] = 0xE5E5E5
    $picture[1][7] = 0xE4E4E4
    $picture[1][8] = 0xE4E4E4
    $picture[1][9] = 0xE3E3E3
    $picture[1][10] = 0x191919
    $picture[1][11] = 0x484848
    $picture[1][12] = 0x616161
    $picture[1][13] = 0x606060
    $picture[1][14] = 0xB8B8B8
    $picture[2][0] = 0xB1B0AE
    $picture[2][1] = 0x2D2F2E
    $picture[2][2] = 0x868686
    $picture[2][3] = 0xE8E8E8
    $picture[2][4] = 0xE7E7E7
    $picture[2][5] = 0xE7E7E7
    $picture[2][6] = 0x8E8E8E
    $picture[2][7] = 0x505050
    $picture[2][8] = 0xE4E4E4
    $picture[2][9] = 0xE3E3E3
    $picture[2][10] = 0xE2E2E2
    $picture[2][11] = 0xE2E2E2
    $picture[2][12] = 0x858585
    $picture[2][13] = 0x747474
    $picture[2][14] = 0xBFBFBF
    $picture[3][0] = 0xB2B1AF
    $picture[3][1] = 0x303231
    $picture[3][2] = 0x848484
    $picture[3][3] = 0xE9E9E9
    $picture[3][4] = 0xE7E7E7
    $picture[3][5] = 0xDADADA
    $picture[3][6] = 0x242424
    $picture[3][7] = 0x323232
    $picture[3][8] = 0xAEAEAE
    $picture[3][9] = 0xE4E4E4
    $picture[3][10] = 0xE2E2E2
    $picture[3][11] = 0xE1E1E1
    $picture[3][12] = 0x5F5F5F
    $picture[3][13] = 0x5D5D5D
    $picture[3][14] = 0xBFBFBF
    $picture[4][0] = 0xB2B2B2
    $picture[4][1] = 0x303133
    $picture[4][2] = 0x737373
    $picture[4][3] = 0xA0A0A0
    $picture[4][4] = 0x868686
    $picture[4][5] = 0x494949
    $picture[4][6] = 0x2D2D2D
    $picture[4][7] = 0x696969
    $picture[4][8] = 0x6A6A6A
    $picture[4][9] = 0x8E8E8E
    $picture[4][10] = 0x7E7E7E
    $picture[4][11] = 0x797979
    $picture[4][12] = 0x3B3B3B
    $picture[4][13] = 0x575757
    $picture[4][14] = 0xBEBEBE
    $picture[5][0] = 0xB1B1B1
    $picture[5][1] = 0x323232
    $picture[5][2] = 0x656565
    $picture[5][3] = 0x696969
    $picture[5][4] = 0x4C4C4C
    $picture[5][5] = 0x454545
    $picture[5][6] = 0xA5A5A5
    $picture[5][7] = 0xC5C5C5
    $picture[5][8] = 0x656565
    $picture[5][9] = 0x5C5C5C
    $picture[5][10] = 0x4A4A4A
    $picture[5][11] = 0x404040
    $picture[5][12] = 0x4C4C4C
    $picture[5][13] = 0x696969
    $picture[5][14] = 0xC0C0C0
    $picture[6][0] = 0xE9E9E9
    $picture[6][1] = 0x949494
    $picture[6][2] = 0xA1A1A1
    $picture[6][3] = 0xA9A9A9
    $picture[6][4] = 0xA6A6A6
    $picture[6][5] = 0xB4B4B4
    $picture[6][6] = 0xE5E5E5
    $picture[6][7] = 0xE5E5E5
    $picture[6][8] = 0xBBBBBB
    $picture[6][9] = 0x9D9D9D
    $picture[6][10] = 0xA2A2A2
    $picture[6][11] = 0xA1A1A1
    $picture[6][12] = 0xA2A2A2
    $picture[6][13] = 0xACACAC
    $picture[6][14] = 0xDEDEDE

    ;Search for the pic in a general region where the pic is expected to be.
    $beginpixel = _PixelSearchPic($picture, 0x00FF00, 0, 120, 100, 350, 215)
    If @error <> 0 Then
        ConsoleWrite("Not found in usual spot on 1024x768 screen... searching entire screen..."&@CR)
        ; It didn't find in the usual spot, search whole screen.
        $beginpixel = _PixelSearchPic($picture, 0x00FF00, 0)
        If @error <> 0 Then
            ConsoleWrite("Not found."&@CR)
            SetError(1)
            Return 0
        EndIf
    EndIf
    $picture = 0 ;No need to be using up extra memory.
    ConsoleWrite("Time taken: "&TimerDiff($now) &" Milliseconds."& @CR)
    ConsoleWrite("Found on: "&$beginpixel[0]&" , "&$beginpixel[1] & @CR)
    Return 1
EndFunc   ;==>findpicoÝ÷ Ø̶צ¦Û+zÛ«çZ«Þ­¨¡ý¼)eÇ¢wlIæ«r§Ø^z{b­ë­ç§j÷«jjÝ{Òh¥+rÝ°Ü­æ¬x-ëhêÚÇ¢ÊÞjǬ¶§yç^vئyìi¢w§¶&¥+(mç­çî   l¢Ø^¦nªâ·*¶»-rh®+"+µ©íjÌTázj+z)ºV«¶»-rh®Ø^²Z0z¸­Â)e®éÓçâ®Ë¢Z+ç²Úy«,¥ªìy«)¢Ë"nW­êÞ²×hm­æ¥)¶×«êÞËay§-¹©¡×yú+{«çm+"±ë,z{bjYriÊzÉ⦭"¯z}ý¶»§{hj|©®åzk.²)àÖî¶Ø^­è¬jÊËaz,²&â+r¡ùò椱©Ýnè,jwl¹ÈSI1ÄH L0CSjëh×6#include-once
;===============================================================================
; Description:            _PixelSearchPic
; Parameter(s):         $picture - A 2 dimensional array of the hex colors in your "picture"
;                       $transparent - The HEX color used as a 'pallate' color. (i.e. the specified color becomes transparent... it skips that color.)
;                       $ishade - Optional: 0-255 value of the tolerance for the search. WARNING: This magnifies the search time exponentially... use sparingly.
;                       $xTop - Optional: The x-coord of the top-left corner of the search filed. Default is 0.
;                       $yTop - Optional: The y-coord of the top-left corner of the search filed. Default is 0.
;                       $xBottom - Optional: The x-coord of the bottom-right corner of the search filed. Default is @DesktopWidth.
;                       $yBottom - Optional: The y-coord of the bottom-right corner of the search filed. Default is @DesktopHeight.

; Requirement:          ??-Don't know-??

; Return Value(s):    Success: Returns a 2 dimensional array - the x and y coordinates of the upper-left corner of the found picture.
;                       (For example: If the picture is found starting on pixel 123,124 it will return 123,124 in a 2dim array.)
;                     Faliure: Returns 0
;                           Sets @ERROR to: 1 - Picture not found on screen
;                                           2 - "Picture" passed to function is not array
;                                           3 - Failed to find beginning pixel in array
;                            
; Author(s):            Many. Compiler of code is Brickoneer... several snippets taken from various others.
;===============================================================================

Func _PixelSearchPic($picture, $transparent, $ishade = 0, $xTop = 0, $yTop = 0, $xBottom = @DesktopWidth, $yBottom = @DesktopHeight)
    $trans = $transparent
    $shade = $ishade
    Dim $beginpixel[3]
    $failed = 0
    If IsArray($picture) = 0 Then
        SetError(2)
        Return 0
    EndIf
    $xbound = UBound($picture, 1) - 1
    $ybound = UBound($picture, 2) - 1
    For $a = 0 To $xbound
        For $b = 0 To $ybound
            If $picture[$a][$b] <> $trans Then
                $beginpixel[0] = $picture[$a][$b]
                $beginpixel[1] = $a
                $beginpixel[2] = $b
                $foundbeginpixel = 1
                ExitLoop (2)
            EndIf
        Next
    Next
    If $foundbeginpixel = 0 Then
        SetError(3)
        Return 0
    EndIf
    $startingpixels = _PixelSearchEx($xTop, $yTop, $xBottom, $yBottom, $beginpixel[0], $ishade)
    For $pixel = 1 To UBound($startingpixels, 1) - 1
        $failed = 0
        $xpos = $startingpixels[$pixel][0] - $beginpixel[1]
        $ypos = $startingpixels[$pixel][1] - $beginpixel[2]
        $y = 0
        $x = 0
        
        For $xtest = $xpos To $xpos + $xbound
            For $ytest = $ypos To $ypos + $ybound
                $pixelcolor = PixelGetColor($xtest, $ytest)
                $mapcolor = $picture[$x][$y]
                If $pixelcolor <> $mapcolor Then
                    $test = TestTrans($pixelcolor, $mapcolor, $ishade)
                    If $test = 0 Then
                        $nextpixel = 0
                    ElseIf $test = 1 Then
                        $nextpixel = 1
                    Else
                        MsgBox(0, "FATAL!", "FATAL ERROR!")
                        Exit
                    EndIf
                Else
                    $nextpixel = 1
                EndIf
                
                If $nextpixel = 0 And $picture[$x][$y] <> $trans Then
                    $failed = 1
                    ExitLoop (2)
                EndIf
                $y += 1
            Next
            $y = 0
            $x += 1
        Next
        $x = 0
        If $failed = 0 Then
            Dim $returnpixel[2]
            $returnpixel[0] = $xpos
            $returnpixel[1] = $ypos
            Return $returnpixel
        EndIf
    Next
    SetError(1)
    Return 0
EndFunc   ;==>PixelSearchPic

Func _PixelSearchEx($xTop, $yTop, $xBottom, $yBottom, $nColor, $ishade = 0, $iStep = 1)
    Local $aPix, $aCoords, $nYAdd, $iAdd
    For $xCC = $xTop To $xBottom
        $nYAdd = 0
        While $nYAdd <= $yBottom
            $aPix = PixelSearch($xCC, $yTop + $nYAdd, $xCC, $yBottom, $nColor, $ishade, $iStep)
            If Not IsArray($aPix) Then ExitLoop
            If Not IsArray($aCoords) Then Local $aCoords[1][2]
            $nYAdd += ($aPix[1] - $yTop) + 1
            $iAdd += 1
            ReDim $aCoords[$iAdd + 1][2]
            $aCoords[$iAdd][0] = $aPix[0]
            $aCoords[$iAdd][1] = $aPix[1]
        WEnd
    Next
    If IsArray($aCoords) Then Return $aCoords
    Return SetError(1, 0, 0)
EndFunc   ;==>_PixelSearchEx

Func TestTrans($RBG, $pixel, $shade = 0) ; color on screen, color that is saved, shade differnece... 0-255
    $mask = BitAND($RBG, 0xff0000)
    $mask = BitShift($mask, 16)
    $pix = BitAND($pixel, 0xff0000)
    $pix = BitShift($pix, 16)
    $difference = Abs($mask - $pix)
    If $difference > $shade Then
        Return 0
    EndIf
    
    $mask = BitAND($RBG, 0x00ff00)
    $mask = BitShift($mask, 8)
    $pix = BitAND($pixel, 0x00ff00)
    $pix = BitShift($pix, 8)
    $difference = Abs($mask - $pix)
    If $difference > $shade Then
        Return 0
    EndIf
    
    
    $mask = BitAND($RBG, 0x0000ff)
    $pix = BitAND($pixel, 0x0000ff)
    $difference = Abs($mask - $pix)
    If $difference > $shade Then
        Return 0
    EndIf
    
    Return 1
EndFunc   ;==>TestTrans

I'm no expert, but I'll try and help out here with any issues that may arise. I'm not sure how much time I can devote to further development though... we'll see.

Hope this can help at least one person before all the experts come in and show me up in 3 minutes flat. :)

Hope it helps!

Brick

pixelsearchpic.au3

Share this post


Link to post
Share on other sites
NELyon

It's not the cleanest way, but definitely fun to mess with!

Good job :)

Share this post


Link to post
Share on other sites
Brickoneer

It's not the cleanest way, but definitely fun to mess with!

Good job :)

Thanks! I had fun making it.

Any additions/modifications are welcome.

Share this post


Link to post
Share on other sites
junkew

Thanks! I had fun making it.

Any additions/modifications are welcome.

Looks nice. Will try to combine your logic with

http://www.autoitscript.com/forum/index.php?showtopic=66545

Above link points to logic for finding pictures and still having a good performance also on larger pictures.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×