Nombre: findBMP
; Descripcion: Encuentra un (.BMP) en otro fichero BMP (other formats BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF deberían funcionar pero no probados)
; Syntax: findBMP($BMP1, $BMP2, $MatchType=TRUE)
Salu22:)
Aunque hay unas modificaciones al final del tópico en http://www.autoitscript.com/forum/index ... t&p=815484
El Código original
Código: Seleccionar todo
; 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)
; $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
$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 = $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 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