. Let me know if you can help me, please.
My main source is complex, and I tried to summarize the maximum so that you could understand. All main code is inside a thread body.
I have the following situation below, where one of the parameters is not returning correctly. This parameter must return 2 values, example: 100,300.
result is not being displayed. I've tried it as a string and inside the quotes. Do you know if need to change the function?
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
}
;#####################################################################################
; Function Gdip_GetImageDimensions
; Description Gives the width and height of a bitmap
;
; pBitmap Pointer to a bitmap
; Width ByRef variable. This variable will be set to the width of the bitmap
; Height ByRef variable. This variable will be set to the height of the bitmap
;
; return GDI+ status enumeration return value
Gdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height) {
If StrLen(pBitmap)<3
Return -1
Width := 0, Height := 0
E := Gdip_GetImageDimension(pBitmap, Width, Height)
Width := Round(Width)
Height := Round(Height)
return E
}
Gdip_CloneBitmapArea(pBitmap, x:="", y:="", w:=0, h:=0, PixelFormat:=0, KeepPixelFormat:=0) {
; The new pBitmap is by default in the 32-ARGB PixelFormat.
;
; If the specified coordinates exceed the boundaries of pBitmap
; the resulted pBitmap is erroneuous / defective.
pBitmapDest := 0
If !PixelFormat
PixelFormat := 0x26200A ; 32-ARGB
If (KeepPixelFormat=1)
PixelFormat := Gdip_GetImagePixelFormat(pBitmap, 1)
If (y="")
y := 0
If (x="")
x := 0
If (!w && !h)
Gdip_GetImageDimensions(pBitmap, w, h)
E := DllCall("gdiplus\GdipCloneBitmapArea"
, "float", x, "float", y
, "float", w, "float", h
, "int", PixelFormat
, "UPtr", pBitmap
, "UPtr*", pBitmapDest)
return pBitmapDest
}
;#####################################################################################
; BitmapLockBits
;#####################################################################################
Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode := 3, PixelFormat := 0x26200a) {
Static Ptr := "UPtr"
CreateRect(_Rect, x, y, w, h)
VarSetCapacity(BitmapData, 16+2*A_PtrSize, 0)
_E := DllCall("Gdiplus\GdipBitmapLockBits", Ptr, pBitmap, Ptr, &_Rect, "uint", LockMode, "int", PixelFormat, Ptr, &BitmapData)
Stride := NumGet(BitmapData, 8, "Int")
Scan0 := NumGet(BitmapData, 16, Ptr)
return _E
}
Gdip_DisposeImage(pBitmap, noErr:=0) {
; modified by Marius ?ucan to help avoid crashes
; by disposing a non-existent pBitmap
If (StrLen(pBitmap)<=2 && noErr=1)
Return 0
r := DllCall("gdiplus\GdipDisposeImage", "UPtr", pBitmap)
If (r=2 || r=1) && (noErr=1)
r := 0
Return r
}
Gdip_GetImageDimension(pBitmap, ByRef w, ByRef h) {
Static Ptr := "UPtr"
return DllCall("gdiplus\GdipGetImageDimension", Ptr, pBitmap, "float*", w, "float*", h)
}
Gdip_GetImagePixelFormat(pBitmap, mode:=0) {
; Mode options
; 0 - in decimal
; 1 - in hex
; 2 - in human readable format
;
; PXF01INDEXED = 0x00030101 ; 1 bpp, indexed
; PXF04INDEXED = 0x00030402 ; 4 bpp, indexed
; PXF08INDEXED = 0x00030803 ; 8 bpp, indexed
; PXF16GRAYSCALE = 0x00101004; 16 bpp, grayscale
; PXF16RGB555 = 0x00021005 ; 16 bpp; 5 bits for each RGB
; PXF16RGB565 = 0x00021006 ; 16 bpp; 5 bits red, 6 bits green, and 5 bits blue
; PXF16ARGB1555 = 0x00061007 ; 16 bpp; 1 bit for alpha and 5 bits for each RGB component
; PXF24RGB = 0x00021808 ; 24 bpp; 8 bits for each RGB
; PXF32RGB = 0x00022009 ; 32 bpp; 8 bits for each RGB, no alpha.
; PXF32ARGB = 0x0026200A ; 32 bpp; 8 bits for each RGB and alpha
; PXF32PARGB = 0x000E200B ; 32 bpp; 8 bits for each RGB and alpha, pre-mulitiplied
; PXF48RGB = 0x0010300C ; 48 bpp; 16 bits for each RGB
; PXF64ARGB = 0x0034400D ; 64 bpp; 16 bits for each RGB and alpha
; PXF64PARGB = 0x001A400E ; 64 bpp; 16 bits for each RGB and alpha, pre-multiplied
; INDEXED [1-bits, 4-bits and 8-bits] pixel formats rely on color palettes.
; The color information for the pixels is stored in palettes.
; Indexed images always contain a palette - a special table of colors.
; Each pixel is an index in this table. Usually a palette contains 256
; or less entries. That's why the maximum depth of an indexed pixel is 8 bpp.
; Using palettes is a common practice when working with small color depths.
; modified by Marius ?ucan
Static PixelFormatsList := {0x30101:"1-INDEXED", 0x30402:"4-INDEXED", 0x30803:"8-INDEXED", 0x101004:"16-GRAYSCALE", 0x021005:"16-RGB555", 0x21006:"16-RGB565", 0x61007:"16-ARGB1555", 0x21808:"24-RGB", 0x22009:"32-RGB", 0x26200A:"32-ARGB", 0xE200B:"32-PARGB", 0x10300C:"48-RGB", 0x34400D:"64-ARGB", 0x1A400E:"64-PARGB"}
PixelFormat := 0
E := DllCall("gdiplus\GdipGetImagePixelFormat", "UPtr", pBitmap, "UPtr*", PixelFormat)
If E
Return -1
If (mode=0)
Return PixelFormat
inHEX := Format("{1:#x}", PixelFormat)
If (PixelFormatsList.Haskey(inHEX) && mode=2)
result := PixelFormatsList[inHEX]
Else
result := inHEX
return result
}
;#####################################################################################
; Function CreateRectF
; Description Creates a RectF object, containing a the coordinates and dimensions of a rectangle
;
; RectF Name to call the RectF object
; x, y x, y coordinates of the upper left corner of the rectangle
; w, h Width and height of the rectangle
;
; return No return value
CreateRectF(ByRef RectF, x, y, w, h) {
VarSetCapacity(RectF, 16)
NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float")
NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}