Pixelsearch a specific area of a (possibly background) window using the gdip library Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Balimia
Posts: 1
Joined: 24 Sep 2016, 16:35

Pixelsearch a specific area of a (possibly background) window using the gdip library

Post by Balimia » 24 Sep 2016, 17:18

I am currently trying to make a function for my script that would find and return the (X,Y) coordinates of a specified color within a delimited area of a window that is either visible on screen or in the background covered by other windows.

Using the gdip library and with the help of one of tic's examples, the following code will print and display an area of a window. The area of the window is delimited with four parameters; x,y,w,h, which are respectively the top-left x, top-left y, width of the area and height of the area :

Code: Select all

#Include Gdip_All.ahk

global ScrBoxOn := 0
global win_title:="Untitled - Notepad"

Fn_ScreenCapture(0,0,1500,1000)

Fn_ScreenCapture(x,y,w,h)
{
If !pToken := Gdip_Startup()
{
	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
	ExitApp
}
ScrBoxOn := !ScrBoxOn
Gui, ScrBox:  +E0x80000 +LastFound +AlwaysOnTop ;+ToolWindow +OwnDialogs -Caption
Gui, ScrBox: Show, NA

hwnd1 := WinExist()
pBitmap := Gdip_BitmapFromHWND(WinExist(win_title)) 

If !pBitmap
{
	MsgBox, 4096, File loading error!, Could not load the image specified
	ExitApp
}

Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap)
hbm := CreateDIBSection(Width, Height)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap,x,y,w,h,x,y,w,h)
UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth -Width)/2, (A_ScreenHeight-Height)/2, Width, Height)
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_DisposeImage(pBitmap)
ToolTip, Press Esc to close.
Return
}

#If  ScrBoxOn = 1
	Esc::
	Gdip_Shutdown(pToken)
	Gui, ScrBox:Destroy
	ToolTip
	ExitApp
#If
I'm not quite sure how I could go on about making a function that would find a specific color within an area defined by a function similar to Fn_ScreenCapture. The source bitmap of the area wouldn't have to be printed out, just saved until the pixelsearch is done finding the color.

I would greatly appreciate any help or advice, I tried looking for similar problems on the forums and on google, but none of them match my problem. Also, I'm pretty new to Ahk, so any extensive explanation is most welcome.

User avatar
noname
Posts: 515
Joined: 19 Nov 2013, 09:15

Re: Pixelsearch a specific area of a (possibly background) window using the gdip library  Topic is solved

Post by noname » 25 Sep 2016, 02:15

Here is an example maybe you can use parts of the code.The search with gdip works for background window (but the standard mousemove only if it is visible and active).

It creates a demo window with one pixel 0x28F028 to look for.

Code: Select all

#include *i gdip_all.ahk

If !pToken := Gdip_Startup()
{
	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
	ExitApp
}

;---------------- create demo gui ---------------- 
hbitmap:=Create_bgrd_png()


Gui, add,text,+0xE w200 h200 hwndimage_hwnd       ; +0xE is SS_BITMAP
Gui, show,,demo

SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap,, ahk_id %image_hwnd%
win_title:="demo"
;---------------- end create demo gui ---------------- 
sleep 2000

pBitmap := Gdip_BitmapFromHWND(WinExist(win_title))

; if needed get area of bitmap for search
x:=20 , y:=20 ,w:=100 ,h:=100

area_bitmap:=Gdip_CloneBitmapArea(pBitmap, x, y, w, h)

;color to search for
argb:=0xff28f028  

Gdip_PixelSearch(area_bitmap,argb, posx, posy)

MouseMove, x+posx,y+posy

msgbox % x+posx "`n" y+posy 

; if needed cleanup
Gdip_DisposeImage(pBitmap)
Gdip_DisposeImage(area_bitmap)
Gdip_Shutdown(pToken)

exitapp


