Code: Select all
;**********************************************************************************
;
; Gdip_ImageSearch()
; by MasterFocus - 02/APRIL/2013 00:30h BRT
; Thanks to guest3456 for helping me ponder some ideas
; Requires GDIP, Gdip_SetBitmapTransColor() and Gdip_MultiLockedBitsSearch()
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -> http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the "Share Alike" condition of the license EXCLUSIVELY
; for these users: tic , Rseding91 , guest3456
;
;==================================================================================
;
; This function searches for pBitmapNeedle within pBitmapHaystack
; The returned value is the number of instances found (negative = error)
;
; ++ PARAMETERS ++
;
; pBitmapHaystack and pBitmapNeedle
; Self-explanatory bitmap pointers, are the only required parameters
;
; OutputList
; ByRef variable to store the list of coordinates where a match was found
;
; OuterX1, OuterY1, OuterX2, OuterY2
; Equivalent to ImageSearch's X1,Y1,X2,Y2
; Default: 0 for all (which searches the whole haystack area)
;
; Variation
; Just like ImageSearch, a value from 0 to 255
; Default: 0
;
; Trans
; Needle RGB transparent color, should be a numerical value from 0 to 0xFFFFFF
; Default: blank (does not use transparency)
;
; SearchDirection
; Haystack search direction
; Vertical preference:
; 1 = top->left->right->bottom [default]
; 2 = bottom->left->right->top
; 3 = bottom->right->left->top
; 4 = top->right->left->bottom
; Horizontal preference:
; 5 = left->top->bottom->right
; 6 = left->bottom->top->right
; 7 = right->bottom->top->left
; 8 = right->top->bottom->left
;
; Instances
; Maximum number of instances to find when searching (0 = find all)
; Default: 1 (stops after one match is found)
;
; LineDelim and CoordDelim
; Outer and inner delimiters for the list of coordinates (OutputList)
; Defaults: "`n" and ","
;
; ++ RETURN VALUES ++
;
; -1001 ==> invalid haystack and/or needle bitmap pointer
; -1002 ==> invalid variation value
; -1003 ==> X1 and Y1 cannot be negative
; -1004 ==> unable to lock haystack bitmap bits
; -1005 ==> unable to lock needle bitmap bits
; any non-negative value ==> the number of instances found
;
;==================================================================================
;
;**********************************************************************************
Gdip_ImageSearch(pBitmapHaystack,pBitmapNeedle,ByRef OutputList=""
,OuterX1=0,OuterY1=0,OuterX2=0,OuterY2=0,Variation=0,Trans=""
,SearchDirection=1,Instances=1,LineDelim="`n",CoordDelim=",") {
; Some validations that can be done before proceeding any further
If !( pBitmapHaystack && pBitmapNeedle )
Return -1001
If Variation not between 0 and 255
return -1002
If ( ( OuterX1 < 0 ) || ( OuterY1 < 0 ) )
return -1003
If SearchDirection not between 1 and 8
SearchDirection := 1
If ( Instances < 0 )
Instances := 0
; Getting the dimensions and locking the bits [haystack]
Gdip_GetImageDimensions(pBitmapHaystack,hWidth,hHeight)
; Last parameter being 1 says the LockMode flag is "READ only"
If Gdip_LockBits(pBitmapHaystack,0,0,hWidth,hHeight,hStride,hScan,hBitmapData,1)
OR !(hWidth := NumGet(hBitmapData,0,"UInt"))
OR !(hHeight := NumGet(hBitmapData,4,"UInt"))
Return -1004
; Careful! From this point on, we must do the following before returning:
; - unlock haystack bits
; Getting the dimensions and locking the bits [needle]
Gdip_GetImageDimensions(pBitmapNeedle,nWidth,nHeight)
; If Trans is correctly specified, create a backup of the original needle bitmap
; and modify the current one, setting the desired color as transparent.
; Also, since a copy is created, we must remember to dispose the new bitmap later.
; This whole thing has to be done before locking the bits.
If Trans between 0 and 0xFFFFFF
{
pOriginalBmpNeedle := pBitmapNeedle
pBitmapNeedle := Gdip_CloneBitmapArea(pOriginalBmpNeedle,0,0,nWidth,nHeight)
Gdip_SetBitmapTransColor(pBitmapNeedle,Trans)
DumpCurrentNeedle := true
}
; Careful! From this point on, we must do the following before returning:
; - unlock haystack bits
; - dispose current needle bitmap (if necessary)
If Gdip_LockBits(pBitmapNeedle,0,0,nWidth,nHeight,nStride,nScan,nBitmapData)
OR !(nWidth := NumGet(nBitmapData,0,"UInt"))
OR !(nHeight := NumGet(nBitmapData,4,"UInt"))
{
If ( DumpCurrentNeedle )
Gdip_DisposeImage(pBitmapNeedle)
Gdip_UnlockBits(pBitmapHaystack,hBitmapData)
Return -1005
}
; Careful! From this point on, we must do the following before returning:
; - unlock haystack bits
; - unlock needle bits
; - dispose current needle bitmap (if necessary)
; Adjust the search box. "OuterX2,OuterY2" will be the last pixel evaluated
; as possibly matching with the needle's first pixel. So, we must avoid going
; beyond this maximum final coordinate.
OuterX2 := ( !OuterX2 ? hWidth-nWidth+1 : OuterX2-nWidth+1 )
OuterY2 := ( !OuterY2 ? hHeight-nHeight+1 : OuterY2-nHeight+1 )
OutputCount := Gdip_MultiLockedBitsSearch(hStride,hScan,hWidth,hHeight
,nStride,nScan,nWidth,nHeight,OutputList,OuterX1,OuterY1,OuterX2,OuterY2
,Variation,SearchDirection,Instances,LineDelim,CoordDelim)
Gdip_UnlockBits(pBitmapHaystack,hBitmapData)
Gdip_UnlockBits(pBitmapNeedle,nBitmapData)
If ( DumpCurrentNeedle )
Gdip_DisposeImage(pBitmapNeedle)
Return OutputCount
}
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////