Jump to content

Can anyone get this to work?


Recommended Posts

This has a function that finds a BMP within another BMP. Use it like this:

$result = _FindBMP($imageToSearch, $imageToFind)

$result[1] will hold True if found, false otherwise.

If found, then $result[3] will hold the x-coordinate and $result[4] will hold the y-coordinate of the location where the image was found (I think).

It doesn't work for me. Can anyone get it to work?

This file is based off of http://www.autoitscript.com/forum/index.php?showtopic=66545

FindBMP.au3

ScreenCaptureFixed.au3

Edited by Phenom
Link to comment
Share on other sites

  • Replies 40
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

The following works for me: (in fact, the originials work for me too)

;===============================================================================
; 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):
;
;===============================================================================

#include "ScreenCaptureFixed.au3"

Global Const $c24RGBFullMatch = 1 ;Load as 24 bits and full match
Global Const $c24RGBPartialMatch = 2 ;Load as 24 bits and partial match
Global Const $c16RGBFullMatch = 3 ;Load as 16 bits and full match
Global Const $c16RGBPartialMatch = 4 ;Load as 16 bits and partial match

Global $result = _FindBMP("image1.bmp", "image2.bmp")

For $I = 0 To $result[0] - 1
    ConsoleWrite($result[$I] & @CRLF)
Next

Func _FindBMP($BMP1, $BMP2, $MatchType = $c24RGBFullMatch)
    Local $BMP1Data = "", $BMP1Width = 0, $BMP1Height = 0, $BMP1LineWidth = 0;
    Local $BMP2Data = "", $BMP2Width = 0, $BMP2Height = 0, $BMP2LineWidth = 0
    Local $matchedLines = 0, $foundAtLeft = -1, $foundAtTop = -1 ; $foundAt = "", $matchPossible = False,
    Local $bestMatchLine = -1, $HighestMatchingLines = -1; For knowing when no match is found where best area is
    Local $iPos = 1;
    Local $imgBytes;

    Local $iFuzzyDist, $searchFor, $iAbove, $bMatchPossible, $aboveLine

    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

;~  Local $fLine[$BMP2Height]; Line number of found line(s), reLocalmed when second picture size is known

    ;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

;~ Local    $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)
    _GDIPlus_Startup()

    Local $Scan0, $pixelData, $hbScreen, $pBitmap, $handle ; $pBitmapCap,

    ; 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
        Local $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.
;~ Local    $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)
    _GDIPlus_Shutdown()
    _WinAPI_DeleteObject($pBitmap)
    _WinAPI_DeleteObject($hbScreen)
EndFunc ;==>_GetImage

#include-once

#include <GDIPlus.au3>
#include <WinAPI.au3>

; #INDEX# =======================================================================================================================
; Title .........: Screen Capture
; AutoIt Version: 3.2.3++
; Language:     English
; Description ...: This module allows you to copy the screen or a region of the screen and save it to file. Depending on the type
;   of image, you can set various image parameters such as pixel format, quality and compression.
; Author ........: Paul Campbell (PaulIA)
; ===============================================================================================================================

; #VARIABLES# ===================================================================================================================
Global $giBMPFormat = $GDIP_PXF24RGB
Global $giJPGQuality = 100
Global $giTIFColorDepth = 24
Global $giTIFCompression = $GDIP_EVTCOMPRESSIONLZW
Global Const $_ScreenCAPTURECONSTANT_SM_CXSCREEN = 0
Global Const $_ScreenCAPTURECONSTANT_SM_CYSCREEN = 1
Global Const $_ScreenCAPTURECONSTANT_SRCCOPY = 0x00CC0020
; ===============================================================================================================================

;==============================================================================================================================
; #CURRENT# =====================================================================================================================
;ScreenCapture_Capture
;ScreenCapture_CaptureWnd
;ScreenCapture_SaveImage
;ScreenCapture_SetBMPFormat
;ScreenCapture_SetJPGQuality
;ScreenCapture_SetTIFColorDepth
;ScreenCapture_SetTIFCompression
; ===============================================================================================================================
;==============================================================================================================================

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_Capture
; Description ...: Captures a region of the screen
; Syntax.........: ScreenCapture_Capture([$sFileName = ""[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]]])
; Parameters ....: $sFileName - Full path and extension of the image file
;   $iLeft  - X coordinate of the upper left corner of the rectangle
;   $iTop   - Y coordinate of the upper left corner of the rectangle
;   $iRight     - X coordinate of the lower right corner of the rectangle. If this is -1, the current screen
;   +width will be used.
;   $iBottom    - Y coordinate of the lower right corner of the rectangle. If this is -1, the current screen
;   +height will be used.
;   $fCursor    - If True the cursor will be captured with the image
; Return values .: See remarks
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
;   function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
;   finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: _WinAPI_DeleteObject
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_Capture($sFileName = "", $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)
    Local $iH, $iW, $hWnd, $hDDC, $hCDC, $hBMP, $aCursor, $aIcon, $hIcon

    If $iRight = -1 Then $iRight = _WinAPI_GetSystemMetrics($_ScreenCAPTURECONSTANT_SM_CXSCREEN)
    If $iBottom = -1 Then $iBottom = _WinAPI_GetSystemMetrics($_ScreenCAPTURECONSTANT_SM_CYSCREEN)
    If $iRight < $iLeft Then Return SetError(-1, 0, 0)
    If $iBottom < $iTop Then Return SetError(-2, 0, 0)

    $iW = $iRight - $iLeft
    $iH = $iBottom - $iTop
    $hWnd = _WinAPI_GetDesktopWindow()
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iW, $iH)
    _WinAPI_SelectObject($hCDC, $hBMP)
    _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, $iLeft, $iTop, $_ScreenCAPTURECONSTANT_SRCCOPY)

    If $fCursor Then
        $aCursor = _WinAPI_GetCursorInfo()
        If $aCursor[1] Then
            $hIcon = _WinAPI_CopyIcon($aCursor[2])
            $aIcon = _WinAPI_GetIconInfo($hIcon)
            _WinAPI_DrawIcon($hCDC, $aCursor[3] - $aIcon[2] - $iLeft, $aCursor[4] - $aIcon[3] - $iTop, $hIcon)
            _WinAPI_DestroyIcon($hIcon)
            _WinAPI_DeleteObject($aIcon[4]); <- THIS!
            _WinAPI_DeleteObject($aIcon[5]); <- THIS!
        EndIf
    EndIf

    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
    If $sFileName = "" Then Return $hBMP

    ScreenCapture_SaveImage($sFileName, $hBMP)
    _WinAPI_DeleteObject($hBMP)
EndFunc ;==>ScreenCapture_Capture

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_CaptureWnd
; Description ...: Captures a screen shot of a specified window
; Syntax.........: ScreenCapture_CaptureWnd($sFileName, $hWnd[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]])
; Parameters ....: $sFileName - Full path and extension of the image file
;   $hWnd   - Handle to the window to be captured
;   $iLeft  - X coordinate of the upper left corner of the client rectangle
;   $iTop   - Y coordinate of the upper left corner of the client rectangle
;   $iRight     - X coordinate of the lower right corner of the rectangle
;   $iBottom    - Y coordinate of the lower right corner of the rectangle
;   $fCursor    - If True the cursor will be captured with the image
; Return values .: See remarks
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
;   function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
;   finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle. All coordinates are in
;   client coordinate mode.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: _WinAPI_DeleteObject
; Link ..........;
; Example .......; Yes
; Credits .......: Thanks to SmOke_N for his suggestion for capturing part of the client window
; ===============================================================================================================================
Func ScreenCapture_CaptureWnd($sFileName, $hWnd, $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)
    Local $tRect

    $tRect = _WinAPI_GetWindowRect($hWnd)
    $iLeft += DllStructGetData($tRect, "Left")
    $iTop += DllStructGetData($tRect, "Top")
    If $iRight = -1 Then $iRight = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    If $iBottom = -1 Then $iBottom = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")
    $iRight += DllStructGetData($tRect, "Left")
    $iBottom += DllStructGetData($tRect, "Top")
    If $iLeft > DllStructGetData($tRect, "Right") Then $iLeft = DllStructGetData($tRect, "Left")
    If $iTop > DllStructGetData($tRect, "Bottom") Then $iTop = DllStructGetData($tRect, "Top")
    If $iRight > DllStructGetData($tRect, "Right") Then $iRight = DllStructGetData($tRect, "Right")
    If $iBottom > DllStructGetData($tRect, "Bottom") Then $iBottom = DllStructGetData($tRect, "Bottom")
    Return ScreenCapture_Capture($sFileName, $iLeft, $iTop, $iRight, $iBottom, $fCursor)
EndFunc ;==>ScreenCapture_CaptureWnd

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SaveImage
; Description ...: Saves an image to file
; Syntax.........: ScreenCapture_SaveImage($sFileName, $hBitmap[, $fFreeBmp = True])
; Parameters ....: $sFileName - Full path and extension of the bitmap file to be saved
;   $hBitmap    - HBITMAP handle
;   $fFreeBmp   - If True, hBitmap will be freed on a successful save
; Return values .: Success  - True
;   Failure     - False
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: This function saves a bitmap to file, converting it to the image format specified by the file name extension.
;   For Windows XP, the valid extensions are BMP, GIF, JPEG, PNG and TIF.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: ScreenCapture_Capture
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_SaveImage($sFileName, $hBitmap, $fFreeBmp = True)
    Local $hClone, $sCLSID, $tData, $sExt, $hImage, $pParams, $tParams, $iResult, $iX, $iY

    _GDIPlus_Startup()
    If @error Then Return SetError(-1, -1, False)

    $sExt = StringUpper(__GDIPlus_ExtractFileExt($sFileName))
    $sCLSID = _GDIPlus_EncodersGetCLSID($sExt)
    If $sCLSID = "" Then Return SetError(-2, -2, False)
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    If @error Then Return SetError(-3, -3, False)

    Switch $sExt
        Case "BMP"
            $iX = _GDIPlus_ImageGetWidth($hImage)
            $iY = _GDIPlus_ImageGetHeight($hImage)
            $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY, $giBMPFormat)
            _GDIPlus_ImageDispose($hImage)
            $hImage = $hClone
        Case "JPG", "JPEG"
            $tParams = _GDIPlus_ParamInit(1)
            $tData = DllStructCreate("int Quality")
            DllStructSetData($tData, "Quality", $giJPGQuality)
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tData))
        Case "TIF", "TIFF"
            $tParams = _GDIPlus_ParamInit(2)
            $tData = DllStructCreate("int ColorDepth;int Compression")
            DllStructSetData($tData, "ColorDepth", $giTIFColorDepth)
            DllStructSetData($tData, "Compression", $giTIFCompression)
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOLORDEPTH, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "ColorDepth"))
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOMPRESSION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Compression"))
    EndSwitch
    If IsDllStruct($tParams) Then $pParams = DllStructGetPtr($tParams)

    $iResult = _GDIPlus_ImageSaveToFileEx($hImage, $sFileName, $sCLSID, $pParams)
    _GDIPlus_ImageDispose($hImage)
    If $fFreeBmp Then _WinAPI_DeleteObject($hBitmap)
    _GDIPlus_Shutdown()

    Return SetError($iResult = False, 0, $iResult = True)
EndFunc ;==>ScreenCapture_SaveImage

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetBMPFormat
; Description ...: Sets the bit format that will be used for BMP screen captures
; Syntax.........: ScreenCapture_SetBMPFormat($iFormat)
; Parameters ....: $iFormat     - Image bits per pixel (bpp) setting:
;   |0 = 16 bpp; 5 bits for each RGB component
;   |1 = 16 bpp; 5 bits for red, 6 bits for green and 5 bits blue
;   |2 = 24 bpp; 8 bits for each RGB component
;   |3 = 32 bpp; 8 bits for each RGB component. No alpha component.
;   |4 = 32 bpp; 8 bits for each RGB and alpha component
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, BMP screen captures default to 24 bpp
; Related .......:
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_SetBMPFormat($iFormat)
    Switch $iFormat
        Case 0
            $giBMPFormat = $GDIP_PXF16RGB555
        Case 1
            $giBMPFormat = $GDIP_PXF16RGB565
        Case 2
            $giBMPFormat = $GDIP_PXF24RGB
        Case 3
            $giBMPFormat = $GDIP_PXF32RGB
        Case 4
            $giBMPFormat = $GDIP_PXF32ARGB
        Case Else
            $giBMPFormat = $GDIP_PXF24RGB
    EndSwitch
EndFunc ;==>ScreenCapture_SetBMPFormat

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetJPGQuality
; Description ...: Sets the quality level that will be used for JPEG screen captures
; Syntax.........: ScreenCapture_SetJPGQuality($iQuality)
; Parameters ....: $iQuality    - The quality level of the image. Must be in the range of 0 to 100.
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, JPEG screen captures default to a quality level of 100
; Related .......:
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetJPGQuality($iQuality)
    If $iQuality < 0 Then $iQuality = 0
    If $iQuality > 100 Then $iQuality = 100
    $giJPGQuality = $iQuality
EndFunc ;==>ScreenCapture_SetJPGQuality

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetTIFColorDepth
; Description ...: Sets the color depth used for TIFF screen captures
; Syntax.........: ScreenCapture_SetTIFColorDepth($iDepth)
; Parameters ....: $iDepth  - Image color depth:
;   | 0 - Default encoder color depth
;   |24 - 24 bit
;   |32 - 32 bit
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, TIFF screen captures default to 24 bits
; Related .......: ScreenCapture_SetTIFCompression
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetTIFColorDepth($iDepth)
    Switch $iDepth
        Case 24
            $giTIFColorDepth = 24
        Case 32
            $giTIFColorDepth = 32
        Case Else
            $giTIFColorDepth = 0
    EndSwitch
EndFunc ;==>ScreenCapture_SetTIFColorDepth

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetTIFCompression
; Description ...: Sets the compression used for TIFF screen captures
; Syntax.........: ScreenCapture_SetTIFCompression($iCompress)
; Parameters ....: $iCompress - Image compression type:
;   |0 - Default encoder compression
;   |1 - No compression
;   |2 - LZW compression
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, TIF screen captures default to LZW compression
; Related .......: ScreenCapture_SetTIFColorDepth
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetTIFCompression($iCompress)
    Switch $iCompress
        Case 1
            $giTIFCompression = $GDIP_EVTCOMPRESSIONNONE
        Case 2
            $giTIFCompression = $GDIP_EVTCOMPRESSIONLZW
        Case Else
            $giTIFCompression = 0
    EndSwitch
EndFunc ;==>ScreenCapture_SetTIFCompression
Edited by jaberwocky6669
Link to comment
Share on other sites

When I try to run that I get the following error in FindBMP.au3

(36) : ==> Subscript used with non-Array variable.:

For $I = 0 To $result[0]

For $I = 0 To $result^ ERROR

*facepalm* I fixed it. THat's what happens when I don't test every single little thing I do!
Link to comment
Share on other sites

Check out this remake that I chunked together using AutoItObject:

#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_Fileversion=0.0.0.55
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=p
#AutoIt3Wrapper_Res_Language=1033
#AutoIt3Wrapper_AU3Check_Stop_OnWarning=y
#AutoIt3Wrapper_AU3Check_Parameters=-w 1 -w 2 -w 3 -w 4 -w 6 -d -I "D:\AutoIt\AutoIt Scripts\Includes"
#AutoIt3Wrapper_Run_Tidy=y
#Tidy_Parameters=/sfc
#AutoIt3Wrapper_Run_After=md "%scriptdir%\Versions\%fileversion%"
#AutoIt3Wrapper_Run_After=copy "%in%" "%scriptdir%\Versions\%fileversion%\%scriptfile%%fileversion%.au3"
#AutoIt3Wrapper_Run_After=copy "%out%" "%scriptdir%\Versions\%fileversion%\%scriptfile%%fileversion%.exe"
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include "AutoItObject.au3"
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <Array.au3>

_AutoItObject_Startup()

Global $BMPinBMP = BMPinBMP()

Global $result = $BMPinBMP.FindBMP("image1.bmp", "image2.bmp") ; substitute your own images here

If IsArray($result) Then
    For $i = 0 To UBound($result) - 1
        ConsoleWrite($result[$i] & @CRLF)
    Next
EndIf

$BMPinBMP = 0

_AutoItObject_Shutdown()

#region BMPinBMP Object
Func BMPinBMP()
    Local $this = _AutoItObject_Create(ScreenCapture())
    _AutoItObject_AddProperty($this, "c24RGBFullMatch", $ELSCOPE_PRIVATE, 1) ;Load as 24 bits and full match
    _AutoItObject_AddProperty($this, "c24RGBPartialMatch", $ELSCOPE_PRIVATE, 2) ;Load as 24 bits and partial match
    _AutoItObject_AddProperty($this, "c16RGBFullMatch", $ELSCOPE_PRIVATE, 3) ;Load as 16 bits and full match
    _AutoItObject_AddProperty($this, "c16RGBPartialMatch", $ELSCOPE_PRIVATE, 4) ;Load as 16 bits and partial match
    _AutoItObject_AddProperty($this, "SuccessArr", $ELSCOPE_PRIVATE)
    _AutoItObject_AddProperty($this, "BMP1Height", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP1Width", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP1LineWidth", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP1Data", $ELSCOPE_PRIVATE, 1)
    _AutoItObject_AddProperty($this, "BMP2Height", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP2Width", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP2LineWidth", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP2Data", $ELSCOPE_PRIVATE, 2)
    _AutoItObject_AddDestructor($this, "BMPinBMP_dtor")
    _AutoItObject_AddMethod($this, "FindBMP", "BMPinBMP_FindBMP")
    _AutoItObject_AddMethod($this, "GetImage", "BMPinBMP_GetImage", True)
    _AutoItObject_AddMethod($this, "", "BMPinBMP_")
    Return $this
EndFunc ;==>BMPinBMP

Func BMPinBMP_FindBMP($this, $BMP1, $BMP2)
    Local $MatchType = $this.c24RGBFullMatch
    Local $matchedLines = 0, $foundAtLeft = -1, $foundAtTop = -1 ; $foundAt = "", $matchPossible = False,
    Local $bestMatchLine = -1, $HighestMatchingLines = -1; For knowing when no match is found where best area is
    Local $iPos = 1, $iFuzzyDist, $searchFor, $iAbove, $bMatchPossible, $aboveLine

    If ($MatchType = $this.c24RGBFullMatch) Or ($MatchType = $this.c24RGBPartialMatch) Then
        Local $imgBytes = 3
    Else
        $imgBytes = 2
    EndIf

    ; Load the bitmap to search in
    $this.GetImage($BMP1, 1, $imgBytes)
    $this.BMP1Data = BinaryToString($this.BMP1Data)

    ; Load the bitmap to find
    $this.GetImage($BMP2, 2, $imgBytes)
    ;Make it a string to be able to use string functions for searching
    $this.BMP2Data = BinaryToString($this.BMP2Data)

    ;For reference of line where in BMP2FindIn a line of BMP2Find was found
    If $this.BMP2Height = 0 Then Return SetError(1, 0, 0)

;~  Local $fLine[$BMP2Height]; Line number of found line(s), reLocalmed when second picture size is known

    ;If exact match check every 1 line else do it more fuzzy (as most likely other lines are unique)
    If ($MatchType = $this.c24RGBFullMatch) Or ($MatchType = $this.c16RGBFullMatch) Then
        $iFuzzyDist = 1
    Else
        ;Check fuzzy every 10% of lines
        $iFuzzyDist = Ceiling(($this.BMP2Height * 0.1))
    EndIf
;~ Local $begin = TimerInit()
    For $i = 0 To $this.BMP2Height - 1 ;Look for each line of the bitmap if it exists in the bitmap to find in
        ;Minus imgbytes as last bits are padded with unpredictable bytes (24 bits image assumption) or 2 when 16 bits
        $searchFor = StringMid($this.BMP2Data, 1 + ($i * $this.BMP2LineWidth), ($this.BMP2LineWidth - $imgBytes))
        $iPos = StringInStr($this.BMP1Data, $searchFor, 2, 1, $iPos)
        ;$iPos = StringInStr($this.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 / $this.BMP1LineWidth) - $i
            $foundAtLeft = Int(Mod($iPos, $this.BMP1LineWidth) / $imgBytes)
        Else
            $bMatchPossible = False
            ExitLoop
        EndIf

        While (($i + $iAbove) <= ($this.BMP2Height - 1)) And ($bMatchPossible = True)
            $searchFor = StringMid($this.BMP2Data, 1 + (($i + $iAbove) * $this.BMP2LineWidth), ($this.BMP2LineWidth - $imgBytes))
            $aboveLine = StringMid($this.BMP1Data, $iPos + ($iAbove * $this.BMP1LineWidth), ($this.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 - $this.BMP2Height
                    $foundAtTop = Int($iPos / $this.BMP1LineWidth);+ $i - $this.BMP2Height
                    $bestMatchLine = Int($iPos / $this.BMP1LineWidth)
                EndIf
                ExitLoop
            EndIf

            $matchedLines += 1
            $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)

    $this.SuccessArr = StringSplit($bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $this.BMP2Width & ";" & $this.BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine, ";", 2)
    ;Return $bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $this.bmp2width & ";" & $this.BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine

    Return $this.SuccessArr
EndFunc ;==>BMPinBMP_FindBMP

Func BMPinBMP_GetImage($this, $BMPFile, $image, $imgBytes = 3)
    _GDIPlus_Startup()

    If $BMPFile == "SCREEN" Then ; Load the bitmap to search in
        Local $hbScreen = $this.Capture("", 0, 0, -1, -1, False)
        Local $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    Else
        ;try to get a handle
        Local $handle = WinGetHandle($BMPFile)

        If @error Then ;Assume its an unknown handle so correct filename should be given
            $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
        Else
            $hbScreen = $this.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
        Local $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)

    If $image = 1 Then
        $this.BMP1LineWidth = 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.
        $this.BMP1Width = DllStructGetData($BitmapData, "Width") ;Image width - Number of pixels in one scan line of the bitmap.
        $this.BMP1Height = DllStructGetData($BitmapData, "Height") ;Image height - Number of scan lines in the bitmap.
;~      Local $PixelFormat = DllStructGetData($BitmapData, "PixelFormat") ;Pixel format - Integer that specifies the pixel format of the bitmap
        Local $Scan0 = DllStructGetData($BitmapData, "Scan0") ;Scan0 - Pointer to the first (index 0) scan line of the bitmap.
        Local $pixelData = DllStructCreate("ubyte lData[" & (Abs($this.BMP1LineWidth) * $this.BMP1Height - 1) & "]", $Scan0)
        $this.BMP1Data = DllStructGetData($pixelData, "lData")
    ElseIf $image = 2 Then
        $this.BMP2LineWidth = 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.
        $this.BMP2Width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap.
        $this.BMP2Height = 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($this.BMP2LineWidth) * $this.BMP2Height - 1) & "]", $Scan0)
        $this.BMP2Data = DllStructGetData($pixelData, "lData")
    EndIf

    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
    _GDIPlus_ImageDispose($pBitmap)
    _GDIPlus_Shutdown()
