Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;===============================================================================
- ; Function Name: findBMP
- ; Description: Finds a bitmap (.BMP) in another BMP file (other formats PNG and TIFF work also other formats less usefull GIF, JPEG, Exif, WMF, and EMF should work)
- ; 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, $avData;
- local $iFuzzyDist, $searchFor, $iAbove, $bMatchPossible, $aboveLine
- local $j, $imgBits
- local $tDebug
- 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
- ;~ Split bitmap to search in lines
- ;~ $avData=stringregexp($BMP2Data, ".{1," & $BMP2lineWidth & "}+", 3)
- 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))
- ;~ $searchfor=stringleft($avData[$i],$BMP2lineWidth - $imgBytes)
- $iPos = StringInStr($BMP1Data, $searchFor, 2, 1, $iPos)
- ; $iPos = StringInStr($BMP1Data, $searchFor)
- ;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
- ;~ No 1st line found so far nothing to start matching
- $bMatchPossible=false
- exitloop
- endif
- while (($i+$iAbove) <= ($BMP2Height -1)) and ($bMatchPossible=True)
- $searchFor = StringMid($BMP2Data, 1 + (($i + $iAbove) * $BMP2lineWidth), ($BMP2lineWidth - $imgBytes))
- ;~ $searchfor = stringleft($avData[$i+$iAbove],$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 = $fline[$i] + $i - $BMP2Height
- $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
- ;For some debugging of time
- ; if $bMatchPossible = True Then
- ; ConsoleWrite("Searching took " & TimerDiff($begin) / 1000 & " seconds " & @LF)
- ; Else
- ; ConsoleWrite("NOT FOUND Searching took " & TimerDiff($begin) / 1000 & " seconds" & @LF)
- ; endif
- ;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)
- local $sLen, $iMatched
- 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
- Else
- if $bDebug=True Then
- ;~ START debugging
- FileWrite (@ScriptDir & "\COMPAREDLINES.TXT" , "Debug mismatch pixel " & $tj & "=" & int($tj/4) & @crlf)
- endif
- 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
- ;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)
- ;~ $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
- Else
- $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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement