1 (изменено: Vicoriyan, 2017-10-23 19:40:56)

Тема: AHK: ImageSearch без файла картинки

Может кто-то подумает, что ерундой страдаю, но вот мне интересно, можно ли осуществить такой алгоритм.

Скрипт делает скрин, сохраняет в виде картинки, выполняет действия и ждет, когда эта картинки исчезнет.

hwnd := WinExist("А")
SetBatchLines, -1
CoordMode, Pixel, Window
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromHWND(hwnd)
Gdip_GetDimensions(pBitmap, w, h)
pBitmap2 := Gdip_CropImage(pBitmap, 50, 110, 25, 30)
Gdip_SaveBitmapToFile(pBitmap2, "outScreen.png")
Sleep, 1000
CoordMode, Mouse, Window
ControlClick, x105 y305, ahk_class Qt5QWindowIcon,, Left, 1,  NA
Sleep, 1000
Loop
{
   ImageSearch, FoundX, FoundY, 0, 0, A_ScreenWidth, A_ScreenHeight, *15 outScreen.png
   If ErrorLevel
   {
      MsgBox картинка исчезла
      Break
   }
}
Gdip_CropImage(pBitmap, x, y, w, h)
{
   pBitmap2 := Gdip_CreateBitmap(w, h), G2 := Gdip_GraphicsFromImage(pBitmap2)
   Gdip_DrawImage(G2, pBitmap, 0, 0, w, h, x, y, w, h)
   Gdip_DeleteGraphics(G2)
   return pBitmap2
}
Gdip_DisposeImage(pBitmap), Gdip_DisposeImage(pBitmap2)
Gdip_Shutdown(pToken)

Может как-то по другому можно реализовать, но и так работает. У меня вопрос в другом, можно ли избавиться от физического сохранения картинки? Ведь скрин сохраняется в памяти и можно ведь как-то использовать это при поиске?
Или для этой цели ImageSearch не подходит?

2

Re: AHK: ImageSearch без файла картинки

ImageSearch не подходит.

3

Re: AHK: ImageSearch без файла картинки

Malcev А как тогда реализовать? Каким способом?

4 (изменено: Malcev, 2017-10-23 21:22:40)

Re: AHK: ImageSearch без файла картинки

Мы же с вами эту тему вдоль и поперек обсудили.
Если вы беретесь за довольно сложные коды с GDI+, то стоит почитать о том как он работает, а не просто спрашивать-копировать-вставлять.
Кстати, протестировал - из всех найденных мною Gdip Imagesearch, этот пока самый быстрый:

SetBatchLines -1
If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}
a:=a_tickcount
loop 20
   ImageSearch, FoundX, FoundY, 0,0, 1920, 1080, find.png
msgbox % a_tickcount - a


a:=a_tickcount
bmpHaystack := Gdip_BitmapFromScreen()
bmpNeedle := Gdip_CreateBitmapFromFile("find.png")
loop 20
   Gdip_ImageSearch(bmpHaystack, bmpNeedle, x, y)
msgbox % a_tickcount - a
Gdip_DisposeImage(bmpHaystack), Gdip_DisposeImage(bmpNeedle)
Gdip_Shutdown(pToken)