;~  _WinAPI_DeleteObject($pBitmap)
;~  _WinAPI_DeleteObject($hbScreen)

    Return $this
EndFunc ;==>BMPinBMP_GetImage
#endregion BMPinBMP Object

#region ScreenCapture Object
; #INDEX# =======================================================================================================================
; Title .........: Screen Capture
; AutoIt Version: 3.2.3++
; Language:     English
; Description ...: This module allows you to copy the screen or a region of the screen and save it to file. Depending on the type
;   of image, you can set various image parameters such as pixel format, quality and compression.
; Author ........: Paul Campbell (PaulIA)
; ===============================================================================================================================

; #CURRENT# =====================================================================================================================
;ScreenCapture_Capture
;ScreenCapture_CaptureWnd
;ScreenCapture_SaveImage
;ScreenCapture_SetBMPFormat
;ScreenCapture_SetJPGQuality
;ScreenCapture_SetTIFColorDepth
;ScreenCapture_SetTIFCompression
; ===============================================================================================================================

Func ScreenCapture()
    Local $this = _AutoItObject_Create()
    _AutoItObject_AddProperty($this, "giBMPFormat", $ELSCOPE_PRIVATE, $GDIP_PXF24RGB)
    _AutoItObject_AddProperty($this, "giJPGQuality", $ELSCOPE_PRIVATE, 100)
    _AutoItObject_AddProperty($this, "giTIFColorDepth", $ELSCOPE_PRIVATE, 24)
    _AutoItObject_AddProperty($this, "giTIFCompression", $ELSCOPE_PRIVATE, $GDIP_EVTCOMPRESSIONLZW)
    _AutoItObject_AddProperty($this, "ScreenCAPTURECONSTANT_SM_CXSCREEN", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "ScreenCAPTURECONSTANT_SM_CYSCREEN", $ELSCOPE_PRIVATE, 1)
    _AutoItObject_AddProperty($this, "ScreenCAPTURECONSTANT_SRCCOPY", $ELSCOPE_PRIVATE, 0x00CC0020)
    _AutoItObject_AddMethod($this, "Capture", "ScreenCapture_Capture", True)
    _AutoItObject_AddMethod($this, "CaptureWnd", "ScreenCapture_CaptureWnd", True)
    _AutoItObject_AddMethod($this, "SaveImage", "ScreenCapture_SaveImage", True)
    _AutoItObject_AddMethod($this, "SetBMPFormat", "ScreenCapture_SetBMPFormat", True)
    _AutoItObject_AddMethod($this, "SetJPGQuality", "ScreenCapture_SetJPGQuality", True)
    _AutoItObject_AddMethod($this, "SetTIFColorDepth", "ScreenCapture_SetTIFColorDepth", True)
    _AutoItObject_AddMethod($this, "SetTIFCompression", "ScreenCapture_SetTIFCompression", True)
    Return $this
EndFunc ;==>ScreenCapture

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_Capture
; Description ...: Captures a region of the screen
; Syntax.........: ScreenCapture_Capture([$sFileName = ""[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]]])
; Parameters ....: $sFileName - Full path and extension of the image file
;   $iLeft  - X coordinate of the upper left corner of the rectangle
;   $iTop   - Y coordinate of the upper left corner of the rectangle
;   $iRight     - X coordinate of the lower right corner of the rectangle. If this is -1, the current screen
;   +width will be used.
;   $iBottom    - Y coordinate of the lower right corner of the rectangle. If this is -1, the current screen
;   +height will be used.
;   $fCursor    - If True the cursor will be captured with the image
; Return values .: See remarks
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
;   function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
;   finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: _WinAPI_DeleteObject
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_Capture($this, $sFileName = "", $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)
    Local $iH, $iW, $hWnd, $hDDC, $hCDC, $hBMP, $aCursor, $aIcon, $hIcon

    If $iRight = -1 Then $iRight = _WinAPI_GetSystemMetrics($this.ScreenCAPTURECONSTANT_SM_CXSCREEN)
    If $iBottom = -1 Then $iBottom = _WinAPI_GetSystemMetrics($this.ScreenCAPTURECONSTANT_SM_CYSCREEN)
    If $iRight < $iLeft Then Return SetError(-1, 0, 0)
    If $iBottom < $iTop Then Return SetError(-2, 0, 0)

    $iW = $iRight - $iLeft
    $iH = $iBottom - $iTop
    $hWnd = _WinAPI_GetDesktopWindow()
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iW, $iH)
    _WinAPI_SelectObject($hCDC, $hBMP)
    _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, $iLeft, $iTop, $this.ScreenCAPTURECONSTANT_SRCCOPY)

    If $fCursor Then
        $aCursor = _WinAPI_GetCursorInfo()
        If $aCursor[1] Then
            $hIcon = _WinAPI_CopyIcon($aCursor[2])
            $aIcon = _WinAPI_GetIconInfo($hIcon)
            _WinAPI_DrawIcon($hCDC, $aCursor[3] - $aIcon[2] - $iLeft, $aCursor[4] - $aIcon[3] - $iTop, $hIcon)
            _WinAPI_DestroyIcon($hIcon)
            _WinAPI_DeleteObject($aIcon[4]); <- THIS!
            _WinAPI_DeleteObject($aIcon[5]); <- THIS!
        EndIf
    EndIf

    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
    If $sFileName = "" Then Return $hBMP

    $this.SaveImage($sFileName, $hBMP)
    _WinAPI_DeleteObject($hBMP)
EndFunc ;==>ScreenCapture_Capture

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_CaptureWnd
; Description ...: Captures a screen shot of a specified window
; Syntax.........: ScreenCapture_CaptureWnd($sFileName, $hWnd[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]])
; Parameters ....: $sFileName - Full path and extension of the image file
;   $hWnd   - Handle to the window to be captured
;   $iLeft  - X coordinate of the upper left corner of the client rectangle
;   $iTop   - Y coordinate of the upper left corner of the client rectangle
;   $iRight     - X coordinate of the lower right corner of the rectangle
;   $iBottom    - Y coordinate of the lower right corner of the rectangle
;   $fCursor    - If True the cursor will be captured with the image
; Return values .: See remarks
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
;   function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
;   finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle. All coordinates are in
;   client coordinate mode.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: _WinAPI_DeleteObject
; Link ..........;
; Example .......; Yes
; Credits .......: Thanks to SmOke_N for his suggestion for capturing part of the client window
; ===============================================================================================================================
Func ScreenCapture_CaptureWnd($sFileName, $hWnd, $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)
    Local $tRect

    $tRect = _WinAPI_GetWindowRect($hWnd)
    $iLeft += DllStructGetData($tRect, "Left")
    $iTop += DllStructGetData($tRect, "Top")
    If $iRight = -1 Then $iRight = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    If $iBottom = -1 Then $iBottom = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")
    $iRight += DllStructGetData($tRect, "Left")
    $iBottom += DllStructGetData($tRect, "Top")
    If $iLeft > DllStructGetData($tRect, "Right") Then $iLeft = DllStructGetData($tRect, "Left")
    If $iTop > DllStructGetData($tRect, "Bottom") Then $iTop = DllStructGetData($tRect, "Top")
    If $iRight > DllStructGetData($tRect, "Right") Then $iRight = DllStructGetData($tRect, "Right")
    If $iBottom > DllStructGetData($tRect, "Bottom") Then $iBottom = DllStructGetData($tRect, "Bottom")
    Return ScreenCapture_Capture($sFileName, $iLeft, $iTop, $iRight, $iBottom, $fCursor)
