johnmcloud Posted December 27, 2012 Posted December 27, 2012 (edited) Hi guys and happy holidays I have found a cool Func and i'm playing around This is the script: expandcollapse popup#include <GDIPlus.au3> #include <ScreenCapture.au3> Opt("WinTitleMatchMode", 4) ;Matching windows by advanced options ;~ 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 ; Screen samples Global Const $Bitmap1Filename = @ScriptDir & "\FULLSCREEN.bmp" Global Const $Bitmap2Filename = @ScriptDir & "\CALCULATOR.bmp" ; Initialize GDI+ library _GDIPlus_Startup() ;Calculator, make sure its started $calcHWND = WinGetHandle("[REGEXPCLASS:.*Calc.*]") If $calcHWND = "" Then Run("calc.exe") Sleep(2000) $calcHWND = WinGetHandle("[REGEXPCLASS:.*Calc.*]") EndIf ;Capture the calculator screen WinActivate($calcHWND) _ScreenCapture_CaptureWnd($Bitmap2Filename, $calcHWND, 0, 0, -1, -1, False) ConsoleWrite("Saving calculator window" & @LF) ; Capture full screen _ScreenCapture_Capture($Bitmap1Filename, 0, 0, -1, -1, False) ConsoleWrite("Saving full screen" & @LF) 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, $Type) Local $tResult $tResult = _FindBMP($BMP1, $BMP2, $Type) ConsoleWrite($tResult & " " & FileGetName($BMP2) & " in " & FileGetName($BMP1) & " ** matchtype " & $Type & @LF) EndFunc ;==>_FindTester _FindTester("SCREEN", $Bitmap2Filename, $c24RGBFullMatch);Find the full calculator screen _FindTester("SCREEN", $Bitmap2Filename, $c24RGBPartialMatch);Find the full calculator screen with partial match _FindTester("SCREEN", $Bitmap2Filename, $c16RGBFullMatch);Find the full calculator screen _FindTester("SCREEN", $Bitmap2Filename, $c16RGBPartialMatch);Find the full calculator screen with partial match _FindTester($Bitmap1Filename, $Bitmap2Filename, $c16RGBFullMatch);Find the full calculator screen _FindTester($Bitmap1Filename, $Bitmap2Filename, $c16RGBPartialMatch);Find the full calculator screen with partial match _GDIPlus_Shutdown() ;=============================================================================== ; 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 $fLine[1];Line number of found line(s), redimmed when second picture size is known 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; Local $iFuzzyDist, $searchFor, $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 ReDim $fLine[$BMP2Height] ;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 Else ;Check fuzzy every 10% of lines $iFuzzyDist = Ceiling(($BMP2Height * 0.1)) EndIf $begin = TimerInit() ;Look for each line of the bitmap if it exists in the bitmap to find in For $i = 0 To $BMP2Height - 1 ;Minus imgbytes as last bits are padded with unpredictable bytes (24 bits image assumption) or 2 when 16 bits $searchFor = StringMid($BMP2Data, 1 + ($i * $BMP2LineWidth), ($BMP2LineWidth - $imgBytes)) $iPos = StringInStr($BMP1Data, $searchFor, 2, 1, $iPos) ;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) - $i $foundAtLeft = Int(Mod($iPos, $BMP1LineWidth) / $imgBytes) Else $bMatchPossible = False ExitLoop EndIf While (($i + $iAbove) <= ($BMP2Height - 1)) And ($bMatchPossible = True) $searchFor = StringMid($BMP2Data, 1 + (($i + $iAbove) * $BMP2LineWidth), ($BMP2LineWidth - $imgBytes)) $aboveLine = StringMid($BMP1Data, $iPos + ($iAbove * $BMP1LineWidth), ($BMP2LineWidth - $imgBytes)) If $aboveLine <> $searchFor Then $bMatchPossible = False ;To remember the area with the best match If $matchedLines >= $HighestMatchingLines Then $HighestMatchingLines = $matchedLines ;Best guess of location $foundAtTop = Int($iPos / $BMP1LineWidth);+ $i - $BMP2Height $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($begin) / 1000 & " seconds" & @LF) ; MouseMove($foundatleft, $foundatTop) ExitLoop Else ;~ consolewrite("i not matched " & $ipos & " " & $matchedlines & @crlf ) EndIf Next ;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 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 ;~ 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 Work fine, but i'd like to add it in a loop ( my goal is search for the temperature of an HW component , if is X then start an alarm, in this case i have posted, as always, an example for everyone ) I have try many ways with While-WEnd and Do-Until, but if the $tResult is False, it's everytime false, never change. So in the example i'd like to do: 1) Open the script 2) If i open Calc.exe , the script comparing the two images, and give me a MsgBox Thanks for any help Edited December 27, 2012 by johnmcloud
FireFox Posted December 27, 2012 Posted December 27, 2012 Hi, If it works outside a loop it should work in a loop. Plus, it does not work for me at all.
johnmcloud Posted December 27, 2012 Author Posted December 27, 2012 (edited) Hi, If it works outside a loop it should work in a loop. Plus, it does not work for me at all. If i put it in a loop i have everytime the same value, so if is true is always true, also if the real value is false, don't know why I have tested on XP SP3 x86 and on Windows 7 x64, work on both. Just press F5 and wait. This is the ConsoleWrite output: Saving calculator window Saving full screen True;322;125;0;228;322;-1;-1 CALCULATOR.bmp in SCREEN ** matchtype 1 True;11;125;0;228;322;-1;-1 CALCULATOR.bmp in SCREEN ** matchtype 2 True;322;125;0;228;322;-1;-1 CALCULATOR.bmp in SCREEN ** matchtype 3 True;11;125;0;228;322;-1;-1 CALCULATOR.bmp in SCREEN ** matchtype 4 True;322;125;0;228;322;-1;-1 CALCULATOR.bmp in FULLSCREEN.bmp ** matchtype 3 True;11;125;0;228;322;-1;-1 CALCULATOR.bmp in FULLSCREEN.bmp ** matchtype 4 Edited December 27, 2012 by johnmcloud
junkew Posted January 5, 2013 Posted January 5, 2013 (edited) Not sure what you are saying. If it works without a loop it should work with a loop to.I looked thru under W7 and 64 bits as library was written a long time ago by me in Windows XP / 32 bitsOn my W7 64 bits machine it gives in the end an issue as bitmap and bitmaparea of the screen where the calculator is seems indeed to be different for me for unknown reasondebugging code (creates hex files) to show this (its only of by 1 byte) easiest shown if you have a white background (put blanco MS Paint screen behind calculator)only 1 findtester active as this 24 bits is most complicated _FindTester("SCREEN", $Bitmap2Filename, $c24RGBFullMatch);Find the full calculator screenSections added for start debugging / end debugging that writes the data to the filescheck files BMP2DATA.TXT, BMP1DATA.TXT and COMPAREDLINES.TXT (with good editor you will see where it mismatches)So no clue why it has in the fullscreen image a different bmp written (must be something weird of GDI)At least is shows the algorithm in itself is correct and the issue is in the BMP files createdworkaround: doing a subcheck within the string but that would slow down the comparison[Edit] Created more debugging stuff in the code and enable with a boolean the debugging[Edit2] Fixed with new function addedfunc comparePicLine($s1,$s2) if $s1=$s2 Then return True Else $iMatched=0 $sLen=stringlen($s1) for $tJ=1 to $slen if stringmid($s1,$tJ,1)=stringmid($s2,$tJ,1) Then $iMatched=$imatched+1 endif Next if ($iMatched / $sLen ) > $cMatchLinePercentage then return true Else return false endif EndIf endfuncFull demo code (not in debugging mode, turn $bDebug=True to understand and analyse the details in difference in hex textfiles)expandcollapse popup#include <GDIPlus.au3> #include <ScreenCapture.au3> #include <string.au3> ;~ If debugging output is wanted to understand and analyse the algorithm put this on true/false Const $bDebug=False Const $cMatchLinePercentage=0.99 ;Minimum matching, put on 1 if exact matching is needed on all lines Opt("WinTitleMatchMode", 4) ;Matching windows by advanced options ;~ 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 ; Screen samples ;~ Works with all GDI formats but most stable for the bitmaps BMP, TIFF, PNG ;~ Global Const $Bitmap1Filename = @ScriptDir & "\FULLSCREEN.bmp" ;~ Global Const $Bitmap2Filename = @ScriptDir & "\CALCULATOR.bmp" ;~ Global Const $Bitmap1Filename = @ScriptDir & "\FULLSCREEN.TIFF" ;~ Global Const $Bitmap2Filename = @ScriptDir & "\CALCULATOR.TIFF" ;~ PNG seems to be smarter to use as it minimizes filesize Global Const $Bitmap1Filename = @ScriptDir & "\FULLSCREEN.PNG" Global Const $Bitmap2Filename = @ScriptDir & "\CALCULATOR.PNG" ; Initialize GDI+ library _GDIPlus_Startup() ;Calculator, make sure its started $calcHWND = WinGetHandle("[REGEXPCLASS:.*Calc.*]") If $calcHWND = "" Then Run("calc.exe") Sleep(2000) $calcHWND = WinGetHandle("[REGEXPCLASS:.*Calc.*]") EndIf ;Capture the calculator screen WinActivate($calcHWND) _ScreenCapture_CaptureWnd($Bitmap2Filename, $calcHWND, 0, 0, -1, -1, False) ConsoleWrite("Saving calculator window" & @LF) ; Capture full screen _ScreenCapture_Capture($Bitmap1Filename, 0, 0, -1, -1, False) ConsoleWrite("Saving full screen" & @LF) 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, $Type) Local $tResult $tResult = _FindBMP($BMP1, $BMP2, $Type) ConsoleWrite($tResult & " " & FileGetName($BMP2) & " in " & FileGetName($BMP1) & " ** matchtype " & $Type & @LF) EndFunc ;==>_FindTester _FindTester("SCREEN", $Bitmap2Filename, $c24RGBFullMatch);Find the full calculator screen if not $bDebug=True Then _FindTester("SCREEN", $Bitmap2Filename, $c24RGBPartialMatch);Find the full calculator screen with partial match _FindTester("SCREEN", $Bitmap2Filename, $c16RGBFullMatch);Find the full calculator screen _FindTester("SCREEN", $Bitmap2Filename, $c16RGBPartialMatch);Find the full calculator screen with partial match _FindTester($Bitmap1Filename, $Bitmap2Filename, $c16RGBFullMatch);Find the full calculator screen _FindTester($Bitmap1Filename, $Bitmap2Filename, $c16RGBPartialMatch);Find the full calculator screen with partial match EndIf _GDIPlus_Shutdown() ;=============================================================================== ; 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 $fLine[1];Line number of found line(s), redimmed when second picture size is known 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; Local $iFuzzyDist, $searchFor, $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) if $bDebug=True Then ;~ START debugging ;Get some debugging information FileDelete(@ScriptDir & "\BMP1DATA.TXT") FileDelete(@ScriptDir & "\BMP2DATA.TXT") FileDelete(@ScriptDir & "\COMPAREDLINES.TXT") consolewrite($BMP1Width & @crlf) consolewrite($BMP1Height & @crlf) consolewrite($BMP1LineWidth & @crlf) consolewrite(stringlen($BMP1Data) & @crlf) consolewrite(".{" & $BMP1LineWidth & "}"& @CRLF) consolewrite(".{" & $BMP2LineWidth & "}"& @CRLF) $tDebug=StringRegExpReplace(_stringtohex($BMP1Data),"(.{" & $BMP1LineWidth*2 & "})","$1" & @CRLF) consolewrite(@error & @extended & @CRLF) FileWrite (@ScriptDir & "\BMP1DATA.TXT" , $tdebug) $tDebug=StringRegExpReplace(_stringtohex($BMP2Data),"(.{" & $BMP2LineWidth*2 & "})","$1" & @CRLF) consolewrite(@error & @extended & @CRLF) FileWrite (@ScriptDir & "\BMP2DATA.TXT" , $tdebug) ;~ END debugging EndIf ;For reference of line where in BMP2FindIn a line of BMP2Find was found If $BMP2Height = 0 Then SetError(1, 0, 0) Return False EndIf ReDim $fLine[$BMP2Height] ;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 Else ;Check fuzzy every 10% of lines $iFuzzyDist = Ceiling(($BMP2Height * 0.1)) EndIf $begin = TimerInit() ;Look for each line of the bitmap if it exists in the bitmap to find in For $i = 0 To $BMP2Height - 1 ;Minus imgbytes as last bits are padded with unpredictable bytes (24 bits image assumption) or 2 when 16 bits $searchFor = StringMid($BMP2Data, 1 + ($i * $BMP2LineWidth), ($BMP2LineWidth - $imgBytes)) $iPos = StringInStr($BMP1Data, $searchFor, 2, 1, $iPos) ;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) - $i $foundAtLeft = Int(Mod($iPos, $BMP1LineWidth) / $imgBytes) Else $bMatchPossible = False ExitLoop EndIf While (($i + $iAbove) <= ($BMP2Height - 1)) And ($bMatchPossible = True) $searchFor = StringMid($BMP2Data, 1 + (($i + $iAbove) * $BMP2LineWidth), ($BMP2LineWidth - $imgBytes)) $aboveLine = StringMid($BMP1Data, $iPos + ($iAbove * $BMP1LineWidth), ($BMP2LineWidth - $imgBytes)) if $bDebug=True Then ;~ START debugging $tDebug=StringRegExpReplace(_stringtohex($searchfor),"(.{8})","$1_") FileWrite (@ScriptDir & "\COMPAREDLINES.TXT" , $tDebug & @crlf) $tDebug=StringRegExpReplace(_stringtohex($aboveline),"(.{8})","$1_") FileWrite (@ScriptDir & "\COMPAREDLINES.TXT" , $tDebug & @crlf) If $aboveLine <> $searchFor Then FileWrite (@ScriptDir & "\COMPAREDLINES.TXT" , "** MISMATCH ** of line " & (1+$iAbove) & " in 2nd bitmap at line " & ($foundAtTop + $i) & @crlf) endIf ;~ END debugging EndIf if comparePicLine($aboveline,$searchfor) = false then $bMatchPossible = False ;To remember the area with the best match If $matchedLines >= $HighestMatchingLines Then $HighestMatchingLines = $matchedLines ;Best guess of location $foundAtTop = Int($iPos / $BMP1LineWidth);+ $i - $BMP2Height $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($begin) / 1000 & " seconds" & @LF) ; MouseMove($foundatleft, $foundatTop) ExitLoop Else ;~ consolewrite("i not matched " & $ipos & " " & $matchedlines & @crlf ) EndIf Next ;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 EndFunc ;==>_FindBMP func comparePicLine($s1,$s2) if $s1=$s2 Then return True Else $iMatched=0 $sLen=stringlen($s1) for $tJ=1 to $slen if stringmid($s1,$tJ,1)=stringmid($s2,$tJ,1) Then $iMatched=$imatched+1 endif Next if ($iMatched / $sLen ) > $cMatchLinePercentage then return true Else return false endif EndIf endfunc 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 ;~ 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_PXF32ARGB) $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_PXF32ARGB) $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 Edited January 5, 2013 by junkew FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
junkew Posted January 5, 2013 Posted January 5, 2013 (edited) think the solution will be in the lockbits parameters $GDIP_PXF32PARGB but then I have to change and test a little more[edit] 05 jan 2013: lockbits is not the issue gives same result, its just one part of a pixel different regardless of 2,3 or 4 bytes per pixel.Pixels as shown hexadecimal seems jus a color shade difference which is weird as calculator is saved at sime time as full screenshot726557FF_726456FF_716356FF_716355FF_706355FF726557FF_726456FF_726356FF_716356FF_706355FFsee full module over here Edited January 5, 2013 by junkew 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