Gdip_PixelSearch(pBitmap, ARGB, ByRef x, ByRef y)
{
	static _PixelSearch
	if !_PixelSearch
	{
		MCode_PixelSearch := "8B44241099535583E2035603C233F6C1F80239742418577E388B7C24148B6C24248B5424188D1C85000000008D64240033C085"
		. "D27E108BCF3929743183C00183C1043BC27CF283C60103FB3B74241C7CDF8B4424288B4C242C5F5EC700FFFFFFFF5DC701FFFFFFFF83C8FF5BC38B4C2"
		. "4288B54242C5F890189325E5D33C05BC3"

		VarSetCapacity(_PixelSearch, StrLen(MCode_PixelSearch)//2)
		Loop % StrLen(MCode_PixelSearch)//2      ;%
			NumPut("0x" SubStr(MCode_PixelSearch, (2*A_Index)-1, 2), _PixelSearch, A_Index-1, "char")
	}
	Gdip_GetImageDimensions(pBitmap, Width, Height)
	if !(Width && Height)
		return -1

	if (E1 := Gdip_LockBits(pBitmap, 0, 0, Width, Height, Stride1, Scan01, BitmapData1))
		return -2

	x := y := 0
	E := DllCall(&_PixelSearch, "uint", Scan01, "int", Width, "int", Height, "int", Stride1, "uint", ARGB, "int*", x, "int*", y)
	Gdip_UnlockBits(pBitmap, BitmapData1)
	return (E = "") ? -3 : E
}

;---------------- ---------------- ---------------- ---------------- ---------------- 
; only for creating demo gui image

; ##################################################################################
; # This #Include file was generated by Image2Include.ahk, you must not change it! #
; ##################################################################################
Create_bgrd_png(NewHandle := False) {
Static hBitmap := 0
If (NewHandle)
   hBitmap := 0
If (hBitmap)
   Return hBitmap
VarSetCapacity(B64, 396 << !!A_IsUnicode)
B64 := "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAIAAAAiOjnJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AkZBiEH7Oc3tAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAAAn0lEQVR42u3QQQ0AIAwEMELOxBzMvzIk8J4FaCV0LQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC+kEoqHh62FQAAAAAAAAAAAAAAwNSnJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMB0AUZwAYVNlk1sAAAAAElFTkSuQmCC"
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", 0, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
   Return False
VarSetCapacity(Dec, DecLen, 0)
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", &Dec, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
   Return False
; Bitmap creation adopted from "How to convert Image data (JPEG/PNG/GIF) to hBITMAP?" by SKAN
; -> http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257
hData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr")
pData := DllCall("Kernel32.dll\GlobalLock", "Ptr", hData, "UPtr")
DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen)
DllCall("Kernel32.dll\GlobalUnlock", "Ptr", hData)
DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream)
hGdip := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")
VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar")
DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0)
DllCall("Gdiplus.dll\GdipCreateBitmapFromStream",  "Ptr", pStream, "PtrP", pBitmap)
DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0)
DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", pToken)
DllCall("Kernel32.dll\FreeLibrary", "Ptr", hGdip)
DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream)
Return hBitmap
}

phoenixL337
Posts: 12
Joined: 17 Oct 2021, 04:30

Re: Pixelsearch a specific area of a (possibly background) window using the gdip library

Post by phoenixL337 » 18 Oct 2021, 10:50

noname wrote:
25 Sep 2016, 02:15
Here is an example maybe you can use parts of the code.The search with gdip works for background window (but the standard mousemove only if it is visible and active).

It creates a demo window with one pixel 0x28F028 to look for.

Code: Select all

#include *i gdip_all.ahk

If !pToken := Gdip_Startup()
{
	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
	ExitApp
}

;---------------- create demo gui ---------------- 
hbitmap:=Create_bgrd_png()


Gui, add,text,+0xE w200 h200 hwndimage_hwnd       ; +0xE is SS_BITMAP
Gui, show,,demo

SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap,, ahk_id %image_hwnd%
win_title:="demo"
;---------------- end create demo gui ---------------- 
sleep 2000

pBitmap := Gdip_BitmapFromHWND(WinExist(win_title))

; if needed get area of bitmap for search
x:=20 , y:=20 ,w:=100 ,h:=100

area_bitmap:=Gdip_CloneBitmapArea(pBitmap, x, y, w, h)

;color to search for
argb:=0xff28f028  

Gdip_PixelSearch(area_bitmap,argb, posx, posy)

MouseMove, x+posx,y+posy