EndFunc ;==>ScreenCapture_CaptureWnd

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SaveImage
; Description ...: Saves an image to file
; Syntax.........: ScreenCapture_SaveImage($sFileName, $hBitmap[, $fFreeBmp = True])
; Parameters ....: $sFileName - Full path and extension of the bitmap file to be saved
;   $hBitmap    - HBITMAP handle
;   $fFreeBmp   - If True, hBitmap will be freed on a successful save
; Return values .: Success  - True
;   Failure     - False
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: This function saves a bitmap to file, converting it to the image format specified by the file name extension.
;   For Windows XP, the valid extensions are BMP, GIF, JPEG, PNG and TIF.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: ScreenCapture_Capture
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_SaveImage($this, $sFileName, $hBitmap, $fFreeBmp = True)
    Local $hClone, $sCLSID, $tData, $sExt, $hImage, $pParams, $tParams, $iResult, $iX, $iY

    _GDIPlus_Startup()

    If @error Then Return SetError(-1, -1, False)

    $sExt = StringUpper(__GDIPlus_ExtractFileExt($sFileName))
    $sCLSID = _GDIPlus_EncodersGetCLSID($sExt)
    If $sCLSID = "" Then Return SetError(-2, -2, False)
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    If @error Then Return SetError(-3, -3, False)

    Switch $sExt
        Case "BMP"
            $iX = _GDIPlus_ImageGetWidth($hImage)
            $iY = _GDIPlus_ImageGetHeight($hImage)
            $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY, $this.giBMPFormat)
            _GDIPlus_ImageDispose($hImage)
            $hImage = $hClone
        Case "JPG", "JPEG"
            $tParams = _GDIPlus_ParamInit(1)
            $tData = DllStructCreate("int Quality")
            DllStructSetData($tData, "Quality", $this.giJPGQuality)
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tData))
        Case "TIF", "TIFF"
            $tParams = _GDIPlus_ParamInit(2)
            $tData = DllStructCreate("int ColorDepth;int Compression")
            DllStructSetData($tData, "ColorDepth", $this.giTIFColorDepth)
            DllStructSetData($tData, "Compression", $this.giTIFCompression)
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOLORDEPTH, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "ColorDepth"))
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOMPRESSION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Compression"))
    EndSwitch

    If IsDllStruct($tParams) Then $pParams = DllStructGetPtr($tParams)

    $iResult = _GDIPlus_ImageSaveToFileEx($hImage, $sFileName, $sCLSID, $pParams)

    _GDIPlus_ImageDispose($hImage)

    If $fFreeBmp Then _WinAPI_DeleteObject($hBitmap)

    _GDIPlus_Shutdown()

    Return SetError($iResult = False, 0, $iResult = True)
EndFunc ;==>ScreenCapture_SaveImage

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetBMPFormat
; Description ...: Sets the bit format that will be used for BMP screen captures
; Syntax.........: ScreenCapture_SetBMPFormat($iFormat)
; Parameters ....: $iFormat     - Image bits per pixel (bpp) setting:
;   |0 = 16 bpp; 5 bits for each RGB component
;   |1 = 16 bpp; 5 bits for red, 6 bits for green and 5 bits blue
;   |2 = 24 bpp; 8 bits for each RGB component
;   |3 = 32 bpp; 8 bits for each RGB component. No alpha component.
;   |4 = 32 bpp; 8 bits for each RGB and alpha component
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, BMP screen captures default to 24 bpp
; Related .......:
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_SetBMPFormat($this, $iFormat)
    Switch $iFormat
        Case 0
            $this.giBMPFormat = $GDIP_PXF16RGB555
        Case 1
            $this.giBMPFormat = $GDIP_PXF16RGB565
        Case 2
            $this.giBMPFormat = $GDIP_PXF24RGB
        Case 3
            $this.giBMPFormat = $GDIP_PXF32RGB
        Case 4
            $this.giBMPFormat = $GDIP_PXF32ARGB
        Case Else
            $this.giBMPFormat = $GDIP_PXF24RGB
    EndSwitch

    Return $this
EndFunc ;==>ScreenCapture_SetBMPFormat

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetJPGQuality
; Description ...: Sets the quality level that will be used for JPEG screen captures
; Syntax.........: ScreenCapture_SetJPGQuality($iQuality)
; Parameters ....: $iQuality    - The quality level of the image. Must be in the range of 0 to 100.
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, JPEG screen captures default to a quality level of 100
; Related .......:
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetJPGQuality($this, $iQuality)
    If $iQuality < 0 Then $iQuality = 0
    If $iQuality > 100 Then $iQuality = 100
    $this.giJPGQuality = $iQuality

    Return $this
EndFunc ;==>ScreenCapture_SetJPGQuality

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetTIFColorDepth
; Description ...: Sets the color depth used for TIFF screen captures
; Syntax.........: ScreenCapture_SetTIFColorDepth($iDepth)
; Parameters ....: $iDepth  - Image color depth:
;   | 0 - Default encoder color depth
;   |24 - 24 bit
;   |32 - 32 bit
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, TIFF screen captures default to 24 bits
; Related .......: ScreenCapture_SetTIFCompression
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetTIFColorDepth($this, $iDepth)
    Switch $iDepth
        Case 24
            $this.giTIFColorDepth = 24
        Case 32
            $this.giTIFColorDepth = 32
        Case Else
            $this.giTIFColorDepth = 0
    EndSwitch

    Return $this
EndFunc ;==>ScreenCapture_SetTIFColorDepth

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetTIFCompression
; Description ...: Sets the compression used for TIFF screen captures
; Syntax.........: ScreenCapture_SetTIFCompression($iCompress)
; Parameters ....: $iCompress - Image compression type:
;   |0 - Default encoder compression
;   |1 - No compression
;   |2 - LZW compression
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, TIF screen captures default to LZW compression
; Related .......: ScreenCapture_SetTIFColorDepth
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetTIFCompression($this, $iCompress)
    Switch $iCompress
        Case 1
            $this.giTIFCompression = $GDIP_EVTCOMPRESSIONNONE
        Case 2
            $this.giTIFCompression = $GDIP_EVTCOMPRESSIONLZW
        Case Else
            $this.giTIFCompression = 0
    EndSwitch

    Return $this
EndFunc ;==>ScreenCapture_SetTIFCompression
#endregion ScreenCapture Object
Edited by jaberwocky6669
Link to comment
Share on other sites

Is this supposed to go all in one file? Because when I include this file, I get the error

(14,10) : ERROR: can't open include file "AutoItObject.au3"

Yes, all into one file.

Btw, I think I may have found an error. In the GetImage() function there is this line: Local $handle = WinGetHandle($BMPFile). Well, $BMPFile isn't a window. No, nevermind, it's fine.

The only major bug that I see now is that it reports false even though a match was found.

For some reason, whenever a match is found within the two bitmaps then the For loop within the FindBMP function will loop for a second time. This seems to me to be unusual behavior.

Edited by jaberwocky6669
Link to comment
Share on other sites

Ok, I feel confident that I have pretty well debugged this.

#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_Fileversion=0.0.0.55
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=p
#AutoIt3Wrapper_Res_Language=1033
#AutoIt3Wrapper_AU3Check_Stop_OnWarning=y
#AutoIt3Wrapper_AU3Check_Parameters=-w 1 -w 2 -w 3 -w 4 -w 6 -d -I "D:\AutoIt\AutoIt Scripts\Includes"
#AutoIt3Wrapper_Run_Tidy=y
#Tidy_Parameters=/sfc
#AutoIt3Wrapper_Run_After=md "%scriptdir%\Versions\%fileversion%"
#AutoIt3Wrapper_Run_After=copy "%in%" "%scriptdir%\Versions\%fileversion%\%scriptfile%%fileversion%.au3"
#AutoIt3Wrapper_Run_After=copy "%out%" "%scriptdir%\Versions\%fileversion%\%scriptfile%%fileversion%.exe"
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include "AutoItObject.au3"
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <Array.au3>

_AutoItObject_Startup()

Global $BMPinBMP = BMPinBMP()

Global $result = $BMPinBMP.FindBMP("image1.bmp", "image2.bmp", 1) ; substitute your own images here

If IsArray($result) Then
    Global $resultArr[8] = ["Possible Match     ", "Matched Lines   ", "Found at left   ", "Found at top    ", "2nd BMP Width   ", "2nd BMP Height  ", "Highest Matching Lines ", "Best match line  "]

    For $i = 0 To UBound($result) - 1
        ConsoleWrite($resultArr[$i] & $result[$i] & @CRLF)
    Next
EndIf

$BMPinBMP = 0

_AutoItObject_Shutdown()

