Advertisement
CocBotTBC

BMPinBMP

Jan 16th, 2015
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
AutoIt 11.84 KB | None | 0 0
  1. ;===============================================================================
  2. ; Function Name:    findBMP
  3. ; 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)
  4. ; Syntax:        findBMP($BMP1, $BMP2, $MatchType=TRUE)
  5. ;
  6. ; Parameter(s):  $BMP1           = Filename of bitmap to search in
  7. ;                $BMP2           = Filename of bitmap to search for
  8. ;                $MatchType     = c24RGBFullMatch, c24RGBPartialMatch, c16RGBFullMatch, c16RGBPartialMatch
  9. ;
  10. ; Return Value(s): On Success: = Returns Array List
  11. ;                On Failure: = @error 1 (Control was found but there was an error with the DLLCall)
  12. ;
  13. ; Author(s):        JunkEW
  14. ;
  15. ; Note(s):
  16. ;               * Its never an exact match even with TRUE as last few bits are disposed in algorithm and lines below
  17. ;                are not checked under assumption that those are 99.99% of the time correct
  18. ;            * locking bits overview http://www.bobpowell.net/lockingbits.htm
  19. ; ToDo:
  20. ;               * Transparency (when search letters on a different background) http://www.winprog.org/tutorial/transparency.html
  21. ;               * Match quicker by doing a bitblt with srcinvert when first line is found (instead of checking line by line)
  22. ;               * $BMP1 and $BMP2 to be HBITMAP handle as input instead of filenames (will make searching within partial screen easier)
  23. ; Example(s):
  24. ;
  25. ;===============================================================================
  26.  
  27. Func findBMP($BMP1, $BMP2, $MatchType=$c24RGBFullMatch)
  28.     Dim $fLine[1];Line number of found line(s), redimmed when second picture size is known
  29.     Dim $BMP1Data="", $BMP1Width=0, $BMP1Height=0, $BMP1LineWidth=0;
  30.     Dim $BMP2Data="", $BMP2Width=0, $BMP2Height=0, $BMP2LineWidth=0
  31.     Dim $foundAt = "", $matchPossible=FALSE, $matchedLines=0, $foundAtLeft=-1, $foundAtTop=-1
  32.     Dim $bestMatchLine=-1, $HighestMatchingLines=-1; For knowing when no match is found where best area is
  33.     Dim $iPos=1;
  34.     dim $imgBytes, $avData;
  35.  
  36.     local $iFuzzyDist, $searchFor, $iAbove, $bMatchPossible, $aboveLine
  37.     local $j, $imgBits
  38. local $tDebug
  39.  
  40.     if ($MatchType=$c24RGBFullMatch) or ($matchtype=$c24RGBPartialMatch) then
  41.         $imgBytes=3
  42.     Else
  43.         $imgBytes=2
  44.     endif
  45.  
  46. ; Load the bitmap to search in
  47.     getImage($BMP1, $BMP1Data, $BMP1Width, $BMP1Height, $BMP1LineWidth, $imgBytes)
  48.     $BMP1Data = BinaryToString($BMP1Data)
  49.  
  50. ; Load the bitmap to find
  51.     getImage($BMP2, $BMP2Data, $BMP2Width, $BMP2Height, $BMP2LineWidth, $imgBytes)
  52. ;Make it strings to be able to use string functions for searching
  53.     $BMP2Data = BinaryToString($BMP2Data)
  54.  
  55. if $bDebug=True Then
  56. ;~ START debugging
  57. ;Get some debugging information
  58.     FileDelete(@ScriptDir & "\BMP1DATA.TXT")
  59.     FileDelete(@ScriptDir & "\BMP2DATA.TXT")
  60.     FileDelete(@ScriptDir & "\COMPAREDLINES.TXT")
  61.  
  62.     consolewrite($BMP1Width & @crlf)
  63.     consolewrite($BMP1Height & @crlf)
  64.     consolewrite($BMP1LineWidth & @crlf)
  65.     consolewrite(stringlen($BMP1Data) & @crlf)
  66.  
  67.     consolewrite(".{" & $BMP1LineWidth & "}"& @CRLF)
  68.  
  69.     consolewrite(".{" & $BMP2LineWidth & "}"& @CRLF)
  70.     $tDebug=StringRegExpReplace(_stringtohex($BMP1Data),"(.{" & $BMP1LineWidth*2 & "})","$1" & @CRLF)
  71.     consolewrite(@error & @extended & @CRLF)
  72.     FileWrite (@ScriptDir & "\BMP1DATA.TXT" , $tdebug)
  73.  
  74.     $tDebug=StringRegExpReplace(_stringtohex($BMP2Data),"(.{" & $BMP2LineWidth*2 & "})","$1" & @CRLF)
  75.     consolewrite(@error & @extended & @CRLF)
  76.     FileWrite (@ScriptDir & "\BMP2DATA.TXT" , $tdebug)
  77. ;~ END debugging
  78. EndIf
  79.  
  80. ;For reference of line where in BMP2FindIn a line of BMP2Find was found
  81.     If $BMP2Height = 0 Then
  82.         SetError(1,0,0)
  83.         Return False
  84.     EndIf
  85.  
  86.     ReDim $fline[$BMP2Height]
  87.  
  88. ;If exact match check every 1 line else do it more fuzzy (as most likely other lines are unique)
  89.     if ($MatchType=$c24RGBFullMatch) or ($matchtype=$c16RGBFullMatch) Then
  90.         $iFuzzyDist = 1
  91.     Else
  92. ;Check fuzzy every 10% of lines
  93.         $iFuzzyDist = ceiling(($bmp2height * 0.1))
  94.     endIf
  95.  
  96.     $begin = TimerInit()
  97. ;Look for each line of the bitmap if it exists in the bitmap to find in
  98. ;~ Split bitmap to search in lines
  99. ;~  $avData=stringregexp($BMP2Data, ".{1," & $BMP2lineWidth & "}+", 3)
  100.     For $i = 0 To $BMP2Height - 1
  101. ;Minus imgbytes as last bits are padded with unpredictable bytes (24 bits image assumption) or 2 when 16 bits
  102.         $searchFor = StringMid($BMP2Data, 1 + ($i * $BMP2lineWidth), ($BMP2lineWidth - $imgBytes))
  103. ;~      $searchfor=stringleft($avData[$i],$BMP2lineWidth - $imgBytes)
  104.  
  105.         $iPos = StringInStr($BMP1Data, $searchFor, 2, 1, $iPos)
  106. ;       $iPos = StringInStr($BMP1Data, $searchFor)
  107.  
  108.  
  109. ;Look for all lines above if there is also a match
  110. ;Not doing it for the lines below as speed is more important and risk of mismatch on lines below is small
  111.         $iAbove=1
  112.         if $iPos > 0 then
  113.             $bMatchPossible=True
  114.             $matchedLines=1;As first found line is matched we start counting
  115. ;Location of the match
  116.             $foundAtTop = Int($iPos / $BMP1lineWidth) -$i
  117.             $foundAtLeft = int(mod($iPos,$bmp1linewidth) / $imgBytes)
  118.         Else
  119. ;~          No 1st line found so far nothing to start matching
  120.             $bMatchPossible=false
  121.             exitloop
  122.         endif
  123.  
  124.         while (($i+$iAbove) <= ($BMP2Height -1)) and ($bMatchPossible=True)
  125.             $searchFor = StringMid($BMP2Data, 1 + (($i + $iAbove) * $BMP2lineWidth), ($BMP2lineWidth - $imgBytes))
  126. ;~          $searchfor = stringleft($avData[$i+$iAbove],$BMP2lineWidth - $imgBytes)
  127.             $aboveLine = stringmid($BMP1Data,$iPos + ($iAbove * $BMP1LineWidth), ($BMP2LineWidth - $imgBytes))
  128.  
  129.             if $bDebug=True Then
  130.             ;~ START debugging
  131.                 $tDebug=StringRegExpReplace(_stringtohex($searchfor),"(.{8})","$1_")
  132.                 FileWrite (@ScriptDir & "\COMPAREDLINES.TXT" , $tDebug & @crlf)
  133.                 $tDebug=StringRegExpReplace(_stringtohex($aboveline),"(.{8})","$1_")
  134.                 FileWrite (@ScriptDir & "\COMPAREDLINES.TXT" , $tDebug & @crlf)
  135.                 If $aboveLine <> $searchFor Then
  136.                     FileWrite (@ScriptDir & "\COMPAREDLINES.TXT" , "** MISMATCH ** of line " & (1+$iAbove) & " in 2nd bitmap at line " & ($foundAtTop + $i) & @crlf)
  137.                 endIf
  138.             ;~ END debugging
  139.             EndIf
  140.  
  141.             if comparePicLine($aboveline,$searchfor) = false then
  142.                 $bMatchPossible=False
  143. ;To remember the area with the best match
  144.                 if $matchedLines >= $HighestMatchingLines Then
  145.                     $HighestMatchingLines = $matchedLines
  146.  
  147.     ;Best guess of location
  148. ;~                  $foundAtTop = $fline[$i] + $i - $BMP2Height
  149.                     $foundAtTop = Int($iPos / $BMP1lineWidth);+ $i - $BMP2Height
  150.                     $bestMatchLine = Int($iPos / $BMP1lineWidth)
  151.                 EndIf
  152.                 ExitLoop
  153.             EndIf
  154.             $matchedLines=$matchedLines + 1
  155.             $iAbove=$iAbove+$iFuzzyDist
  156.         WEnd
  157.  
  158. ;If bMatchPossible is still true most likely we have found the bitmap
  159.         if $bmatchPossible = True then
  160. ;~          ConsoleWrite("Could match top: " & $foundAtTop & " left: " & $foundAtLeft & " in " & TimerDiff($begin) / 1000 & " seconds" & @LF)
  161. ;           MouseMove($foundatleft,$foundatTop)
  162.             exitloop
  163.         else
  164. ;~          consolewrite("i not matched " & $ipos & " " & $matchedlines & @crlf )
  165.         EndIf
  166.  
  167.     Next
  168.  
  169. ;For some debugging of time
  170. ;   if $bMatchPossible = True Then
  171. ;       ConsoleWrite("Searching took " & TimerDiff($begin) / 1000 & " seconds " & @LF)
  172. ;   Else
  173. ;       ConsoleWrite("NOT FOUND Searching took " & TimerDiff($begin) / 1000 & " seconds" & @LF)
  174. ;   endif
  175.  
  176. ;Return an error if not found else return an array with all information
  177.     if $bMatchPossible = False Then
  178.         SetError(1, 0, 0)
  179.     endif
  180. ;   return stringsplit($bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $bmp2width & ";" & $BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine,";")
  181.     return $bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $bmp2width & ";" & $BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine
  182. EndFunc;==>findBMP
  183.  
  184. func comparePicLine($s1,$s2)
  185.     local $sLen, $iMatched
  186.     if $s1=$s2 Then
  187.         return True
  188.     Else
  189.         $iMatched=0
  190.         $sLen=stringlen($s1)
  191.         for $tJ=1 to $slen
  192.             if stringmid($s1,$tJ,1)=stringmid($s2,$tJ,1) Then
  193.                 $iMatched=$imatched+1
  194.             Else
  195.                 if $bDebug=True Then
  196.                 ;~ START debugging
  197.                     FileWrite (@ScriptDir & "\COMPAREDLINES.TXT" , "Debug mismatch pixel " & $tj & "=" & int($tj/4) & @crlf)
  198.                 endif
  199.             endif
  200.         Next
  201.         if  ($iMatched / $sLen ) > $cMatchLinePercentage then
  202.             return true
  203.         Else
  204.             return false
  205.         endif
  206.     EndIf
  207. endfunc
  208.  
  209. Func GetImage($BMPFile, byref $BMPDataStart, byref $Width, byRef $Height, byref $Stride, $imgBytes=3)
  210. local $Scan0, $pixelData, $hbScreen, $pBitmap, $pBitmapCap, $handle
  211.  
  212. ; Load the bitmap to search in
  213.     If $BMPFile="SCREEN" Then
  214.         $hbScreen=_ScreenCapture_Capture("",0,0,-1,-1,False)
  215.         $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
  216.     Else
  217. ;try to get a handle
  218.         $handle = WinGetHandle($BMPFile)
  219.         If @error Then
  220. ;Assume its an unknown handle so correct filename should be given
  221.             $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
  222.         Else
  223.             $hbScreen=_ScreenCapture_CaptureWnd("",$handle,0,0,-1,-1,False)
  224.             $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
  225.         EndIf
  226.     EndIf
  227.  
  228. ;Get $tagGDIPBITMAPDATA structure
  229. ;~  ConsoleWrite("Bitmap Width:  " & _GDIPlus_ImageGetWidth($pBitmap) & @CRLF )
  230. ;~  ConsoleWrite("Bitmap Height:     " & _GDIPlus_ImageGetHeight($pBitmap) & @CRLF)
  231.  
  232. ;~  24 bits (3 bytes) or 16 bits (2 bytes) comparison
  233.     if ($imgBytes=2) then
  234.         $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF16RGB555)
  235. ;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
  236.     Else
  237.         $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB)
  238. ;~      $BitmapData= _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32ARGB)
  239.     endIf
  240.  
  241.     If @ERROR Then MsgBox(0,"","Error locking region " & @error)
  242.  
  243.     $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.
  244.     $Width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap.
  245.     $Height = DllStructGetData($BitmapData, "Height");Image height - Number of scan lines in the bitmap.
  246.     $PixelFormat = DllStructGetData($BitmapData, "PixelFormat");Pixel format - Integer that specifies the pixel format of the bitmap
  247.     $Scan0 = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap.
  248.  
  249.     $pixelData = DllStructCreate("ubyte lData[" & (abs($Stride) * $Height-1) & "]", $Scan0)
  250.     $BMPDataStart = $BMPDataStart & DllStructGetData($pixeldata,"lData")
  251.  
  252.     _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
  253.     _GDIPlus_ImageDispose ($pBitmap)
  254.     _WinAPI_DeleteObject ($pBitmap)
  255.  
  256. EndFunc;==>GetImage
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement