jaberwacky Posted June 9, 2010 Share Posted June 9, 2010 (edited) Let me know what you feel is a bug in findBMP coding then I can explain or fix.The main subtle problems are that its looking for an exact match if it doesn't have an exact match it will return false but the other values will indicate how many lines of the comparison matched and based on that you still can decide to see it as a positive match.differences are - frequently on rounded corners and then there is a different background- frequently on clocks, times, highlighted areasissues are frequently in- not having GDIPLUS in the right location (or not installed at all)Awesome, so you're the author? That's sweet. Fainth pointed out that the script only seems to find BMPs if the top line of both BMPs are the same. I did some small tests and I think he is right. I took a bmp from which I cut out a section from the middle of the bmp and then I cut out a section from the very top of the bmp. The only time the script reports a find is when I look for the section that I cropped from the top. Is that proper behavior? Edited June 9, 2010 by jaberwocky6669 Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
Phenom Posted June 10, 2010 Author Share Posted June 10, 2010 Let me know what you feel is a bug in findBMP coding then I can explain or fix.The main subtle problems are that its looking for an exact match if it doesn't have an exact match it will return false but the other values will indicate how many lines of the comparison matched and based on that you still can decide to see it as a positive match.differences are - frequently on rounded corners and then there is a different background- frequently on clocks, times, highlighted areasissues are frequently in- not having GDIPLUS in the right location (or not installed at all)It's a little bit slow for my purposes, since it searches the entire screen. Could it be modified so that only a section of the screen can be specified for the search? Link to comment Share on other sites More sharing options...
junkew Posted June 10, 2010 Share Posted June 10, 2010 It's a little bit slow for my purposes, since it searches the entire screen. Could it be modified so that only a section of the screen can be specified for the search? The original post for findBMP is here http://www.autoitscript.com/forum/index.php?showtopic=66545 read that thread and you understand more of the details There are different ways of speeding things up. I assume you use findBMP("SCREEN","yourpicture") You can use findBMP("[ACTIVE]","yourpicture") to only search in an active window or use first _ScreenCapture_Capture (see help for usage) to save an screen area to file (this is very quick) and use then the 2 bitmaps you have to compare FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
junkew Posted June 10, 2010 Share Posted June 10, 2010 Awesome, so you're the author? That's sweet. Fainth pointed out that the script only seems to find BMPs if the top line of both BMPs are the same. I did some small tests and I think he is right. I took a bmp from which I cut out a section from the middle of the bmp and then I cut out a section from the very top of the bmp. The only time the script reports a find is when I look for the section that I cropped from the top. Is that proper behavior?add the bmp's to the post then I will check FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
Phenom Posted June 10, 2010 Author Share Posted June 10, 2010 add the bmp's to the post then I will checkI can't get it to work with these files. Can you get it to work?image files.zip Link to comment Share on other sites More sharing options...
jaberwacky Posted June 10, 2010 Share Posted June 10, 2010 I can't get it to work with these files. Can you get it to work?Lulz, you're making a bot... =P Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
jaberwacky Posted June 10, 2010 Share Posted June 10, 2010 add the bmp's to the post then I will check Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
junkew Posted June 10, 2010 Share Posted June 10, 2010 findTester(@tempdir & "\" & "screencap.bmp",@tempdir & "\" & "ks.bmp",$c24RGBPartialMatch) ;Find the Ks will do the trick (save the files you attached in %temp%) Script copy paste at the bottom and run in SCITE I added the demo for the calculator and output should be something like below >"C:\Program Files\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "H:\CTS\tests\findbmp2.au3" /autoit3dir "C:\Program Files\AutoIt3" /UserParams +>21:05:13 Starting AutoIt3Wrapper v.1.10.1.14 Environment(Language:0413 Keyboard:00020409 OS:WIN_XP/Service Pack 3 CPU:X86 ANSI) >Running AU3Check (1.54.19.0) from:C:\Program Files\AutoIt3 +>21:05:13 AU3Check ended.rc:0 >Running:(3.3.6.0):C:\Program Files\AutoIt3\autoit3.exe "H:\CTS\tests\findbmp2.au3" Saving calculator window 270.368966727151 milliseconds Saving backspacebutton 12.4119965380464 milliseconds Saving 0-button 12.3177124373022 milliseconds Saving 1-button 12.339076299987 milliseconds Saving 2-button 12.5508997403535 milliseconds Saving 3-button 12.6476620117426 milliseconds Saving 4-button 31.4894654356013 milliseconds Saving 5-button 18.0730378642821 milliseconds Saving 6-button 12.403707899336 milliseconds Saving 7-button 12.3783888549154 milliseconds Saving 8-button 14.9442338088507 milliseconds Saving 9-button 12.7914921487838 milliseconds Saving full screen took 149.761209411434 milliseconds 0 BACKSPACE.bmp True;13;271;428;73;30;-1;-1;17 BACKSPACE.bmp in SCREEN ** matchtype 2 time elapsed: 1056.52249167093 milliseconds True;13;48;87;73;30;-1;-1;17 BACKSPACE.bmp in [ACTIVE] ** matchtype 2 time elapsed: 53.223209792383 milliseconds 1 0.bmp True;19;280;562;37;30;9;464;1 0.bmp in SCREEN ** matchtype 2 time elapsed: 1120.10529150919 milliseconds True;19;57;221;37;30;9;123;1 0.bmp in [ACTIVE] ** matchtype 2 time elapsed: 58.3368213518327 milliseconds 2 1.bmp True;20;280;529;37;30;9;464;1 1.bmp in SCREEN ** matchtype 2 time elapsed: 1208.43248889735 milliseconds True;20;57;188;37;30;9;123;1 1.bmp in [ACTIVE] ** matchtype 2 time elapsed: 55.3522671451915 milliseconds 3 2.bmp True;20;319;529;37;30;9;464;1 2.bmp in SCREEN ** matchtype 2 time elapsed: 1109.43714382145 milliseconds True;20;96;188;37;30;9;123;1 2.bmp in [ACTIVE] ** matchtype 2 time elapsed: 55.9108406599098 milliseconds 4 3.bmp True;18;358;529;37;30;9;464;1 3.bmp in SCREEN ** matchtype 2 time elapsed: 1109.64861304649 milliseconds True;18;135;188;37;30;9;123;1 3.bmp in [ACTIVE] ** matchtype 2 time elapsed: 56.1307161498799 milliseconds 5 4.bmp True;20;280;497;37;30;9;464;1 4.bmp in SCREEN ** matchtype 2 time elapsed: 1167.3247492924 milliseconds True;20;57;156;37;30;9;123;1 4.bmp in [ACTIVE] ** matchtype 2 time elapsed: 55.0261310663552 milliseconds True;3;672;221;43;59;22;254;34 ks.bmp in screencap.bmp ** matchtype 2 time elapsed: 669.776453368889 milliseconds +>21:05:25 AutoIT3.exe ended.rc:0 +>21:05:26 AutoIt3Wrapper Finished >Exit code: 0 Time: 13.576 The full script expandcollapse popupOpt('MustDeclareVars', 1) ;#include <GUIConstants.au3> #include <GDIPlus.au3> #include <ScreenCapture.au3> #include <string.au3> ;~ Constants for type of picture matching Const $c24RGBFullMatch = 1 ;Load as 24 bits and full match Const $c24RGBPartialMatch = 2 ;Load as 24 bits and partial match Const $c16RGBFullMatch = 3 ;Load as 16 bits and full match Const $c16RGBPartialMatch = 4 ;Load as 16 bits and partial match ; ** Example start ** ;~ Executable name of the calculator Const $cCalculatorExe="calc.exe" ;Global Const $Bitmap12Filename = @TempDir & "\wordgt2.jpg" ;Global Const $Bitmap12Filename = @TempDir & "\t.bmp" ; Screen samples Global $Bitmap1Filename = @tempdir & "\FULLSCREEN.BMP" ;Full screen to search in Global $Bitmap2Filename = @tempdir & "\CALCULATOR.BMP" ;Calculator window to search in Global $Bitmap3Filename = @tempdir & "\BACKSPACE.BMP" ;Calculator window to search in ;~ ; All bitmaps we want to search in abouve screens ;~ Global $BitmapFileNamesScreen[22] = ["CALCULATOR.BMP", "BACKSPACE.bmp", _ ;~ "7WDS_BW.bmp","SEVEN_BW.bmp","CAT_BW.bmp", _ ;~ "AUTOIT3.bmp", _ ;Make sure the homepage of autoit with 3 is visible ;~ "six_control_codes.bmp","control_code_3.bmp","control_code_5.bmp", _ ;~ "blueenvelope.bmp","gray.bmp","car.bmp", _ ;~ "0.bmp","1.bmp","2.bmp","3.bmp","4.bmp","5.bmp","6.bmp","7.bmp","8.bmp","9.bmp"] Global $BitmapFileNamesScreen[6] = ["CALCULATOR.BMP", "BACKSPACE.bmp", _ "blueenvelope.bmp","white.bmp","car.bmp", "1.bmp"] ;~ Global $BitmapFileNamesCalculator[11] = ["BACKSPACE.bmp", "0.bmp","1.bmp","2.bmp","3.bmp","4.bmp","5.bmp","6.bmp","7.bmp","8.bmp","9.bmp"] Global $BitmapFileNamesCalculator[6] = ["BACKSPACE.bmp", "0.bmp","1.bmp","2.bmp","3.bmp","4.bmp"] Local $calcHWND, $tBeginTime, $pos, $aWinPos, $aWinCSize, $start Local $pBitmap, $BitmapData, $pixelFormat Local $x Opt("WinTitleMatchMode", 4) ;Matching windows by advanced options ; Initialize GDI+ library _GDIPlus_Startup() ;Calculator, make sure its started $calcHWND = WinGetHandle("[CLASS:SciCalc]") If $calcHWND = "" Then Run($cCalculatorExe) Sleep(2000) $calcHWND = WinGetHandle("[CLASS:SciCalc]") EndIf ;Capture the calculator screen $tBeginTime = TimerInit() WinActivate($calcHWND) WinMove("[ACTIVE]", "", 223, 341) _ScreenCapture_CaptureWnd($Bitmap2Filename, $calcHWND, 0, 0, -1, -1, False) ConsoleWrite("Saving calculator window " & TimerDiff($tBeginTime) & " milliseconds " & @LF) ;Capture an area within the calculator area backspace $tBeginTime = TimerInit() $pos = ControlGetPos("", "", "[CLASS:Button; TEXT:BACKSPACE]") $aWinPos = WinGetPos($calcHWND) $aWinCSize = WinGetClientSize($calcHWND) ;Q&D calculation of offsets to capture _ScreenCapture_Capture($Bitmap3Filename, ($aWinPos[0] + $pos[0]) + ($aWinPos[2] - $aWinCSize[0]) - 3, ($aWinPos[1] + $pos[1]) + ($aWinPos[3] - $aWinCSize[1]) - 3, $aWinPos[0] + $pos[0] + $pos[2] + 3, ($aWinPos[1] + $pos[1]) + ($aWinPos[3] - $aWinCSize[1]) + $pos[3] - 3, False) ConsoleWrite("Saving backspacebutton " & TimerDiff($tBeginTime) & " milliseconds " & @LF) ;Capture all numeric buttons of the calculator For $i = 0 To 9 $tBeginTime = TimerInit() $pos = ControlGetPos("", "", "[CLASS:Button; TEXT:" & StringStripWS($i, 3) & "]") $aWinPos = WinGetPos($calcHWND) $aWinCSize = WinGetClientSize($calcHWND) ;Q&D calculation of offsets to capture _ScreenCapture_Capture(@TempDir & "\" & StringStripWS($i, 3) & ".bmp", ($aWinPos[0] + $pos[0]) + ($aWinPos[2] - $aWinCSize[0]) - 3, ($aWinPos[1] + $pos[1]) + ($aWinPos[3] - $aWinCSize[1]) - 3, $aWinPos[0] + $pos[0] + $pos[2] + 3, ($aWinPos[1] + $pos[1]) + ($aWinPos[3] - $aWinCSize[1]) + $pos[3] - 3, False) ConsoleWrite("Saving " & StringStripWS($i, 3) & "-button " & TimerDiff($tBeginTime) & " milliseconds " & @LF) Next ; Capture full screen $tBeginTime = TimerInit() _ScreenCapture_Capture($Bitmap1Filename, 0, 0, -1, -1, False) ConsoleWrite("Saving full screen took " & TimerDiff($tBeginTime) & " milliseconds " & @LF) ;~ Just a little helper to get the name of the file Func fileGetname($f) Local $i $i = StringInStr($f, "\", False, -1) If $i > 0 Then Return StringMid($f, $i + 1) Else Return $f EndIf EndFunc ;==>filegetname ;Do the actual find Func FindTester($BMP1, $BMP2, $Bool) Local $tResult $start = TimerInit() $tResult = findBMP($BMP1, $BMP2, $Bool) ConsoleWrite($tResult & @tab & filegetname($BMP2) & " in " & filegetname($BMP1) & @tab & " ** matchtype " & $Bool & " time elapsed: " & TimerDiff($start) & " milliseconds" & @LF) EndFunc ;==>FindTester ;Find all the different bmp files in the 2 screenshots made or in SCREEN or ACTIVE ;~ Make sure the autoit homepage is active in the browser and visible on screen if you want to find the 3 ;~ Not very usefull to find full screen and tricky as screen is most likely changed (clock, output from application etc.) for $i=0 to ubound($BitmapFileNamesScreen)-1 ;~ consolewrite($i & @tab & $bitmapfilenamesScreen[$i] &@crlf) ;~ findTester("SCREEN",@tempdir & "\" & $bitmapFilenamesScreen[$i],$c24RGBFullMatch) ;~ findTester("SCREEN",@tempdir & "\" & $bitmapFilenamesScreen[$i],$c24RGBPartialMatch) ;~ findTester("SCREEN",@tempdir & "\" & $bitmapFilenamesScreen[$i],$c16RGBFullMatch) ;~ findTester("SCREEN",@tempdir & "\" & $bitmapFilenamesScreen[$i],$c16RGBPartialMatch) ;~ findTester("[ACTIVE]",@tempdir & "\" & $bitmapFilenamesScreen[$i],$c24RGBFullMatch) ;Find the bitmap in the active screen Next for $i=0 to ubound($BitmapFileNamesCalculator)-1 consolewrite($i & @tab & $bitmapfilenamesCalculator[$i] &@crlf) findTester("SCREEN",@tempdir & "\" & $bitmapfilenamesCalculator[$i],$c24RGBPartialMatch) winactivate($calcHWND) ;Make sure calculator is active on the screen findTester("[ACTIVE]",@tempdir & "\" & $bitmapFilenamesCalculator[$i],$c24RGBPartialMatch) ;Find the backspace button Next findTester(@tempdir & "\" & "screencap.bmp",@tempdir & "\" & "ks.bmp",$c24RGBPartialMatch) ;Find the Ks _GDIPlus_Shutdown() ;** Example end ** ;=============================================================================== ; Function Name: findBMP ; Description: Finds a bitmap (.BMP) in another BMP file (other formats BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF should work but not tested) ; Syntax: findBMP($BMP1, $BMP2, $MatchType=TRUE) ; ; Parameter(s): $BMP1 = Filename of bitmap to search in ; $BMP2 = Filename of bitmap to search for ; $MatchType = c24RGBFullMatch, c24RGBPartialMatch, c16RGBFullMatch, c16RGBPartialMatch ; ; Return Value(s): On Success: = Returns Array List ; On Failure: = @error 1 (Control was found but there was an error with the DLLCall) ; ; Author(s): JunkEW ; ; Note(s): ; * Its never an exact match even with TRUE as last few bits are disposed in algorithm and lines below ; are not checked under assumption that those are 99.99% of the time correct ; * locking bits overview http://www.bobpowell.net/lockingbits.htm ; ToDo: ; * Transparency (when search letters on a different background) http://www.winprog.org/tutorial/transparency.html ; * Match quicker by doing a bitblt with srcinvert when first line is found (instead of checking line by line) ; * $BMP1 and $BMP2 to be HBITMAP handle as input instead of filenames (will make searching within partial screen easier) ; Example(s): ; ;=============================================================================== Func findBMP($BMP1, $BMP2, $MatchType = $c24RGBFullMatch) Dim $splitMeOn ;~ , $picLines[1] ;Line number of found line(s), redimmed when second picture size is known Dim $vCount, $vLine, $prevVCount ;For determining the most unique line in the picture Dim $BMP1Data = "", $BMP1Width = 0, $BMP1Height = 0, $BMP1LineWidth = 0 Dim $BMP2Data = "", $BMP2Width = 0, $BMP2Height = 0, $BMP2LineWidth = 0 Dim $foundAt = "", $matchPossible = False, $matchedLines = 0, $foundAtLeft = -1, $foundAtTop = -1 Dim $bestMatchLine = -1, $HighestMatchingLines = -1 ; For knowing when no match is found where best area is Dim $iPos = 1 Dim $imgBytes, $padBytes1, $padBytes2, $splitpos Dim $sLineToSearch, $vCount dim $dataAbove dim $sData Local $iFuzzyDist, $iAbove, $bMatchPossible, $aboveLine Local $j, $imgBits If ($MatchType = $c24RGBFullMatch) Or ($MatchType = $c24RGBPartialMatch) Then $imgBytes = 3 Else $imgBytes = 2 EndIf ; Load the bitmap to search in GetImage($BMP1, $BMP1Data, $BMP1Width, $BMP1Height, $BMP1LineWidth, $imgBytes) $BMP1Data = BinaryToString($BMP1Data) ; Load the bitmap to find GetImage($BMP2, $BMP2Data, $BMP2Width, $BMP2Height, $BMP2LineWidth, $imgBytes) ;Make it strings to be able to use string functions for searching $BMP2Data = BinaryToString($BMP2Data) ;For reference of line where in BMP2FindIn a line of BMP2Find was found If $BMP2Height = 0 Then SetError(1, 0, 0) Return False EndIf ;Determine bytes used for padding on 4 byte boundary $padBytes1 = $BMP1LineWidth - ($BMP1Width * $imgBytes) $padBytes2 = $BMP2LineWidth - ($BMP2Width * $imgBytes) ;Get all of the picturelines of 2nd bitmap in a seperate array Dim $picLines[$BMP2Height] $vline=0 for $i=0 to $BMP2Height-1 $picLines[$i]=StringMid($BMP2Data, 1 + ($i * $BMP2LineWidth), ($BMP2LineWidth - $padBytes2)) ;~ ;Find line with most variation $sLineToSearch=$picLines[$i] $vCount=0 For $j=2 to (Stringlen($slineToSearch)/$imgBytes) step $imgBytes if stringmid($slinetosearch,$j,$imgBytes) <> stringmid($slinetosearch,$j-$imgBytes,$imgBytes) then $vCount=$vcount+1 endif Next if $vcount > $prevVCount Then $prevVCount=$vcount $vLine=$i endIf Next ;~ consolewrite($vLine & "; " & $vcount & @crlf) ;For debugging ;~ dumpHex("test", $BMP1Data, $BMP1Height, $BMP1LineWidth) ;~ dumpHex("test", $BMP2Data, $BMP2Height, $BMP2LineWidth) ;If exact match check every 1 line else do it more fuzzy (as most likely other lines are unique) If ($MatchType = $c24RGBFullMatch) Or ($MatchType = $c16RGBFullMatch) Then $iFuzzyDist = 1 $i=0 ;Start searching at the first line Else ;At least make sure we search at least 10% or 4 lines of the total lines if we are using the most unique line to search if ($vline < ceiling($bmp2height*0.90)) or ($vline < ($bmp2height-4)) Then ;Check fuzzy every 10% of lines left over from starting most unique line $iFuzzyDist = 1; Ceiling((($BMP2Height-$vline) * 0.1)) $i = $vline ;Start searching at the line thats most unique ;~ consolewrite("Fuzzy find < 0.75 " & $vline & ":") Else $iFuzzyDist = Ceiling(($BMP2Height * 0.2)) $i= 0 ;Start searching at line 0 to not start searching to high consolewrite("Fuzzy find > 0.75 " & $vline & ":") endIf EndIf ;~ $tBeginTime = TimerInit() ;Look for each line of the bitmap if it exists in the bitmap to find in ;~ For $i = 0 To $BMP2Height - 1 while $i <= $bmp2height-1 ;Minus imgbytes as last bits are padded with unpredictable bytes (24 bits image assumption) or 2 when 16 bits $sLineToSearch= $piclines[$i] ; StringMid($BMP2Data, 1 + ($i * $BMP2LineWidth), ($BMP2LineWidth - $padBytes2)) $iPos = StringInStr($BMP1Data, $sLineToSearch, 2, 1, $iPos) ;~ ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iPos = ' & $iPos & @CRLF & '>Error code: ' & @error & $i & ";ipos " & $iPos & ";" & _StringToHex($sLineToSearch) & @CRLF) ;### Debug Console ;Look for all lines above if there is also a match ;Not doing it for the lines below as speed is more important and risk of mismatch on lines below is small $iAbove = 1 If $iPos > 0 Then $bMatchPossible = True $matchedLines = 1 ;As first found line is matched we start counting ;Location of the match $foundAtTop = Int($iPos / $BMP1LineWidth) + 1 - $i $foundAtLeft = Int(Mod($iPos, $BMP1LineWidth) / $imgBytes) Else $bMatchPossible = False ExitLoop EndIf ;Reduce the size of the scanning string tremendously to speed things up ;~ $dataAbove=StringMid($BMP1Data, $iPos, ($BMP2Height - $i) * $BMP1LineWidth) While (($i + $iAbove) <= ($BMP2Height - 1)) And ($bMatchPossible = True) $sLineToSearch= $piclines[$i+$iAbove] ;StringMid($BMP2Data, 1 + (($i + $iAbove) * $BMP2LineWidth), ($BMP2LineWidth - $padBytes2)) $aboveLine = StringMid($BMP1Data, $iPos + ($iAbove * $BMP1LineWidth), StringLen($sLineToSearch)) ;Previous line calculates size of string, Be aware of padding. ;~ $aboveLine = StringMid($dataAbove, $iAbove * $BMP1LineWidth, StringLen($sLineToSearch)) ;Previous line calculates size of string, Be aware of padding. If $aboveLine <> $sLineToSearch Then $bMatchPossible = False ;To remember the area with the best match If $matchedLines >= $HighestMatchingLines Then $HighestMatchingLines = $matchedLines ;Best guess of location ;~ $foundAtTop = $picLines[$i] + $i - $BMP2Height $foundAtTop = Int($iPos / $BMP1LineWidth) + 1 ;+ $i - $BMP2Height $foundAtLeft = Int(Mod($iPos, $BMP1LineWidth) / $imgBytes) $bestMatchLine = Int($iPos / $BMP1LineWidth) EndIf ExitLoop EndIf $matchedLines = $matchedLines + 1 $iAbove = $iAbove + $iFuzzyDist WEnd ;If bMatchPossible is still true most likely we have found the bitmap If $bMatchPossible = True Then ;~ ConsoleWrite("Could match top: " & $foundAtTop & " left: " & $foundAtLeft & " in " & TimerDiff($tBeginTime) / 1000 & " seconds" & @LF) ; MouseMove($foundatleft,$foundatTop) ExitLoop Else ;~ consolewrite("i not matched " & $ipos & " " & $matchedlines & @crlf ) EndIf ;~ Next $i=$i+1 WEnd ;Return an error if not found else return an array with all information If $bMatchPossible = False Then SetError(1, 0, 0) EndIf ; return stringsplit($bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $bmp2width & ";" & $BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine,";") Return $bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $BMP2Width & ";" & $BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine & ";" & $vline EndFunc ;==>findBMP Func GetImage($BMPFile, ByRef $BMPDataStart, ByRef $Width, ByRef $Height, ByRef $Stride, $imgBytes = 3) Local $Scan0, $pixelData, $hbScreen, $pBitmap, $pBitmapCap, $handle ; 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) 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 = 2) Then $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF16RGB555) Else $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB) 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 Func dumpHex($sFname, $bmData, $h, $w) Local $i, $tLine For $i = 0 To $h - 1 $tLine = StringMid($bmData, 1 + ($i * $w), $w) ConsoleWrite(StringFormat("%06s;", 1 + ($i * $w)) & _StringToHex($tLine) & ";") ConsoleWrite(@CRLF) Next EndFunc ;==>dumpHex FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
junkew Posted June 10, 2010 Share Posted June 10, 2010 for lenas eyes it works on my system see above post for sourcecode and add the following 2 lines (after you save the files to %temp%) findTester(@tempdir & "\" & "lena.bmp",@tempdir & "\" & "eyes.bmp",$c24RGBPartialMatch) ;Find the eyes of lena findTester(@tempdir & "\" & "lena.bmp",@tempdir & "\" & "eyes top.bmp",$c24RGBPartialMatch) ;Find the eyes of lena True;38;235;254;128;38;-1;-1;0 eyes.bmp in lena.bmp ** matchtype 2 time elapsed: 190.717112276235 milliseconds True;290;239;1;119;290;-1;-1;0 eyes top.bmp in lena.bmp ** matchtype 2 time elapsed: 288.582391488139 milliseconds FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
Phenom Posted June 10, 2010 Author Share Posted June 10, 2010 It didn't work. This is what I got:False;0;-1;-1;43;59;-1;-1;4 ks.bmp in screencap.bmp ** matchtype 2 time elapsed: 338.144013791478 milliseconds Link to comment Share on other sites More sharing options...
Phenom Posted June 10, 2010 Author Share Posted June 10, 2010 for lenas eyes it works on my systemsee above post for sourcecode and add the following 2 lines (after you save the files to %temp%)findTester(@tempdir & "\" & "lena.bmp",@tempdir & "\" & "eyes.bmp",$c24RGBPartialMatch) ;Find the eyes of lenafindTester(@tempdir & "\" & "lena.bmp",@tempdir & "\" & "eyes top.bmp",$c24RGBPartialMatch) ;Find the eyes of lenaTrue;38;235;254;128;38;-1;-1;0 eyes.bmp in lena.bmp ** matchtype 2 time elapsed: 190.717112276235 millisecondsTrue;290;239;1;119;290;-1;-1;0 eyes top.bmp in lena.bmp ** matchtype 2 time elapsed: 288.582391488139 millisecondsThat doesn't work for me either. This is what I get:False;0;-1;-1;128;38;-1;-1;0 eyes.bmp in lena.bmp ** matchtype 2 time elapsed: 146.778692525144 millisecondsFalse;0;-1;-1;119;290;-1;-1;0 eyes top.bmp in lena.bmp ** matchtype 2 time elapsed: 213.216642902082 milliseconds Link to comment Share on other sites More sharing options...
JohnOne Posted June 10, 2010 Share Posted June 10, 2010 (edited) I can't get it to work with these files. Can you get it to work?You wont get that to work, for one quite apparent reason.the pictures do not match, there is some kind of artifacts in the smaller image you are trying to find, that is not in the larger picture.edit or visa versa Edited June 10, 2010 by JohnOne AutoIt Absolute Beginners  Require a serial  Pause Script  Video Tutorials by Morthawt  ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
Phenom Posted June 10, 2010 Author Share Posted June 10, 2010 You wont get that to work, for one quite apparent reason.the pictures do not match, there is some kind of artifacts in the smaller image you are trying to find, that is not in the larger picture.edit or visa versaI don't see how that is possible. How are you able to detect the artifacts? Link to comment Share on other sites More sharing options...
JohnOne Posted June 10, 2010 Share Posted June 10, 2010 zoom in on the larger picture to the leg of the king. Now look at the leg of the king in the other picture. These functions rely on pixels and there colours as far as I can work out, so it's not going to find a picture with so much difference. Use your window info tool to see the differences. AutoIt Absolute Beginners  Require a serial  Pause Script  Video Tutorials by Morthawt  ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
Phenom Posted June 10, 2010 Author Share Posted June 10, 2010 Yeah, I can see a small difference. But should that make a difference? I can successfully match the images using AutoHotkey's ImageSearch() function if I specify a variation of 150. Link to comment Share on other sites More sharing options...
junkew Posted June 10, 2010 Share Posted June 10, 2010 Did you copy / paste the source and run the script? What kind of results did you get for the calculator and its buttons? As calculator is simple and straight forward you first need to have proof that the functions are working on the calculator. If thats not the case you know something is not the same as on my system. The function works checking line by line but if you do a partial match it will skip some lines As it works on my system with the pictures attached in the posting I am 98% sure that the artefacts are not there The intention of the functions I wrote where only to recognize textboxes, icons, hotspots that are not recognizable other ways. It was not intended to match on shading variations etc. in photos or in games although with the concepts in the source code you can come a long way. Comment out those 2 lines (make sure your bitmaps are not to large) to see the pictures hexadecimal and find out if the pattern can be found in the other pattern (use a good text editor for that) ;For debugging ;~ dumpHex("test", $BMP1Data, $BMP1Height, $BMP1LineWidth) ;~ dumpHex("test", $BMP2Data, $BMP2Height, $BMP2LineWidth) FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
junkew Posted June 10, 2010 Share Posted June 10, 2010 zoom in on the larger picture to the leg of the king.Now look at the leg of the king in the other picture.These functions rely on pixels and there colours as far as I can work out, so it's not going to find a picture with so much difference.Use your window info tool to see the differences.At the moment you zoom in your system will change the pixels. Only way to do that on a proper level is using tools like GIMP. Don't trust what microsoft windows shows you on zooming in. As the pictures are from different size zooming can be done differently and heavily depends on the tool you use to zoom. FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
JohnOne Posted June 10, 2010 Share Posted June 10, 2010 If you look closely at all of the cards in the large picture, you will see they all have random colours in them, its pretty clear what the message is, and certainly nothing to do with zoom, lol. AutoIt Absolute Beginners  Require a serial  Pause Script  Video Tutorials by Morthawt  ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
Phenom Posted June 10, 2010 Author Share Posted June 10, 2010 (edited) Did you copy / paste the source and run the script? What kind of results did you get for the calculator and its buttons? As calculator is simple and straight forward you first need to have proof that the functions are working on the calculator. If thats not the case you know something is not the same as on my system. The function works checking line by line but if you do a partial match it will skip some lines As it works on my system with the pictures attached in the posting I am 98% sure that the artefacts are not there The intention of the functions I wrote where only to recognize textboxes, icons, hotspots that are not recognizable other ways. It was not intended to match on shading variations etc. in photos or in games although with the concepts in the source code you can come a long way. Comment out those 2 lines (make sure your bitmaps are not to large) to see the pictures hexadecimal and find out if the pattern can be found in the other pattern (use a good text editor for that) ;For debugging ;~ dumpHex("test", $BMP1Data, $BMP1Height, $BMP1LineWidth) ;~ dumpHex("test", $BMP2Data, $BMP2Height, $BMP2LineWidth) I tried your code before I posted here. It was all in a zip file with the necessary pictures. I recall that there was a problem recognizing the calculator because the calculator looks different in Windows 7. I remember that there were a few successes, but most were failures. Nevertheless, I tried the code you posted here, and I got this error on line 68: Subscript used with non-Array variable.: _ScreenCapture_Capture($Bitmap3Filename, ($aWinPos[0] + $pos[0]) + ($aWinPos[2] - $aWinCSize[0]) - 3, ($aWinPos[1] + $pos[1]) + ($aWinPos[3] - $aWinCSize[1]) - 3, $aWinPos[0] + $pos[0] + $pos[2] + 3, ($aWinPos[1] + $pos[1]) + ($aWinPos[3] - $aWinCSize[1]) + $pos[3] - 3, False) _ScreenCapture_Capture($Bitmap3Filename, ($aWinPos[0] + $pos^ ERROR So I just moved the line I was interested in to the top and wrote exit underneath to get around that. How does the partial match decide which lines to skip? Wouldn't it be better if partial match checked every line, and then used some predefined match percentage to determine if the image matches? Or better yet, what if the user could specify the match percentage? Edited June 10, 2010 by Phenom Link to comment Share on other sites More sharing options...
jaberwacky Posted June 10, 2010 Share Posted June 10, 2010 Oh man, I feel kinda silly. So it was just an option that had to be set! Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now