#region BMPinBMP Object
Func BMPinBMP()
    Local $this = _AutoItObject_Create(ScreenCapture())
    _AutoItObject_AddProperty($this, "c24RGBFullMatch", $ELSCOPE_PRIVATE, 1) ;Load as 24 bits and full match
    _AutoItObject_AddProperty($this, "c24RGBPartialMatch", $ELSCOPE_PRIVATE, 2) ;Load as 24 bits and partial match
    _AutoItObject_AddProperty($this, "c16RGBFullMatch", $ELSCOPE_PRIVATE, 3) ;Load as 16 bits and full match
    _AutoItObject_AddProperty($this, "c16RGBPartialMatch", $ELSCOPE_PRIVATE, 4) ;Load as 16 bits and partial match
    _AutoItObject_AddProperty($this, "SuccessArr", $ELSCOPE_PRIVATE)
    _AutoItObject_AddProperty($this, "BMP1Height", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP1Width", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP1LineWidth", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP1Data", $ELSCOPE_PRIVATE, 1)
    _AutoItObject_AddProperty($this, "BMP2Height", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP2Width", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP2LineWidth", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP2Data", $ELSCOPE_PRIVATE, 2)
    _AutoItObject_AddMethod($this, "FindBMP", "BMPinBMP_FindBMP")
    _AutoItObject_AddMethod($this, "GetImage", "BMPinBMP_GetImage", True)
    Return $this
EndFunc ;==>BMPinBMP

Func BMPinBMP_FindBMP($this, $BMP1, $BMP2, $MatchType = 1)
    Local $matchedLines = 0, $foundAtLeft = -1, $foundAtTop = -1 ; $foundAt = "", $matchPossible = False,
    Local $bestMatchLine = -1, $HighestMatchingLines = -1; For knowing when no match is found where best area is
    Local $iPos = 1, $iFuzzyDist, $searchFor, $iAbove, $aboveLine

    If ($MatchType = $this.c24RGBFullMatch) Or ($MatchType = $this.c24RGBPartialMatch) Then
        Local $imgBytes = 3
    Else
        $imgBytes = 2
    EndIf

    ; Load the bitmap to search in
    $this.GetImage($BMP1, 1, $imgBytes)
    $this.BMP1Data = BinaryToString($this.BMP1Data)

    ; Load the bitmap to find
    $this.GetImage($BMP2, 2, $imgBytes)
    ;Make it a string to be able to use string functions for searching
    $this.BMP2Data = BinaryToString($this.BMP2Data)

    ;For reference of line where in BMP2FindIn a line of BMP2Find was found
    If $this.BMP2Height = 0 Then Return SetError(1)

;~  Local $fLine[$BMP2Height]; Line number of found line(s), reLocalmed when second picture size is known

    ;If exact match check every 1 line else do it more fuzzy (as most likely other lines are unique)
    If ($MatchType = $this.c24RGBFullMatch) Or ($MatchType = $this.c16RGBFullMatch) Then
        $iFuzzyDist = 1
    Else
        ;Check fuzzy every 10% of lines
        $iFuzzyDist = Ceiling(($this.BMP2Height * 0.1))
    EndIf

    Local $bMatchPossible

    For $i = 0 To $this.BMP2Height - 1 ;Look for each line of the bitmap if it exists in the bitmap to find in
        ;Minus imgbytes as last bits are padded with unpredictable bytes (24 bits image assumption) or 2 when 16 bits
        $searchFor = StringMid($this.BMP2Data, 1 + ($i * $this.BMP2LineWidth), ($this.BMP2LineWidth - $imgBytes))
        $iPos = StringInStr($this.BMP1Data, $searchFor, 2, 1, $iPos)
        ;$iPos = StringInStr($this.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 / $this.BMP1LineWidth) - $i
            $foundAtLeft = Int(Mod($iPos, $this.BMP1LineWidth) / $imgBytes)

            While $i + $iAbove <= $this.BMP2Height - 1
                $searchFor = StringMid($this.BMP2Data, 1 + (($i + $iAbove) * $this.BMP2LineWidth), $this.BMP2LineWidth - $imgBytes)
                $aboveLine = StringMid($this.BMP1Data, $iPos + ($iAbove * $this.BMP1LineWidth), $this.BMP2LineWidth - $imgBytes)

                If $aboveLine <> $searchFor Then
                    ;To remember the area with the best match
                    If $matchedLines >= $HighestMatchingLines Then
                        $HighestMatchingLines = $matchedLines
                        ;Best guess of location
;~      $foundAtTop = $fline[$i] + $i - $this.BMP2Height
                        $foundAtTop = Int($iPos / $this.BMP1LineWidth);+ $i - $this.BMP2Height
                        $bestMatchLine = Int($iPos / $this.BMP1LineWidth)
                    EndIf

                    ExitLoop
                EndIf

                $matchedLines += 1
                $iAbove += $iFuzzyDist
            WEnd

        ElseIf $iPos = 0 Then
            Return SetError(2)
        EndIf

        If $bMatchPossible = True Then ExitLoop ;If bMatchPossible is still true most likely we have found the bitmap
    Next

    Return StringSplit($bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $this.BMP2Width & ";" & $this.BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine, ";", 2)
EndFunc ;==>BMPinBMP_FindBMP

Func BMPinBMP_GetImage($this, $BMPFile, $image, $imgBytes = 3)
    _GDIPlus_Startup()

    If $BMPFile == "SCREEN" Then ; Load the bitmap to search in
        Local $hbScreen = $this.Capture("", 0, 0, -1, -1, False)
        Local $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    Else
        ;try to get a handle
        Local $handle = WinGetHandle($BMPFile)

        If @error Then ;Assume its an unknown handle so correct filename should be given
            $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
        Else
            $hbScreen = $this.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
        Local $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)

    If $image = 1 Then
        $this.BMP1LineWidth = 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.
        $this.BMP1Width = DllStructGetData($BitmapData, "Width") ;Image width - Number of pixels in one scan line of the bitmap.
        $this.BMP1Height = DllStructGetData($BitmapData, "Height") ;Image height - Number of scan lines in the bitmap.
;~      Local $PixelFormat = DllStructGetData($BitmapData, "PixelFormat") ;Pixel format - Integer that specifies the pixel format of the bitmap
        Local $Scan0 = DllStructGetData($BitmapData, "Scan0") ;Scan0 - Pointer to the first (index 0) scan line of the bitmap.
        Local $pixelData = DllStructCreate("ubyte lData[" & (Abs($this.BMP1LineWidth) * $this.BMP1Height - 1) & "]", $Scan0)
        $this.BMP1Data = DllStructGetData($pixelData, "lData")
    ElseIf $image = 2 Then
        $this.BMP2LineWidth = 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.
        $this.BMP2Width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap.
        $this.BMP2Height = 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($this.BMP2LineWidth) * $this.BMP2Height - 1) & "]", $Scan0)
        $this.BMP2Data = DllStructGetData($pixelData, "lData")
    EndIf

    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
    _GDIPlus_ImageDispose($pBitmap)
    _GDIPlus_Shutdown()
;~  _WinAPI_DeleteObject($pBitmap)
;~  _WinAPI_DeleteObject($hbScreen)

    Return $this
EndFunc ;==>BMPinBMP_GetImage
#endregion BMPinBMP Object

#region ScreenCapture Object
; #INDEX# =======================================================================================================================
; Title .........: Screen Capture
; AutoIt Version: 3.2.3++
; Language:     English
; Description ...: This module allows you to copy the screen or a region of the screen and save it to file. Depending on the type
;   of image, you can set various image parameters such as pixel format, quality and compression.
; Author ........: Paul Campbell (PaulIA)
; ===============================================================================================================================

; #CURRENT# =====================================================================================================================
;ScreenCapture_Capture
;ScreenCapture_CaptureWnd
;ScreenCapture_SaveImage
;ScreenCapture_SetBMPFormat
;ScreenCapture_SetJPGQuality
;ScreenCapture_SetTIFColorDepth
;ScreenCapture_SetTIFCompression
; ===============================================================================================================================

Func ScreenCapture()
    Local $this = _AutoItObject_Create()
    _AutoItObject_AddProperty($this, "giBMPFormat", $ELSCOPE_PRIVATE, $GDIP_PXF24RGB)
    _AutoItObject_AddProperty($this, "giJPGQuality", $ELSCOPE_PRIVATE, 100)
    _AutoItObject_AddProperty($this, "giTIFColorDepth", $ELSCOPE_PRIVATE, 24)
    _AutoItObject_AddProperty($this, "giTIFCompression", $ELSCOPE_PRIVATE, $GDIP_EVTCOMPRESSIONLZW)
    _AutoItObject_AddProperty($this, "ScreenCAPTURECONSTANT_SM_CXSCREEN", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "ScreenCAPTURECONSTANT_SM_CYSCREEN", $ELSCOPE_PRIVATE, 1)
    _AutoItObject_AddProperty($this, "ScreenCAPTURECONSTANT_SRCCOPY", $ELSCOPE_PRIVATE, 0x00CC0020)
    _AutoItObject_AddMethod($this, "Capture", "ScreenCapture_Capture", True)
    _AutoItObject_AddMethod($this, "CaptureWnd", "ScreenCapture_CaptureWnd", True)
    _AutoItObject_AddMethod($this, "SaveImage", "ScreenCapture_SaveImage", True)
    _AutoItObject_AddMethod($this, "SetBMPFormat", "ScreenCapture_SetBMPFormat", True)
    _AutoItObject_AddMethod($this, "SetJPGQuality", "ScreenCapture_SetJPGQuality", True)
    _AutoItObject_AddMethod($this, "SetTIFColorDepth", "ScreenCapture_SetTIFColorDepth", True)
    _AutoItObject_AddMethod($this, "SetTIFCompression", "ScreenCapture_SetTIFCompression", True)
    Return $this
EndFunc ;==>ScreenCapture

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_Capture
; Description ...: Captures a region of the screen
; Syntax.........: ScreenCapture_Capture([$sFileName = ""[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]]])
; Parameters ....: $sFileName - Full path and extension of the image file
;   $iLeft  - X coordinate of the upper left corner of the rectangle
;   $iTop   - Y coordinate of the upper left corner of the rectangle
;   $iRight     - X coordinate of the lower right corner of the rectangle. If this is -1, the current screen
;   +width will be used.
;   $iBottom    - Y coordinate of the lower right corner of the rectangle. If this is -1, the current screen
;   +height will be used.
;   $fCursor    - If True the cursor will be captured with the image
; Return values .: See remarks
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
;   function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
;   finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: _WinAPI_DeleteObject
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_Capture($this, $sFileName = "", $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)
    Local $iH, $iW, $hWnd, $hDDC, $hCDC, $hBMP, $aCursor, $aIcon, $hIcon

    If $iRight = -1 Then $iRight = _WinAPI_GetSystemMetrics($this.ScreenCAPTURECONSTANT_SM_CXSCREEN)
    If $iBottom = -1 Then $iBottom = _WinAPI_GetSystemMetrics($this.ScreenCAPTURECONSTANT_SM_CYSCREEN)
    If $iRight < $iLeft Then Return SetError(-1, 0, 0)
    If $iBottom < $iTop Then Return SetError(-2, 0, 0)

    $iW = $iRight - $iLeft
    $iH = $iBottom - $iTop
    $hWnd = _WinAPI_GetDesktopWindow()
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iW, $iH)
    _WinAPI_SelectObject($hCDC, $hBMP)
    _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, $iLeft, $iTop, $this.ScreenCAPTURECONSTANT_SRCCOPY)

    If $fCursor Then
        $aCursor = _WinAPI_GetCursorInfo()
        If $aCursor[1] Then
            $hIcon = _WinAPI_CopyIcon($aCursor[2])
            $aIcon = _WinAPI_GetIconInfo($hIcon)
            _WinAPI_DrawIcon($hCDC, $aCursor[3] - $aIcon[2] - $iLeft, $aCursor[4] - $aIcon[3] - $iTop, $hIcon)
            _WinAPI_DestroyIcon($hIcon)
            _WinAPI_DeleteObject($aIcon[4]); <- THIS!
            _WinAPI_DeleteObject($aIcon[5]); <- THIS!
        EndIf
    EndIf

    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
    If $sFileName = "" Then Return $hBMP

    $this.SaveImage($sFileName, $hBMP)
    _WinAPI_DeleteObject($hBMP)
EndFunc ;==>ScreenCapture_Capture

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_CaptureWnd
; Description ...: Captures a screen shot of a specified window
; Syntax.........: ScreenCapture_CaptureWnd($sFileName, $hWnd[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]])
; Parameters ....: $sFileName - Full path and extension of the image file
;   $hWnd   - Handle to the window to be captured
;   $iLeft  - X coordinate of the upper left corner of the client rectangle
;   $iTop   - Y coordinate of the upper left corner of the client rectangle
;   $iRight     - X coordinate of the lower right corner of the rectangle
;   $iBottom    - Y coordinate of the lower right corner of the rectangle
;   $fCursor    - If True the cursor will be captured with the image
; Return values .: See remarks
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
;   function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
;   finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle. All coordinates are in
;   client coordinate mode.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: _WinAPI_DeleteObject
; Link ..........;
; Example .......; Yes
; Credits .......: Thanks to SmOke_N for his suggestion for capturing part of the client window
; ===============================================================================================================================
Func ScreenCapture_CaptureWnd($sFileName, $hWnd, $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)
    Local $tRect

    $tRect = _WinAPI_GetWindowRect($hWnd)
    $iLeft += DllStructGetData($tRect, "Left")
    $iTop += DllStructGetData($tRect, "Top")
    If $iRight = -1 Then $iRight = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    If $iBottom = -1 Then $iBottom = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")
    $iRight += DllStructGetData($tRect, "Left")
    $iBottom += DllStructGetData($tRect, "Top")
    If $iLeft > DllStructGetData($tRect, "Right") Then $iLeft = DllStructGetData($tRect, "Left")
    If $iTop > DllStructGetData($tRect, "Bottom") Then $iTop = DllStructGetData($tRect, "Top")
    If $iRight > DllStructGetData($tRect, "Right") Then $iRight = DllStructGetData($tRect, "Right")
    If $iBottom > DllStructGetData($tRect, "Bottom") Then $iBottom = DllStructGetData($tRect, "Bottom")
    Return ScreenCapture_Capture($sFileName, $iLeft, $iTop, $iRight, $iBottom, $fCursor)