Gdip_ImageSearch(pBitmapHayStack, pBitmapNeedle, ByRef x, ByRef y, Variation=0, sx="", sy="", w="", h="")
{
	static _ImageSearch1, _ImageSearch2
	if !_ImageSearch1
	{
		MCode_ImageSearch1 := "83EC108B44242C9983E20303C28BC88B4424309983E20303C253C1F80255894424148B44244056C1F9023B44244C578944244"
		. "80F8DCA0000008B7C24348D148D000000000FAFC88B442444895424148B54242403C88D1C8A8B4C244C895C24183BC1894424407D7A895C24108D6424"
		. "008B6C2428C744243C000000008D6424008B44243C3B4424380F8D9400000033C985FF7E178BD58BF38B063B02752283C10183C20483C6043BCF7CED8"
		. "B44241C035C24148344243C0103C003C003E8EBC08B4424408B5C24108B4C244C83C00183C3043BC189442440895C24107C928B4424448B5424488B5C"
		. "2418035C241483C2013B54245089542448895C24180F8C5DFFFFFF8B5424548B4424585F5EC702FFFFFFFF5DC700FFFFFFFF83C8FF5B83C410C38B4C2"
		. "4548B5424408B4424585F89118B4C24445E5D890833C05B83C410C3"

		VarSetCapacity(_ImageSearch1, StrLen(MCode_ImageSearch1)//2)
		Loop % StrLen(MCode_ImageSearch1)//2		;%
			NumPut("0x" SubStr(MCode_ImageSearch1, (2*A_Index)-1, 2), _ImageSearch1, A_Index-1, "char")
	}

	if !_ImageSearch2
	{
		MCode_ImageSearch2 :="83EC1C8B4424443B44244C535556578944241C0F8D760100008B4C24488B5424580FAFC88B4424608B742440894C24188B4C24"
		. "503BCA894C24140F8D320100008B54241833FF897C24108B5C24103B5C2444897C2428895424240F8D4E01000085F6C7442420000000000F8ECD00000"
		. "08B7424348D148A8B4C243003F7897424548D1C0AEB0A8DA424000000008D49008B6C2454B9030000000FB60C19BE030000000FB6342E8D2C013BF50F"
		. "8FA20000002BC83BF10F8C980000008B4C24300FB64C0A028B7424340FB67437028D2C013BF57F7F2BC83BF17C798B4C24300FB64C0A018B7424340FB"
		. "67437018D2C013BF57F602BC83BF17C5A0FB60B8B7424540FB6368D2C013BF57F492BC83BF17C438B4C24208B742440834424540483C10183C20483C3"
		. "0483C7043BCE894C24200F8C5BFFFFFF8B4C24148B7C24288B542424035424488344241001037C244CE9F7FEFFFF8B4C24148B5424588B74244083C10"
		. "13BCA894C24140F8CD2FEFFFF8B4C24508B7C241C8B5C2448015C241883C7013B7C245C897C241C0F8CA5FEFFFF8B5424648B4424685F5EC702FFFFFF"
		. "FF5DC700FFFFFFFF83C8FF5B83C41CC38B5424648B4424685F890A8B4C24185E5D890833C05B83C41CC3"

		VarSetCapacity(_ImageSearch2, StrLen(MCode_ImageSearch2)//2)
		Loop % StrLen(MCode_ImageSearch2)//2		;%
			NumPut("0x" SubStr(MCode_ImageSearch2, (2*A_Index)-1, 2), _ImageSearch2, A_Index-1, "char")
	}
	
	if (Variation > 255 || Variation < 0)
		return -2

	Gdip_GetImageDimensions(pBitmapHayStack, hWidth, hHeight), Gdip_GetImageDimensions(pBitmapNeedle, nWidth, nHeight)
	
	if !(hWidth && hHeight && nWidth && nHeight)
		return -3
	if (nWidth > hWidth || nHeight > hHeight)
		return -4
	
	sx := (sx = "") ? 0 : sx
	sy := (sy = "") ? 0 : sy
	w := (w = "") ? hWidth-sx : w
	h := (h = "") ? hHeight-sy : h
	
	if (sx+w > hWidth-nWidth)
		w := hWidth-sx-nWidth+1
	
	if (sy+h > hHeight-nHeight)
		h := hHeight-sy-nHeight+1
		
	E1 := Gdip_LockBits(pBitmapHayStack, 0, 0, hWidth, hHeight, Stride1, Scan01, BitmapData1)
	E2 := Gdip_LockBits(pBitmapNeedle, 0, 0, nWidth, nHeight, Stride2, Scan02, BitmapData2)
	if (E1 || E2)
		return -5

	x := y := 0
	if (Variation = 0)
	{
		E := DllCall(&_ImageSearch1, "uint", Scan01, "uint", Scan02, "int", hWidth, "int", hHeight, "int", nWidth, "int", nHeight, "int", Stride1
		, "int", Stride2, "int", sx, "int", sy, "int", w, "int", h, "int*", x, "int*", y)
	}
	else
	{
		E := DllCall(&_ImageSearch2, "uint", Scan01, "uint", Scan02, "int", hWidth, "int", hHeight, "int", nWidth, "int", nHeight, "int", Stride1
		, "int", Stride2, "int", sx, "int", sy, "int", w, "int", h, "int", Variation, "int*", x, "int*", y)
	}
	Gdip_UnlockBits(pBitmapHayStack, BitmapData1), Gdip_UnlockBits(pBitmapNeedle, BitmapData2)
	return E ? E : -6
}

5

Re: AHK: ImageSearch без файла картинки

Malcev Все на английском и сложно понимать. Разбираюсь на примерах, на экспериментах и бывает на методах тыка.

6 (изменено: Malcev, 2017-10-24 00:56:25)

Re: AHK: ImageSearch без файла картинки

Нашел функции, быстрее чем подобная функция от Tic, более чем в полтора раза быстрее, чем ImageSearch.
И в несколько раз быстрее, чем финальная функция автора - (https://github.com/MasterFocus/AutoHotk … mageSearch)
Только для 32 бит.
https://github.com/MasterFocus/AutoHotk … mageSearch

SetBatchLines -1
pToken := Gdip_Startup()

pBitmapHayStack := Gdip_BitmapFromScreen()
pBitmapNeedle := Gdip_CreateBitmapFromFile("find.png")

start := A_TickCount
Gdip_FastImageSearch(pBitmapHayStack, pBitmapNeedle, x, y)
msgbox % x ", " y "`nвремя: " A_TickCount - start

start := A_TickCount
list := Gdip_ImageSearchList(pBitmapHayStack, pBitmapNeedle)
msgbox % list "`nвремя: " A_TickCount - start

Gdip_DisposeImage(pBitmapHayStack)
Gdip_DisposeImage(pBitmapNeedle)
Gdip_Shutdown(pToken)
return


;**********************************************************************************
;
; Gdip_FastImageSearch() - 08/MARCH/2013 21:00h BRT
; by MasterFocus, based on previous work by tic and Rseding91
; 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 exclusively for these users:
; - tic , Rseding91 , guest3456
;
;**********************************************************************************

;==================================================================================
;
; pBitmapHayStack
;   Use "Screen" or an already existing pBitmap
;   Default: "" (returns -1)
;
; pBitmapNeedle
;   A filename or an already existing pBitmap
;  Default: "" (returns -1)
;
; x and y
;   Variables to store the X and Y coordinates of the image if it's found
;   Default: "" for both
;
; sx1, sy1, sx2 and sy2
;   These can be used to crop the search area within the haystack
;   Default: "" for all (does not crop)
;
; Variation and Trans
;   Same as the builtin ImageSearch command (I guess we all know that)
;   Default: 0 for both
;
; w and h
;   Parameters used to resize the needle (-1 for one of those will mantain aspect ratio)
;   Default: 0 for both
;
; sd
;   Search direction:
;   0 = auto detect best direction [default]
;   1 = left->right, top->bottom ;; 2 = left->right, bottom->top
;   3 = right->left, bottom->top ;; 4 = right->left, top->bottom
;
; UseLastData
;   Tells the function to keep same haystack and/or needle data for future use
;   - If this is set and there is no previous data, the current data is used and saved
;   - If this is not set, any saved data is deleted/released/unlocked
;   0 or 0x00 = not set for the haystack and not set for the needle
;   1 or 0x01 = set for the haystack and not set for the needle
;   2 or 0x10 = not set for the haystack and set for the needle
;   3 or 0x11 = set for the haystack and set for the needle
;   (specially useful for multiple searches with the same haystack and/or needle)
;   Default: 0
;
; nWidth and nHeight
;   These can be used to store, out of the function, the width and height of the needle internally used
;   (retrieved from the resized needle, if w or h is set)
;   (specially useful for multiple searches with the same haystack and/or needle)
;==================================================================================

Gdip_FastImageSearch(pBitmapHayStack="",pBitmapNeedle="",ByRef x="",ByRef y="",sx1="",sy1="",sx2="",sy2=""
,Variation=0,Trans=0,w=0,h=0,sd=0,UseLastData=0,ByRef byref_nWidth="",ByRef byref_nHeight="")
{
    static _ImageSearch1, _ImageSearch2, _PixelAverage, Ptr, PtrA
    ; {MF} added some static stuff
	, hWidth, hHeight, Stride1, Scan01, BitmapData1, lastHaystack
    , Stride2, Scan02, BitmapData2, lastNeedle, nWidth, nHeight

    ; {MF} verify if we should use/keep data for the haystack and/or the needle
    UseLastHaystackData := !!(UseLastData & 0x01)
    UseLastNeedleData := !!(UseLastData & 0x10)

    ; {MF} delete/unlock/release all previous haystack data if it should not be used
	if !UseLastHaystackData
    {
	    Gdip_UnlockBits(lastHaystack, BitmapData1)
        hWidth := hHeight := Stride1 := Scan01 := BitmapData1 := ""
		Gdip_DisposeImage(lastHaystack)
        lastHaystack := ""
    }

    ; {MF} store the previous needle dimensions in the ByRef variables before possibly deleting the values
    byref_nWidth := nWidth, byref_nHeight := nHeight
    ; {MF} delete/unlock/release all previous needle data if it should not be used
	if !UseLastNeedleData
    {
	    Gdip_UnlockBits(lastNeedle, BitmapData2)
        nWidth := nHeight := Stride2 := Scan02 := BitmapData2 := ""
		Gdip_DisposeImage(lastNeedle)
        lastNeedle := ""
    }
    
    if !_ImageSearch1
    {
        Ptr := A_PtrSize ? "UPtr" : "UInt"
        , PtrA := A_PtrSize ? "UPtr*" : "UInt*"
        
        MCode_ImageSearch1 := "8B4C243483EC10803900538B5C2434555657750C80790100750680790200744B8B54243885D27E478B7C2430478BEA908B7424"
        . "3485F67E2C8BC78D9B000000008A50013A510275128A103A5101750B8A50FF3A117504C640020083C0044E75E08B54243803FB4D75C7EB048B5424388B"
        . "4424488944241C3B4424500F8D800200008B4C243C8BF90FAFF88D4402FF0FAFC1897C2418894424148DA424000000008B742444897424543B74244C0F"
        . "8D300200008B74245C83FE0175648B6C243033D2453B5424380F8D5402000033F6397424347E428B4C24548B5C242C8D0C8F8BC58D4C19018A58013A59"
        . "01750E8A183A1975088A58FF3A59FF740A807802000F85B60100004683C10483C0043B7424347CD38B5C2440037C243C4203EBEBA383FE020F85860000"
        . "008BF88BC14A8BCBF7D8F7D98BF20FAFF38B5C243089442410894C24488D6C1E01EB068D9B0000000083FAFF0F8EC701000033F6397424347E468B4C24"
        . "548B5C242C8D0C8F8BC58D4C19018A58013A5901750E8A183A1975088A58FF3A59FF740A807802000F85290100004683C10483C0043B7424347CD38B44"
        . "24108B4C244803F84A03E9EBA283FE030F85840000004A8BFAF7D90FAFFB8BF3F7DE8BE8894C2410897424488D490083FAFF0F8E470100008B44243448"
        . "83F8FF7E518B7424308B5C242C8D0C878D4C31018B74245403F08D74B5008D741E018A59013A5E01750E8A193A1E75088A59FF3A5EFF740A807902000F"
        . "859B0000004883EE0483E90483F8FF7FD48B7424488B4C241003E94A03FEEB9583FE040F85DC00000033ED896C24488D9B00000000395424480F8DC600"
        . "00008B4424344883F8FF7E4D8B4C24308B74242C8D5485008D4C0A018B54245403D08D14978D7432018A51013A5601750E8A113A1675088A51FF3A56FF"
        . "74068079020075224883EE0483E90483F8FF7FD88B5424388B4C243CFF44244803F903EBEB958B5C24408B4424548B7C24188B5424388B4C243C403B44"
        . "244C894424548B4424140F8CD0FDFFFF8B74241C4603C103F98974241C89442414897C24183B7424500F8C9FFDFFFF8B4C24248B5424285F5E5DC701FF"
        . "FFFFFFC702FFFFFFFF83C8FF5B83C410C38B4424248B4C24548B5424285F89088B4424185E5D890233C05B83C410C3"
        
        MCode_ImageSearch2 := "8B4C24348B54241883EC2C803900538B5C2450555657750C80790100750680790200744E8B6C244C85D27E4A8D7D0189542470"
        . "8B74245085F67E298BC78D49008A50013A510275128A103A5101750B8A50FF3A117504C640020083C0044E75E08B6C244C03FBFF4C247075C78B542454"
        . "EB048B6C244C8B442464894424183B44246C0F8D0C0400008B7C24588B74247C8BCF0FAFC8894C24148B8C248000000003C88D4402FF0FAFCF0FAFC789"
        . "4424108B442474894C2430EB068D9B000000008B4C2460894C24643B4C24680F8DA40300008BD30FAF94248000000003D58D0CB20FB611894C24348B4C"
        . "246003CE8B7424308D0C8E034C244889542438894C242CEB048B4C242C0FB6098D34013BD67F062BC83BD17D0E8B4C2434807903000F85350300008B4C"
        . "247883F9010F85AD0000008B742414C7442470000000008D4D018B542470894C2424897424283B5424540F8D5C03000033ED396C24507E698B5424648D"
        . "14968B7424488D7432018BFF0FB656010FB679018D1C023BFB7F2E2BD03BFA7C280FB6160FB6398D1C023BFB7F1B2BD03BFA7C150FB656FF0FB679FF8D"
        . "1C023BFB7F062BD03BFA7D0A807902000F85930200004583C60483C1043B6C24507CAC8B5C245C8B7424288B4C242403742458FF44247003CBE962FFFF"
        . "FF83F9020F85C60000008B5424108B4C2454498954241C8BD78BF3F7DAF7DE8BF90FAFFB8D7C2F018954242889742424897C2420894C247083F9FF0F8E"
        . "9402000033ED396C24507E798B74241C8B5424648B4C24208D14968B7424488D7432018BFF0FB656010FB679018D1C023BFB7F2E2BD03BFA7C280FB616"
        . "0FB6398D1C023BFB7F1B2BD03BFA7C150FB656FF0FB679FF8D1C023BFB7F062BD03BFA7D0A807902000F85C30100004583C60483C1043B6C24507CAC8B"
        . "7424248B5424288B4C24700154241C4901742420E964FFFFFF83F9030F85D80000008B5424548B4C24104A894C24208BF78BCAF7DE0FAFCB8BFBF7DF89"
        . "742428897C2424894C241C8954247083FAFF0F8EC90100008B6C24504D83FDFF0F8E8B0000008B7424208D14A98B4C244C8D4C0A018B54246403D58D14"
        . "968B7424488D543201EB068D9B000000000FB672010FB679018D1C063BFB7F2E2BF03BFE7C280FB6320FB6398D1C063BFB7F1B2BF03BFE7C150FB672FF"
        . "0FB679FF8D1C063BFB7F062BF03BFE7D0A807902000F85E30000004D83EA0483E90483FDFF7FAD8B7C24248B7424288B4C241C8B542470017424204A03"
        . "CFE94AFFFFFF83F9040F851B0100008B74241433C9894C2470894C24288B4C2470897424243B4C24540F8DFB0000008B6C24504D83FDFF7E738B542428"
        . "8D0CAA8B54244C8D4C11018B54246403D58D14968B7424488D5432010FB672010FB679018D1C063BFB7F2E2BF03BFE7C280FB6320FB6398D1C063BFB7F"
        . "1B2BF03BFE7C150FB672FF0FB679FF8D1C063BFB7F062BF03BFE7D068079020075254D83EA0483E90483FDFF7FB18B5C245C8B74242403742458FF4424"
        . "70015C2428E95CFFFFFF8B5C245C8B6C244C8B7C24588B5424388B4C24648344242C0441894C24643B4C24680F8C91FCFFFF8B74247CFF4424188B4C24"
        . "18017C2410017C2414017C24303B4C246C0F8C2CFCFFFF8B4424408B4C24445F5EC700FFFFFFFF5DC701FFFFFFFF83C8FF5B83C42CC38B5424408B4424"
        . "648B4C24445F89028B5424145E5D891133C05B83C42CC3"
        
        MCode_PixelAverage := "83EC488B4C24608B54246433C0890189028944243C894424388B44245453992BC2558B6C246456578BF88B442468992BC28B54"
        . "24688D5D148D73148D4E14D1FF897E04D1F8894104894308897E088951088B542464897D0C89430C89560C8B54246889510C8B542464897D1089561089"
        . "41108BC52BD92BC18BFE8D51042BF9C74424340100000089542410895C24408944242C897C2430EB178DA424000000008B5424108B5C24408B44242C8B"
        . "7C24308B328B0C1333ED896C2468896C2464896C246C897424443BCE0F8D030100008B0410894424148B0417894424188BC10FAF4424602BF189442438"
        . "8974243C8BFF8B7424148B4C241833DB33FF896C241C896C2420896C2424896C24283BF10F8DA00000002BCE83F9027C538B54245C8D0CB08D4C11018B"
        . "5424182BD683EA02D1EA428D34560FB6410103F80FB60103D80FB641FF0144241C0FB64105014424280FB64104014424240FB641030144242083C1084A"
        . "75CF8B4424388B54241033ED3B7424187D1E8D0CB0034C245C0FB67102017424680FB671010FB60901742464014C246C8B4C24248B7424200374241C03"
        . "CB014C24648B4C24280174246C03CF014C246803442460FF4C243C894424380F852AFFFFFF8B5C24408B44242C8B7C24308B34138B3C172B3C108B0A8B"
        . "4424682BCE0FAFCF33D2F7F133D2896C24688BF88B442464F7F133D28BD88B44246CF7F18D57198954246C8D4B1983C7E783C3E7897C243C894C243889"
        . "5C24288D50198954242483C0E733D2894424203B7424440F8DAE0000008B4424108B4C242C8B0C01894C24148B4C24308B1C018BC60FAF442460895C24"
        . "1C894424648D49008B7C24143BFB7D6B8B4C245C8D04B88D4C080280790100744A0FB6018BDA3B44246C7D063B44243C7F01420FB641FF3B4424387D06"
        . "3B4424287F01420FB641FE3B4424247D063B4424207F01428BC22BC33B4424687E0C897C245089742454894424688B5C241C4783C1043BFB7CA48B4424"
        . "640344246046894424643B7424440F8C7AFFFFFF3B5424487E208B4424708B4C2450895424488B54243489088B4424548954244C8B54247489028B4424"
        . "348344241004408944243483F8050F8C7DFDFFFF8B44244C5F5E5D5B83C448C3"
        
        VarSetCapacity(_ImageSearch1, StrLen(MCode_ImageSearch1)//2, 0)
        Loop % StrLen(MCode_ImageSearch1)//2      ;%
            NumPut("0x" . SubStr(MCode_ImageSearch1, (2*A_Index)-1, 2), _ImageSearch1, A_Index-1, "uchar")
        MCode_ImageSearch1 := ""
        
        VarSetCapacity(_ImageSearch2, 1233, 0)
        Loop % StrLen(MCode_ImageSearch2)//2      ;%
            NumPut("0x" . SubStr(MCode_ImageSearch2, (2*A_Index)-1, 2), _ImageSearch2, A_Index-1, "uchar")
        MCode_ImageSearch2 := ""
        
        VarSetCapacity(_PixelAverage, StrLen(MCode_PixelAverage)//2, 0)
        Loop % StrLen(MCode_PixelAverage)//2      ;%
            NumPut("0x" . SubStr(MCode_PixelAverage, (2*A_Index)-1, 2), _PixelAverage, A_Index-1, "uchar")
        MCode_PixelAverage := ""
        
        , DllCall("VirtualProtect", Ptr, &_ImageSearch1, Ptr, VarSetCapacity(_ImageSearch1), "uint", 0x40, PtrA, 0)
        , DllCall("VirtualProtect", Ptr, &_ImageSearch2, Ptr, VarSetCapacity(_ImageSearch2), "uint", 0x40, PtrA, 0)
        , DllCall("VirtualProtect", Ptr, &_PixelAverage, Ptr, VarSetCapacity(_PixelAverage), "uint", 0x40, PtrA, 0)
    }
    
    If ( UseLastHaystackData && lastHaystack ) ; {MF] if there IS a previous haystack, it's ok to use it
        pBitmapHayStack := lastHaystack
    Else {
        ;Alows the MCode to be setup before imagesearch is really needed
        if (pBitmapHayStack = "")
            return -1
        if (pBitmapHayStack = "Screen") {
            Dump_Haystack := !UseLastHaystackData ; {MF} also, only dump if we're not saving/reusing it
            pBitmapHayStack := Gdip_BitmapFromScreen()
        }
    }
    lastHaystack := pBitmapHayStack ; {MF] save the current haystack (even if it's the same, won't hurt)
    
    If ( UseLastNeedleData && lastNeedle ) ; {MF] if there IS a previous needle, it's ok to use it
        pBitmapNeedle := lastNeedle
    Else {
        if (pBitmapNeedle = "")
            return -1
        if (FileExist(pBitmapNeedle)) {
            ;Load the image from the HD
            Dump_Needle := !UseLastNeedleData ; {MF} also, only dump if we're not saving/reusing it
            pBitmapNeedle := Gdip_CreateBitmapFromFile(pBitmapNeedle)
        }
    }
    lastNeedle := pBitmapNeedle ; {MF] save the current needle (even if it's the same, won't hurt)
    
    if (Variation > 255 || Variation < 0)
        return -2
    
    ; {MF} retrieve the haystack dimensions if we don't wanna use the saved data OR this information is not saved yet
    ; {MF} (this if-statement may not be necessary, I still have to test it)
	if ( !UseLastHaystackData || !hWidth )
        Gdip_GetImageDimensions(pBitmapHayStack, hWidth, hHeight)
    ; {MF} retrieve the needle dimensions if we don't wanna use the saved data OR this information is not saved yet
    ; {MF} (this if-statement may not be necessary, I still have to test it)
	if ( !UseLastNeedleData || !nWidth )
    {
        Gdip_GetImageDimensions(pBitmapNeedle, nWidth, nHeight)
        byref_nWidth := nWidth, byref_nHeight := nHeight ; {MF} replicate the dimensions to the ByRef parameters
    }
    
    if !(hWidth && hHeight && nWidth && nHeight)
        return -3
    if (nWidth > hWidth || nHeight > hHeight)
        return -4
    
    ;Sets/corrects resize variables
    w := (w < -1) ? 0 : w
    , h := (h < -1) ? 0 : h
    
    ;Resizes the needle image if w/h are set
    ;What a pain...
    if (w || h){
        ;Creates a resized needle image and set pBitmapNeedle to the bitmap
        if (w = -1)
            sH := h, sW := nWidth / nHeight, sW := Round(sH * sW)
        else if (h = -1)
            sW := w, sH := nHeight / nWidth, sH := Round(sW * sH)
        else
            sW := w, sH := h
        
        pTempBitmap := Gdip_CreateBitmap(sW, sH)
        , pG := Gdip_GraphicsFromImage(pTempBitmap)

        , Gdip_SetInterpolationMode(pG, 7)
        , Gdip_DrawImage(pG, pBitmapNeedle, 0, 0, sW, sH, 0, 0, nWidth, nHeight)
        , Gdip_DeleteGraphics(pG)
        
        , pBitmapNeedle := pTempBitmap
        , Gdip_GetImageDimensions(pBitmapNeedle, nWidth, nHeight)
        , byref_nWidth := nWidth, byref_nHeight := nHeight ; ADICIONADO (adicinada) esta linha
        
        if !(nWidth && nHeight){
            Gdip_DisposeImage(pBitmapNeedle)
            if (Dump_HayStack)
                Gdip_DisposeImage(pBitmapHayStack)
            return -5
        }
        if (nWidth > hWidth || nHeight > hHeight){
            Gdip_DisposeImage(pBitmapNeedle)
            if (Dump_HayStack)
                Gdip_DisposeImage(pBitmapHayStack)
            return -6
        }
    }
    
    ;Sets/corrects search box and needle scan direction
    sx1 := (sx1 = "") ? 0 : sx1
    , sy1 := (sy1 = "") ? 0 : sy1
    , sx2 := (sx2 = "") ? hWidth : (sx2 - nWidth + 1)
    , sy2 := (sy2 = "") ? hHeight : (sy2 - nHeight + 1)
    , sd := (sd < 0 || sd > 4) ? 1 : sd
    
    if (sx1 < 0 || sy1 < 0){
        if (w || h || Dump_Needle)
            Gdip_DisposeImage(pBitmapNeedle)
        if (Dump_HayStack)
            Gdip_DisposeImage(pBitmapHayStack)
        return -7
    }
    
    ;Detects too small search boxes
    if ((sx2 - sx1) < 1 || (sy2 - sy1) < 1){
        if (w || h || Dump_Needle)
            Gdip_DisposeImage(pBitmapNeedle)
        if (Dump_HayStack)
            Gdip_DisposeImage(pBitmapHayStack)
        return -8
    }
    
    ;Prevents searching to close to the edges: it can't match 20 pixels in a 19 pixel search area
    if (sx2 > (hWidth - nWidth + 1))
        sx2 := (hWidth - nWidth) + 1
    if (sy2 > (hHeight - nHeight + 1))
        sy2 := (hHeight - nHeight) + 1
    
    ;Detects invalid search boxes
    if (sx2 < sx1 || sy2 < sy1){
        if (w || h || Dump_Needle)
            Gdip_DisposeImage(pBitmapNeedle)
        if (Dump_HayStack)
            Gdip_DisposeImage(pBitmapHayStack)
        return -9
    }
    
    ; {MF} the following should be faster than 2 if-statements
    sx2 += !sx2
    sy2 += !sy2
    
    ;If Trans is used and the needle hasen't already been copied through scaling or loading
    ;create a copy because it might be modified by the imagesearch code
    ; {MF} we can only do that if we're not using saved data!
    if ( (!w && !h && Trans && !Dump_Needle) && !UseLastNeedleData )
        pBitmapNeedle := Gdip_CloneBitmapArea(pBitmapNeedle, 0, 0, nWidth, nHeight)        
    
    ;Stride2/Scan02/BitmapData2 are used because the needle is the second image eventhough it's used first
    ; {MF} lock the bits if we don't wanna use the saved data OR the bits are not locked yet
	if (!UseLastNeedleData || !BitmapData2)
    {
        if Gdip_LockBits(pBitmapNeedle, 0, 0, nWidth, nHeight, Stride2, Scan02, BitmapData2) {
            if (w || h || Trans || Dump_Needle)
                Gdip_DisposeImage(pBitmapNeedle)
            if (Dump_HayStack)
                Gdip_DisposeImage(pBitmapHayStack)
            return -12
        }
    }
    
    ;Averages the needle in 4 chunks counting the number of pixels(R, G & B) that arn't +- 25 of the average color
    ;and sets the search code to scan that corner first when matching the image
    ;Also sets a "Check this pixel first" location for the haystack instead of always starting at the corner of the image (0/0, w/h, ...)
    if (sd = 0 And nWidth >= 20 And nHeight >= 20){
        VarSetCapacity(TempData, 5*4*4, 0) ;5 entires at 4 entires each at 4 bytes each
        , sd := DllCall(&_PixelAverage, Ptr, Scan02, "Int", Stride2, "Int", nWidth, "Int", nHeight, Ptr, &TempData
        , "UInt*", suX, "UInt*", suY, "cdecl int")
        , VarSetCapacity(TempData, 0)
    } else
        sd += !sd ; {MF} this should be faster than an if-statement
    
    ;Sets the default search-first location for variation searches if none was set yet
    suX := (suX = "" || suX = -1) ? 0 : suX
    , suY := (suY = "" || suY = -1) ? 0 : suY
    
    ; {MF} lock the bits if we don't wanna use the saved data OR the bits are not locked yet
	if (!UseLastHaystackData || !BitmapData1)
        if (Gdip_LockBits(pBitmapHayStack, 0, 0, hWidth, hHeight, Stride1, Scan01, BitmapData1)){
            if (w || h || Trans || Dump_Needle)
                Gdip_DisposeImage(pBitmapNeedle)
            if (Dump_HayStack)
                Gdip_DisposeImage(pBitmapHayStack)
            return -12
        }
    
    ;The dllcall parameters are the same for easier C code modification even though they arn't all used on the _ImageSearch1 version
    x := 0, y := 0
    , E := DllCall((Variation = 0 ? &_ImageSearch1 : &_ImageSearch2), "int*", x, "int*", y, Ptr, Scan01, Ptr, Scan02, "int", nWidth
    , "int", nHeight, "int", Stride1, "int", Stride2, "int", sx1, "int", sy1, "int", sx2, "int", sy2, Ptr, &Trans, "int", Variation
    , "int", sd, "int", suX, "int", suY, "cdecl int")

    ; {MF} delete/unlock/release all current haystack data (except the bitmap itself) if it should not be saved
    if !UseLastHaystackData
    {
        Gdip_UnlockBits(pBitmapHayStack, BitmapData1)
        hWidth := hHeight := Stride1 := Scan01 := BitmapData1 := ""
        lastHaystack := ""
    }
    ; {MF} delete/unlock/release all current needle data (except the bitmap itself) if it should not be saved
    if !UseLastNeedleData
    {
        Gdip_UnlockBits(pBitmapNeedle, BitmapData2)
        Stride2 := Scan02 := BitmapData2 := nWidth := nHeight := ""
        lastNeedle := ""
    }
    
    if ( w || h || Trans || Dump_Needle )
        Gdip_DisposeImage(pBitmapNeedle)
    
    if ( Dump_HayStack )
        Gdip_DisposeImage(pBitmapHayStack)
    
    return (E = "") ? -13 : E
}

;**********************************************************************************
;
; Gdip_ImageSearchList() by MasterFocus - 08/MARCH/2013 18:45h BRT
; Requires Gdip_FastImageSearch() by MasterFocus
; 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 exclusively for these users:
; - tic , Rseding91 , guest3456
;
;**********************************************************************************



Gdip_ImageSearchList(Haystack="Screen",Needle="",KEEP=0x11) {
;-----------------------------------------
    OuterX1 := OuterY1 := 0
    OuterX2 := A_ScreenWidth
    OuterY2 := A_ScreenHeight
    VARI := TRANS := W := H := 0
    DIR := 1
    LineDelim := "`n"
    CoordDelim := ","
;-----------------------------------------
    InnerX1 := OuterX1
    InnerY1 := OuterY1
    InnerX2 := OuterX2
    InnerY2 := OuterY2
    While !Gdip_FastImageSearch(Haystack,Needle,FoundX,FoundY,OuterX1,OuterY1,OuterX2,OuterY2,VARI,TRANS,W,H,DIR,KEEP,NeedleWidth,NeedleHeight)
    {
        OuterY1 := FoundY+1
        OutputList .= LineDelim FoundX CoordDelim FoundY
        InnerX1 := FoundX+1
        InnerY1 := FoundY
        InnerY2 := InnerY1+NeedleHeight
        While !Gdip_FastImageSearch(Haystack,Needle,FoundX,FoundY,InnerX1,InnerY1,InnerX2,InnerY2,VARI,TRANS,W,H,DIR,KEEP)
        {
            OutputList .= LineDelim FoundX CoordDelim FoundY
            InnerX1 := FoundX+1
        }
    }
    Gdip_FastImageSearch()
    Return SubStr(OutputList,1+StrLen(LineDelim))
}

7

Re: AHK: ImageSearch без файла картинки

Кстати, поделка от Rseding91, упомянутого в примере выше, позволяет сделать каталог файлов заранее вписанных в код, который можно оформить как подключаемая через "#Include" библиотека и производить сканирование по дескрипторам вписанных таким образом файлов. Это может делать как стандартный способ:


ImageSearch,xx,yy,x,y,w,h,% "*10 *Trans000000 HBITMAP:*" file_desc
if (ErrorLevel == 0) {
	...	; Выполнить код
}

Так и посредством "Gdip_ImageSearch()":


needlePointer := Gdip_CreateBitmapFromHBITMAP(file_desc)

И передавать его в функцию вторым параметром.

А вот чтобы прям насовсем избавиться от предварительной подготовки графических фрагментов поиска, если хорошо подумать, то скорее всего не окажется делом достаточно целесообразным. Ведь в любом случае, искомые фрагменты будут использоваться и далее, тогда получается, что их предварительная подготовка снимает дополнительный вопрос накладных вычислительных расходов необходимых при каждой работе.

8

Re: AHK: ImageSearch без файла картинки

О, а я пропустил это нововведение , что можно в ImageSearch искать HBITMAP.
Vicoriyan, тогда можно:

SetBatchLines, -1
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen()
Gdip_GetDimensions(pBitmap, w, h)
pBitmap2 := Gdip_CropImage(pBitmap, 50, 110, 25, 30)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap2)
Loop
{
   ImageSearch, FoundX, FoundY, 0, 0, A_ScreenWidth, A_ScreenHeight, HBITMAP:*%hBitmap%
   If ErrorLevel
   {
      MsgBox картинка исчезла
      Break
   }
   msgbox % foundx
}
Gdip_DisposeImage(pBitmap), Gdip_DisposeImage(pBitmap2)
DeleteObject(hBitmap)
Gdip_Shutdown(pToken)
return

Gdip_CropImage(pBitmap, x, y, w, h)
{
   pBitmap2 := Gdip_CreateBitmap(w, h), G2 := Gdip_GraphicsFromImage(pBitmap2)
   Gdip_DrawImage(G2, pBitmap, 0, 0, w, h, x, y, w, h)
   Gdip_DeleteGraphics(G2)
   return pBitmap2
}