Brickoneer Posted April 5, 2008 Posted April 5, 2008 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. expandcollapse popup;=============================================================================== ; 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! Brickpixelsearchpic.au3
NELyon Posted April 5, 2008 Posted April 5, 2008 It's not the cleanest way, but definitely fun to mess with! Good job
Brickoneer Posted April 5, 2008 Author Posted April 5, 2008 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.
junkew Posted April 7, 2008 Posted April 7, 2008 Thanks! I had fun making it.Any additions/modifications are welcome.Looks nice. Will try to combine your logic withhttp://www.autoitscript.com/forum/index.php?showtopic=66545Above link points to logic for finding pictures and still having a good performance also on larger pictures. FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
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