EndFunc ;==>ScreenCapture_CaptureWnd

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SaveImage
; Description ...: Saves an image to file
; Syntax.........: ScreenCapture_SaveImage($sFileName, $hBitmap[, $fFreeBmp = True])
; Parameters ....: $sFileName - Full path and extension of the bitmap file to be saved
;   $hBitmap    - HBITMAP handle
;   $fFreeBmp   - If True, hBitmap will be freed on a successful save
; Return values .: Success  - True
;   Failure     - False
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: This function saves a bitmap to file, converting it to the image format specified by the file name extension.
;   For Windows XP, the valid extensions are BMP, GIF, JPEG, PNG and TIF.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: ScreenCapture_Capture
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_SaveImage($this, $sFileName, $hBitmap, $fFreeBmp = True)
    Local $hClone, $sCLSID, $tData, $sExt, $hImage, $pParams, $tParams, $iResult, $iX, $iY

    _GDIPlus_Startup()

    If @error Then Return SetError(-1, -1, False)

    $sExt = StringUpper(__GDIPlus_ExtractFileExt($sFileName))
    $sCLSID = _GDIPlus_EncodersGetCLSID($sExt)
    If $sCLSID = "" Then Return SetError(-2, -2, False)
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    If @error Then Return SetError(-3, -3, False)

    Switch $sExt
        Case "BMP"
            $iX = _GDIPlus_ImageGetWidth($hImage)
            $iY = _GDIPlus_ImageGetHeight($hImage)
            $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY, $this.giBMPFormat)
            _GDIPlus_ImageDispose($hImage)
            $hImage = $hClone
        Case "JPG", "JPEG"
            $tParams = _GDIPlus_ParamInit(1)
            $tData = DllStructCreate("int Quality")
            DllStructSetData($tData, "Quality", $this.giJPGQuality)
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tData))
        Case "TIF", "TIFF"
            $tParams = _GDIPlus_ParamInit(2)
            $tData = DllStructCreate("int ColorDepth;int Compression")
            DllStructSetData($tData, "ColorDepth", $this.giTIFColorDepth)
            DllStructSetData($tData, "Compression", $this.giTIFCompression)
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOLORDEPTH, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "ColorDepth"))
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOMPRESSION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Compression"))
    EndSwitch

    If IsDllStruct($tParams) Then $pParams = DllStructGetPtr($tParams)

    $iResult = _GDIPlus_ImageSaveToFileEx($hImage, $sFileName, $sCLSID, $pParams)

    _GDIPlus_ImageDispose($hImage)

    If $fFreeBmp Then _WinAPI_DeleteObject($hBitmap)

    _GDIPlus_Shutdown()

    Return SetError($iResult = False, 0, $iResult = True)
EndFunc ;==>ScreenCapture_SaveImage

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetBMPFormat
; Description ...: Sets the bit format that will be used for BMP screen captures
; Syntax.........: ScreenCapture_SetBMPFormat($iFormat)
; Parameters ....: $iFormat     - Image bits per pixel (bpp) setting:
;   |0 = 16 bpp; 5 bits for each RGB component
;   |1 = 16 bpp; 5 bits for red, 6 bits for green and 5 bits blue
;   |2 = 24 bpp; 8 bits for each RGB component
;   |3 = 32 bpp; 8 bits for each RGB component. No alpha component.
;   |4 = 32 bpp; 8 bits for each RGB and alpha component
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, BMP screen captures default to 24 bpp
; Related .......:
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_SetBMPFormat($this, $iFormat)
    Switch $iFormat
        Case 0
            $this.giBMPFormat = $GDIP_PXF16RGB555
        Case 1
            $this.giBMPFormat = $GDIP_PXF16RGB565
        Case 2
            $this.giBMPFormat = $GDIP_PXF24RGB
        Case 3
            $this.giBMPFormat = $GDIP_PXF32RGB
        Case 4
            $this.giBMPFormat = $GDIP_PXF32ARGB
        Case Else
            $this.giBMPFormat = $GDIP_PXF24RGB
    EndSwitch

    Return $this
EndFunc ;==>ScreenCapture_SetBMPFormat

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetJPGQuality
; Description ...: Sets the quality level that will be used for JPEG screen captures
; Syntax.........: ScreenCapture_SetJPGQuality($iQuality)
; Parameters ....: $iQuality    - The quality level of the image. Must be in the range of 0 to 100.
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, JPEG screen captures default to a quality level of 100
; Related .......:
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetJPGQuality($this, $iQuality)
    If $iQuality < 0 Then $iQuality = 0
    If $iQuality > 100 Then $iQuality = 100
    $this.giJPGQuality = $iQuality

    Return $this
EndFunc ;==>ScreenCapture_SetJPGQuality

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetTIFColorDepth
; Description ...: Sets the color depth used for TIFF screen captures
; Syntax.........: ScreenCapture_SetTIFColorDepth($iDepth)
; Parameters ....: $iDepth  - Image color depth:
;   | 0 - Default encoder color depth
;   |24 - 24 bit
;   |32 - 32 bit
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, TIFF screen captures default to 24 bits
; Related .......: ScreenCapture_SetTIFCompression
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetTIFColorDepth($this, $iDepth)
    Switch $iDepth
        Case 24
            $this.giTIFColorDepth = 24
        Case 32
            $this.giTIFColorDepth = 32
        Case Else
            $this.giTIFColorDepth = 0
    EndSwitch

    Return $this
EndFunc ;==>ScreenCapture_SetTIFColorDepth

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetTIFCompression
; Description ...: Sets the compression used for TIFF screen captures
; Syntax.........: ScreenCapture_SetTIFCompression($iCompress)
; Parameters ....: $iCompress - Image compression type:
;   |0 - Default encoder compression
;   |1 - No compression
;   |2 - LZW compression
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, TIF screen captures default to LZW compression
; Related .......: ScreenCapture_SetTIFColorDepth
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetTIFCompression($this, $iCompress)
    Switch $iCompress
        Case 1
            $this.giTIFCompression = $GDIP_EVTCOMPRESSIONNONE
        Case 2
            $this.giTIFCompression = $GDIP_EVTCOMPRESSIONLZW
        Case Else
            $this.giTIFCompression = 0
    EndSwitch

    Return $this
EndFunc ;==>ScreenCapture_SetTIFCompression
#endregion ScreenCapture Object
Edited by jaberwocky6669
Link to comment
Share on other sites

Which function call do I use now instead of _findBMP()?

If you wanted to run my latest code then just put all of that code into one au3 and hit F5. DOn't forget to substitute your images for mine as per the comment.

Everything that you need to know about how to use it is in my latest code.

Alternatively, you could put the following code into a file named 'BMPinBMP Object.au3':

#include-once
#include "AutoItObject.au3"
#include <GDIPlus.au3>
#include <WinAPI.au3>