msgbox % x+posx "`n" y+posy 

; if needed cleanup
Gdip_DisposeImage(pBitmap)
Gdip_DisposeImage(area_bitmap)
Gdip_Shutdown(pToken)

exitapp


Gdip_PixelSearch(pBitmap, ARGB, ByRef x, ByRef y)
{
	static _PixelSearch
	if !_PixelSearch
	{
		MCode_PixelSearch := "8B44241099535583E2035603C233F6C1F80239742418577E388B7C24148B6C24248B5424188D1C85000000008D64240033C085"
		. "D27E108BCF3929743183C00183C1043BC27CF283C60103FB3B74241C7CDF8B4424288B4C242C5F5EC700FFFFFFFF5DC701FFFFFFFF83C8FF5BC38B4C2"
		. "4288B54242C5F890189325E5D33C05BC3"

		VarSetCapacity(_PixelSearch, StrLen(MCode_PixelSearch)//2)
		Loop % StrLen(MCode_PixelSearch)//2      ;%
			NumPut("0x" SubStr(MCode_PixelSearch, (2*A_Index)-1, 2), _PixelSearch, A_Index-1, "char")
	}
	Gdip_GetImageDimensions(pBitmap, Width, Height)
	if !(Width && Height)
		return -1

	if (E1 := Gdip_LockBits(pBitmap, 0, 0, Width, Height, Stride1, Scan01, BitmapData1))
		return -2

	x := y := 0
	E := DllCall(&_PixelSearch, "uint", Scan01, "int", Width, "int", Height, "int", Stride1, "uint", ARGB, "int*", x, "int*", y)
	Gdip_UnlockBits(pBitmap, BitmapData1)
	return (E = "") ? -3 : E
}

;---------------- ---------------- ---------------- ---------------- ---------------- 
; only for creating demo gui image

; ##################################################################################
; # This #Include file was generated by Image2Include.ahk, you must not change it! #
; ##################################################################################
Create_bgrd_png(NewHandle := False) {
Static hBitmap := 0
If (NewHandle)
   hBitmap := 0
If (hBitmap)
   Return hBitmap
VarSetCapacity(B64, 396 << !!A_IsUnicode)
B64 := "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAIAAAAiOjnJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AkZBiEH7Oc3tAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAAAn0lEQVR42u3QQQ0AIAwEMELOxBzMvzIk8J4FaCV0LQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC+kEoqHh62FQAAAAAAAAAAAAAAwNSnJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMB0AUZwAYVNlk1sAAAAAElFTkSuQmCC"
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", 0, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
   Return False
VarSetCapacity(Dec, DecLen, 0)
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", &Dec, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
   Return False
; Bitmap creation adopted from "How to convert Image data (JPEG/PNG/GIF) to hBITMAP?" by SKAN
; -> http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257
hData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr")
pData := DllCall("Kernel32.dll\GlobalLock", "Ptr", hData, "UPtr")
DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen)
DllCall("Kernel32.dll\GlobalUnlock", "Ptr", hData)
DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream)
hGdip := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")
VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar")
DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0)
DllCall("Gdiplus.dll\GdipCreateBitmapFromStream",  "Ptr", pStream, "PtrP", pBitmap)
DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0)
DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", pToken)
DllCall("Kernel32.dll\FreeLibrary", "Ptr", hGdip)
DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream)
Return hBitmap
}
how do i specify which window to search and how do i know if it found the pixel or not
Thanks for help

User avatar
ibieel
Posts: 216
Joined: 17 Oct 2021, 23:30

Re: Pixelsearch a specific area of a (possibly background) window using the gdip library

Post by ibieel » 19 Oct 2021, 02:12

noname wrote:
25 Sep 2016, 02:15
Here is an example maybe you can use parts of the code.The search with gdip works for background window (but the standard mousemove only if it is visible and active).

It creates a demo window with one pixel 0x28F028 to look for.

Code: Select all

#include *i gdip_all.ahk

If !pToken := Gdip_Startup()
{
	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
	ExitApp
}

;---------------- create demo gui ---------------- 
hbitmap:=Create_bgrd_png()