#region BMPinBMP Object
Func BMPinBMP()
    Local $this = _AutoItObject_Create(ScreenCapture())
    _AutoItObject_AddProperty($this, "c24RGBFullMatch", $ELSCOPE_PRIVATE, 1) ;Load as 24 bits and full match
    _AutoItObject_AddProperty($this, "c24RGBPartialMatch", $ELSCOPE_PRIVATE, 2) ;Load as 24 bits and partial match
    _AutoItObject_AddProperty($this, "c16RGBFullMatch", $ELSCOPE_PRIVATE, 3) ;Load as 16 bits and full match
    _AutoItObject_AddProperty($this, "c16RGBPartialMatch", $ELSCOPE_PRIVATE, 4) ;Load as 16 bits and partial match
    _AutoItObject_AddProperty($this, "SuccessArr", $ELSCOPE_PRIVATE)
    _AutoItObject_AddProperty($this, "BMP1Height", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP1Width", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP1LineWidth", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP1Data", $ELSCOPE_PRIVATE, 1)
    _AutoItObject_AddProperty($this, "BMP2Height", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP2Width", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP2LineWidth", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "BMP2Data", $ELSCOPE_PRIVATE, 2)
    _AutoItObject_AddMethod($this, "FindBMP", "BMPinBMP_FindBMP")
    _AutoItObject_AddMethod($this, "GetImage", "BMPinBMP_GetImage", True)
    Return $this
EndFunc ;==>BMPinBMP

Func BMPinBMP_FindBMP($this, $BMP1, $BMP2, $MatchType = 1)
    Local $matchedLines = 0, $foundAtLeft = -1, $foundAtTop = -1 ; $foundAt = "", $matchPossible = False,
    Local $bestMatchLine = -1, $HighestMatchingLines = -1; For knowing when no match is found where best area is
    Local $iPos = 1, $iFuzzyDist, $searchFor, $iAbove, $aboveLine

    If ($MatchType = $this.c24RGBFullMatch) Or ($MatchType = $this.c24RGBPartialMatch) Then
        Local $imgBytes = 3
    Else
        $imgBytes = 2
    EndIf

    ; Load the bitmap to search in
    $this.GetImage($BMP1, 1, $imgBytes)
    $this.BMP1Data = BinaryToString($this.BMP1Data)

    ; Load the bitmap to find
    $this.GetImage($BMP2, 2, $imgBytes)
    ;Make it a string to be able to use string functions for searching
    $this.BMP2Data = BinaryToString($this.BMP2Data)

    ;For reference of line where in BMP2FindIn a line of BMP2Find was found
    If $this.BMP2Height = 0 Then Return SetError(1)

;~  Local $fLine[$BMP2Height]; Line number of found line(s), reLocalmed when second picture size is known

    ;If exact match check every 1 line else do it more fuzzy (as most likely other lines are unique)
    If ($MatchType = $this.c24RGBFullMatch) Or ($MatchType = $this.c16RGBFullMatch) Then
        $iFuzzyDist = 1
    Else
        ;Check fuzzy every 10% of lines
        $iFuzzyDist = Ceiling(($this.BMP2Height * 0.1))
    EndIf

    Local $bMatchPossible

    For $i = 0 To $this.BMP2Height - 1 ;Look for each line of the bitmap if it exists in the bitmap to find in
        ;Minus imgbytes as last bits are padded with unpredictable bytes (24 bits image assumption) or 2 when 16 bits
        $searchFor = StringMid($this.BMP2Data, 1 + ($i * $this.BMP2LineWidth), ($this.BMP2LineWidth - $imgBytes))
        $iPos = StringInStr($this.BMP1Data, $searchFor, 2, 1, $iPos)
        ;$iPos = StringInStr($this.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 / $this.BMP1LineWidth) - $i
            $foundAtLeft = Int(Mod($iPos, $this.BMP1LineWidth) / $imgBytes)

            While $i + $iAbove <= $this.BMP2Height - 1
                $searchFor = StringMid($this.BMP2Data, 1 + (($i + $iAbove) * $this.BMP2LineWidth), $this.BMP2LineWidth - $imgBytes)
                $aboveLine = StringMid($this.BMP1Data, $iPos + ($iAbove * $this.BMP1LineWidth), $this.BMP2LineWidth - $imgBytes)

                If $aboveLine <> $searchFor Then
                    ;To remember the area with the best match
                    If $matchedLines >= $HighestMatchingLines Then
                        $HighestMatchingLines = $matchedLines
                        ;Best guess of location
;~      $foundAtTop = $fline[$i] + $i - $this.BMP2Height
                        $foundAtTop = Int($iPos / $this.BMP1LineWidth);+ $i - $this.BMP2Height
                        $bestMatchLine = Int($iPos / $this.BMP1LineWidth)
                    EndIf

                    ExitLoop
                EndIf

                $matchedLines += 1
                $iAbove += $iFuzzyDist
            WEnd

        ElseIf $iPos = 0 Then
            Return SetError(2)
        EndIf

        If $bMatchPossible = True Then ExitLoop ;If bMatchPossible is still true most likely we have found the bitmap
    Next

    Return StringSplit($bMatchPossible & ";" & $matchedLines & ";" & $foundAtLeft & ";" & $foundAtTop & ";" & $this.BMP2Width & ";" & $this.BMP2Height & ";" & $HighestMatchingLines & ";" & $bestMatchLine, ";", 2)
EndFunc ;==>BMPinBMP_FindBMP

Func BMPinBMP_GetImage($this, $BMPFile, $image, $imgBytes = 3)
    _GDIPlus_Startup()

    If $BMPFile == "SCREEN" Then ; Load the bitmap to search in
        Local $hbScreen = $this.Capture("", 0, 0, -1, -1, False)
        Local $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    Else
        ;try to get a handle
        Local $handle = WinGetHandle($BMPFile)

        If @error Then ;Assume its an unknown handle so correct filename should be given
            $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
        Else
            $hbScreen = $this.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
        Local $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)

    If $image = 1 Then
        $this.BMP1LineWidth = 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.
        $this.BMP1Width = DllStructGetData($BitmapData, "Width") ;Image width - Number of pixels in one scan line of the bitmap.
        $this.BMP1Height = DllStructGetData($BitmapData, "Height") ;Image height - Number of scan lines in the bitmap.
;~      Local $PixelFormat = DllStructGetData($BitmapData, "PixelFormat") ;Pixel format - Integer that specifies the pixel format of the bitmap
        Local $Scan0 = DllStructGetData($BitmapData, "Scan0") ;Scan0 - Pointer to the first (index 0) scan line of the bitmap.
        Local $pixelData = DllStructCreate("ubyte lData[" & (Abs($this.BMP1LineWidth) * $this.BMP1Height - 1) & "]", $Scan0)
        $this.BMP1Data = DllStructGetData($pixelData, "lData")
    ElseIf $image = 2 Then
        $this.BMP2LineWidth = 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.
        $this.BMP2Width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap.
        $this.BMP2Height = 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($this.BMP2LineWidth) * $this.BMP2Height - 1) & "]", $Scan0)
        $this.BMP2Data = DllStructGetData($pixelData, "lData")
    EndIf

    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
    _GDIPlus_ImageDispose($pBitmap)
    _GDIPlus_Shutdown()
;~  _WinAPI_DeleteObject($pBitmap)
;~  _WinAPI_DeleteObject($hbScreen)

    Return $this
EndFunc ;==>BMPinBMP_GetImage
#endregion BMPinBMP Object

#region ScreenCapture Object
; #INDEX# =======================================================================================================================
; Title .........: Screen Capture
; AutoIt Version: 3.2.3++
; Language:     English
; Description ...: This module allows you to copy the screen or a region of the screen and save it to file. Depending on the type
;   of image, you can set various image parameters such as pixel format, quality and compression.
; Author ........: Paul Campbell (PaulIA)
; ===============================================================================================================================

; #CURRENT# =====================================================================================================================
;ScreenCapture_Capture
;ScreenCapture_CaptureWnd
;ScreenCapture_SaveImage
;ScreenCapture_SetBMPFormat
;ScreenCapture_SetJPGQuality
;ScreenCapture_SetTIFColorDepth
;ScreenCapture_SetTIFCompression
; ===============================================================================================================================

Func ScreenCapture()
    Local $this = _AutoItObject_Create()
    _AutoItObject_AddProperty($this, "giBMPFormat", $ELSCOPE_PRIVATE, $GDIP_PXF24RGB)
    _AutoItObject_AddProperty($this, "giJPGQuality", $ELSCOPE_PRIVATE, 100)
    _AutoItObject_AddProperty($this, "giTIFColorDepth", $ELSCOPE_PRIVATE, 24)
    _AutoItObject_AddProperty($this, "giTIFCompression", $ELSCOPE_PRIVATE, $GDIP_EVTCOMPRESSIONLZW)
    _AutoItObject_AddProperty($this, "ScreenCAPTURECONSTANT_SM_CXSCREEN", $ELSCOPE_PRIVATE, 0)
    _AutoItObject_AddProperty($this, "ScreenCAPTURECONSTANT_SM_CYSCREEN", $ELSCOPE_PRIVATE, 1)
    _AutoItObject_AddProperty($this, "ScreenCAPTURECONSTANT_SRCCOPY", $ELSCOPE_PRIVATE, 0x00CC0020)
    _AutoItObject_AddMethod($this, "Capture", "ScreenCapture_Capture", True)
    _AutoItObject_AddMethod($this, "CaptureWnd", "ScreenCapture_CaptureWnd", True)
    _AutoItObject_AddMethod($this, "SaveImage", "ScreenCapture_SaveImage", True)
    _AutoItObject_AddMethod($this, "SetBMPFormat", "ScreenCapture_SetBMPFormat", True)
    _AutoItObject_AddMethod($this, "SetJPGQuality", "ScreenCapture_SetJPGQuality", True)
    _AutoItObject_AddMethod($this, "SetTIFColorDepth", "ScreenCapture_SetTIFColorDepth", True)
    _AutoItObject_AddMethod($this, "SetTIFCompression", "ScreenCapture_SetTIFCompression", True)
    Return $this
EndFunc ;==>ScreenCapture

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_Capture
; Description ...: Captures a region of the screen
; Syntax.........: ScreenCapture_Capture([$sFileName = ""[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]]])
; Parameters ....: $sFileName - Full path and extension of the image file
;   $iLeft  - X coordinate of the upper left corner of the rectangle
;   $iTop   - Y coordinate of the upper left corner of the rectangle
;   $iRight     - X coordinate of the lower right corner of the rectangle. If this is -1, the current screen
;   +width will be used.
;   $iBottom    - Y coordinate of the lower right corner of the rectangle. If this is -1, the current screen
;   +height will be used.
;   $fCursor    - If True the cursor will be captured with the image
; Return values .: See remarks
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
;   function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
;   finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: _WinAPI_DeleteObject
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_Capture($this, $sFileName = "", $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)
    Local $iH, $iW, $hWnd, $hDDC, $hCDC, $hBMP, $aCursor, $aIcon, $hIcon

    If $iRight = -1 Then $iRight = _WinAPI_GetSystemMetrics($this.ScreenCAPTURECONSTANT_SM_CXSCREEN)
    If $iBottom = -1 Then $iBottom = _WinAPI_GetSystemMetrics($this.ScreenCAPTURECONSTANT_SM_CYSCREEN)
    If $iRight < $iLeft Then Return SetError(-1, 0, 0)
    If $iBottom < $iTop Then Return SetError(-2, 0, 0)

    $iW = $iRight - $iLeft
    $iH = $iBottom - $iTop
    $hWnd = _WinAPI_GetDesktopWindow()
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iW, $iH)
    _WinAPI_SelectObject($hCDC, $hBMP)
    _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, $iLeft, $iTop, $this.ScreenCAPTURECONSTANT_SRCCOPY)

    If $fCursor Then
        $aCursor = _WinAPI_GetCursorInfo()
        If $aCursor[1] Then
            $hIcon = _WinAPI_CopyIcon($aCursor[2])
            $aIcon = _WinAPI_GetIconInfo($hIcon)
            _WinAPI_DrawIcon($hCDC, $aCursor[3] - $aIcon[2] - $iLeft, $aCursor[4] - $aIcon[3] - $iTop, $hIcon)
            _WinAPI_DestroyIcon($hIcon)
            _WinAPI_DeleteObject($aIcon[4]); <- THIS!
            _WinAPI_DeleteObject($aIcon[5]); <- THIS!
        EndIf
    EndIf

    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
    If $sFileName = "" Then Return $hBMP

    $this.SaveImage($sFileName, $hBMP)
    _WinAPI_DeleteObject($hBMP)
EndFunc ;==>ScreenCapture_Capture

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_CaptureWnd
; Description ...: Captures a screen shot of a specified window
; Syntax.........: ScreenCapture_CaptureWnd($sFileName, $hWnd[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]])
; Parameters ....: $sFileName - Full path and extension of the image file
;   $hWnd   - Handle to the window to be captured
;   $iLeft  - X coordinate of the upper left corner of the client rectangle
;   $iTop   - Y coordinate of the upper left corner of the client rectangle
;   $iRight     - X coordinate of the lower right corner of the rectangle
;   $iBottom    - Y coordinate of the lower right corner of the rectangle
;   $fCursor    - If True the cursor will be captured with the image
; Return values .: See remarks
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
;   function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
;   finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle. All coordinates are in
;   client coordinate mode.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: _WinAPI_DeleteObject
; Link ..........;
; Example .......; Yes
; Credits .......: Thanks to SmOke_N for his suggestion for capturing part of the client window
; ===============================================================================================================================
Func ScreenCapture_CaptureWnd($sFileName, $hWnd, $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)
    Local $tRect

    $tRect = _WinAPI_GetWindowRect($hWnd)
    $iLeft += DllStructGetData($tRect, "Left")
    $iTop += DllStructGetData($tRect, "Top")
    If $iRight = -1 Then $iRight = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    If $iBottom = -1 Then $iBottom = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")
    $iRight += DllStructGetData($tRect, "Left")
    $iBottom += DllStructGetData($tRect, "Top")
    If $iLeft > DllStructGetData($tRect, "Right") Then $iLeft = DllStructGetData($tRect, "Left")
    If $iTop > DllStructGetData($tRect, "Bottom") Then $iTop = DllStructGetData($tRect, "Top")
    If $iRight > DllStructGetData($tRect, "Right") Then $iRight = DllStructGetData($tRect, "Right")
    If $iBottom > DllStructGetData($tRect, "Bottom") Then $iBottom = DllStructGetData($tRect, "Bottom")
    Return ScreenCapture_Capture($sFileName, $iLeft, $iTop, $iRight, $iBottom, $fCursor)
EndFunc ;==>ScreenCapture_CaptureWnd

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SaveImage
; Description ...: Saves an image to file
; Syntax.........: ScreenCapture_SaveImage($sFileName, $hBitmap[, $fFreeBmp = True])
; Parameters ....: $sFileName - Full path and extension of the bitmap file to be saved
;   $hBitmap    - HBITMAP handle
;   $fFreeBmp   - If True, hBitmap will be freed on a successful save
; Return values .: Success  - True
;   Failure     - False
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: This function saves a bitmap to file, converting it to the image format specified by the file name extension.
;   For Windows XP, the valid extensions are BMP, GIF, JPEG, PNG and TIF.
;+
;   Requires GDI+: GDI+ requires a redistributable for applications that
;   run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
; Related .......: ScreenCapture_Capture
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_SaveImage($this, $sFileName, $hBitmap, $fFreeBmp = True)
    Local $hClone, $sCLSID, $tData, $sExt, $hImage, $pParams, $tParams, $iResult, $iX, $iY

    _GDIPlus_Startup()

    If @error Then Return SetError(-1, -1, False)

    $sExt = StringUpper(__GDIPlus_ExtractFileExt($sFileName))
    $sCLSID = _GDIPlus_EncodersGetCLSID($sExt)
    If $sCLSID = "" Then Return SetError(-2, -2, False)
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    If @error Then Return SetError(-3, -3, False)

    Switch $sExt
        Case "BMP"
            $iX = _GDIPlus_ImageGetWidth($hImage)
            $iY = _GDIPlus_ImageGetHeight($hImage)
            $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY, $this.giBMPFormat)
            _GDIPlus_ImageDispose($hImage)
            $hImage = $hClone
        Case "JPG", "JPEG"
            $tParams = _GDIPlus_ParamInit(1)
            $tData = DllStructCreate("int Quality")
            DllStructSetData($tData, "Quality", $this.giJPGQuality)
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tData))
        Case "TIF", "TIFF"
            $tParams = _GDIPlus_ParamInit(2)
            $tData = DllStructCreate("int ColorDepth;int Compression")
            DllStructSetData($tData, "ColorDepth", $this.giTIFColorDepth)
            DllStructSetData($tData, "Compression", $this.giTIFCompression)
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOLORDEPTH, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "ColorDepth"))
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOMPRESSION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Compression"))
    EndSwitch

    If IsDllStruct($tParams) Then $pParams = DllStructGetPtr($tParams)

    $iResult = _GDIPlus_ImageSaveToFileEx($hImage, $sFileName, $sCLSID, $pParams)

    _GDIPlus_ImageDispose($hImage)

    If $fFreeBmp Then _WinAPI_DeleteObject($hBitmap)

    _GDIPlus_Shutdown()

    Return SetError($iResult = False, 0, $iResult = True)
EndFunc ;==>ScreenCapture_SaveImage

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetBMPFormat
; Description ...: Sets the bit format that will be used for BMP screen captures
; Syntax.........: ScreenCapture_SetBMPFormat($iFormat)
; Parameters ....: $iFormat     - Image bits per pixel (bpp) setting:
;   |0 = 16 bpp; 5 bits for each RGB component
;   |1 = 16 bpp; 5 bits for red, 6 bits for green and 5 bits blue
;   |2 = 24 bpp; 8 bits for each RGB component
;   |3 = 32 bpp; 8 bits for each RGB component. No alpha component.
;   |4 = 32 bpp; 8 bits for each RGB and alpha component
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, BMP screen captures default to 24 bpp
; Related .......:
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func ScreenCapture_SetBMPFormat($this, $iFormat)
    Switch $iFormat
        Case 0
            $this.giBMPFormat = $GDIP_PXF16RGB555
        Case 1
            $this.giBMPFormat = $GDIP_PXF16RGB565
        Case 2
            $this.giBMPFormat = $GDIP_PXF24RGB
        Case 3
            $this.giBMPFormat = $GDIP_PXF32RGB
        Case 4
            $this.giBMPFormat = $GDIP_PXF32ARGB
        Case Else
            $this.giBMPFormat = $GDIP_PXF24RGB
    EndSwitch

    Return $this
EndFunc ;==>ScreenCapture_SetBMPFormat

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetJPGQuality
; Description ...: Sets the quality level that will be used for JPEG screen captures
; Syntax.........: ScreenCapture_SetJPGQuality($iQuality)
; Parameters ....: $iQuality    - The quality level of the image. Must be in the range of 0 to 100.
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, JPEG screen captures default to a quality level of 100
; Related .......:
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetJPGQuality($this, $iQuality)
    If $iQuality < 0 Then $iQuality = 0
    If $iQuality > 100 Then $iQuality = 100
    $this.giJPGQuality = $iQuality

    Return $this
EndFunc ;==>ScreenCapture_SetJPGQuality

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetTIFColorDepth
; Description ...: Sets the color depth used for TIFF screen captures
; Syntax.........: ScreenCapture_SetTIFColorDepth($iDepth)
; Parameters ....: $iDepth  - Image color depth:
;   | 0 - Default encoder color depth
;   |24 - 24 bit
;   |32 - 32 bit
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, TIFF screen captures default to 24 bits
; Related .......: ScreenCapture_SetTIFCompression
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetTIFColorDepth($this, $iDepth)
    Switch $iDepth
        Case 24
            $this.giTIFColorDepth = 24
        Case 32
            $this.giTIFColorDepth = 32
        Case Else
            $this.giTIFColorDepth = 0
    EndSwitch

    Return $this
EndFunc ;==>ScreenCapture_SetTIFColorDepth

; #FUNCTION# ====================================================================================================================
; Name...........: ScreenCapture_SetTIFCompression
; Description ...: Sets the compression used for TIFF screen captures
; Syntax.........: ScreenCapture_SetTIFCompression($iCompress)
; Parameters ....: $iCompress - Image compression type:
;   |0 - Default encoder compression
;   |1 - No compression
;   |2 - LZW compression
; Return values .:
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; Remarks .......: If not explicitly set, TIF screen captures default to LZW compression
; Related .......: ScreenCapture_SetTIFColorDepth
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func ScreenCapture_SetTIFCompression($this, $iCompress)
    Switch $iCompress
        Case 1
            $this.giTIFCompression = $GDIP_EVTCOMPRESSIONNONE
        Case 2
            $this.giTIFCompression = $GDIP_EVTCOMPRESSIONLZW
        Case Else
            $this.giTIFCompression = 0
    EndSwitch

    Return $this
EndFunc ;==>ScreenCapture_SetTIFCompression
#endregion ScreenCapture Object

And then put the following code into your main program:

#include "BMPinBMP Object.au3"

_AutoItObject_Startup()

Global $BMPinBMP = BMPinBMP()

Global $result = $BMPinBMP.FindBMP("image1.bmp", "image2.bmp", 1) ; substitute your own images here

If IsArray($result) Then
 Global $resultArr[8] = ["Possible Match ", "Matched Lines ", "Found at left ", "Found at top ", "2nd BMP Width ", "2nd BMP Height ", "Highest Matching Lines ", "Best match line "]

 For $i = 0 To UBound($result) - 1
 ConsoleWrite($resultArr[$i] & $result[$i] & @CRLF)
 Next
EndIf

$BMPinBMP = 0

_AutoItObject_Shutdown()
Edited by jaberwocky6669
Link to comment
Share on other sites

Did you try bitmaps that have the first line complete same color ?

No, that's a prerequisite? What I did is to take a bitmap picture, crop out a section of it, save that into a new bitmap. I then tried to find the cropped section in the bigger bitmap. That works fine for that one and only bitmap. So I guess it's possible that my original bmp and the cropped bmp both have the same color at the top?

edit* Ah so yes, that is a prerequisite! Sheesh, that seems kinda unusual.

Edited by jaberwocky6669
Link to comment
Share on other sites

I tried to use this for a Patternsearchengine but then wrote my own as a spin-off from it since i had alot of trouble with selections that had their first lines beeing singlecolor. Thats some time ago, i check if i can dig something up from my old Harddrive.

Edited by Fainth
Link to comment
Share on other sites

I tried to use this for a Patternsearchengine but then wrote my own as a spin-off from it since i had alot of trouble with selections that had their first lines beeing singlecolor. Thats some time ago, i check if i can dig something up from my old Harddrive.

Cool, that'd be awesome.

Link to comment
Share on other sites

When I tested it an array wasn't returned to $result. I just got $result = 1.

I believe that can mean one of two things:

1) The image wasn't found

2) The top line of both images weren't the same

Number 2 is the most likely culprit and seems like a bug in the program. I am waiting on fainth to see if he can dig up some of his old scripts.

Link to comment
Share on other sites

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 areas

issues are frequently in

- not having GDIPLUS in the right location (or not installed at all)

Link to comment
Share on other sites

This has a function that finds a BMP within another BMP. Use it like this:

$result = _FindBMP($imageToSearch, $imageToFind)

$result[1] will hold True if found, false otherwise.

If found, then $result[3] will hold the x-coordinate and $result[4] will hold the y-coordinate of the location where the image was found (I think).

It doesn't work for me. Can anyone get it to work?

This file is based off of http://www.autoitscript.com/forum/index.php?showtopic=66545

The returned values are

$bMatchPossible = Could a match be possible

$matchedLines = The number of matched lines (if its 1 previous returnvalue probably better to set it at False

$foundAtLeft

$foundAtTop

$bmp2width

$BMP2Height

$HighestMatchingLines

$bestMatchLine

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...