Gui, add,text,+0xE w200 h200 hwndimage_hwnd       ; +0xE is SS_BITMAP
Gui, show,,demo

SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap,, ahk_id %image_hwnd%
win_title:="demo"
;---------------- end create demo gui ---------------- 
sleep 2000

pBitmap := Gdip_BitmapFromHWND(WinExist(win_title))

; if needed get area of bitmap for search
x:=20 , y:=20 ,w:=100 ,h:=100

area_bitmap:=Gdip_CloneBitmapArea(pBitmap, x, y, w, h)

;color to search for
argb:=0xff28f028  

Gdip_PixelSearch(area_bitmap,argb, posx, posy)

MouseMove, x+posx,y+posy

msgbox % x+posx "`n" y+posy 

; if needed cleanup
Gdip_DisposeImage(pBitmap)
Gdip_DisposeImage(area_bitmap)
Gdip_Shutdown(pToken)

exitapp


Gdip_PixelSearch(pBitmap, ARGB, ByRef x, ByRef y)
{
	static _PixelSearch
	if !_PixelSearch
	{
		MCode_PixelSearch := "8B44241099535583E2035603C233F6C1F80239742418577E388B7C24148B6C24248B5424188D1C85000000008D64240033C085"
		. "D27E108BCF3929743183C00183C1043BC27CF283C60103FB3B74241C7CDF8B4424288B4C242C5F5EC700FFFFFFFF5DC701FFFFFFFF83C8FF5BC38B4C2"
		. "4288B54242C5F890189325E5D33C05BC3"

		VarSetCapacity(_PixelSearch, StrLen(MCode_PixelSearch)//2)
		Loop % StrLen(MCode_PixelSearch)//2      ;%
			NumPut("0x" SubStr(MCode_PixelSearch, (2*A_Index)-1, 2), _PixelSearch, A_Index-1, "char")
	}
	Gdip_GetImageDimensions(pBitmap, Width, Height)
	if !(Width && Height)
		return -1

	if (E1 := Gdip_LockBits(pBitmap, 0, 0, Width, Height, Stride1, Scan01, BitmapData1))
		return -2

	x := y := 0
	E := DllCall(&_PixelSearch, "uint", Scan01, "int", Width, "int", Height, "int", Stride1, "uint", ARGB, "int*", x, "int*", y)
	Gdip_UnlockBits(pBitmap, BitmapData1)
	return (E = "") ? -3 : E
}

;---------------- ---------------- ---------------- ---------------- ---------------- 
; only for creating demo gui image

; ##################################################################################
; # This #Include file was generated by Image2Include.ahk, you must not change it! #
; ##################################################################################
Create_bgrd_png(NewHandle := False) {
Static hBitmap := 0
If (NewHandle)
   hBitmap := 0
If (hBitmap)
   Return hBitmap
VarSetCapacity(B64, 396 << !!A_IsUnicode)
B64 := "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAIAAAAiOjnJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AkZBiEH7Oc3tAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAAAn0lEQVR42u3QQQ0AIAwEMELOxBzMvzIk8J4FaCV0LQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC+kEoqHh62FQAAAAAAAAAAAAAAwNSnJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMB0AUZwAYVNlk1sAAAAAElFTkSuQmCC"
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", 0, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
   Return False
VarSetCapacity(Dec, DecLen, 0)
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", &Dec, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
   Return False
; Bitmap creation adopted from "How to convert Image data (JPEG/PNG/GIF) to hBITMAP?" by SKAN
; -> http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257
hData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr")
pData := DllCall("Kernel32.dll\GlobalLock", "Ptr", hData, "UPtr")
DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen)
DllCall("Kernel32.dll\GlobalUnlock", "Ptr", hData)
DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream)
hGdip := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")
VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar")
DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0)
DllCall("Gdiplus.dll\GdipCreateBitmapFromStream",  "Ptr", pStream, "PtrP", pBitmap)
DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0)
DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", pToken)
DllCall("Kernel32.dll\FreeLibrary", "Ptr", hGdip)
DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream)
Return hBitmap
}

this script not working for me :(
not found pixel
posx = 0
posy = 0

can you help me please?

Post Reply

Return to “Ask for Help (v1)”