1 (изменено: Malcev, 2020-10-13 07:17:00)

Тема: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Работает на win8+ и ahk 32 bit.
IDXGIOutputDuplication удобен тем, что делает снимок экрана только после обновления рабочего стола.
Gdip_FastImageSearch(), немного измененный мной (удалил некоторые бесполезные функции) отсюда:
https://github.com/MasterFocus/AutoHotk … Search.ahk
Cкрипт делает 10 снимков экрана и
1) ищет "needle.bmp" в координатах x1: = 0, y1: = 0, x2: = 1920, y2: = 1080.
2) ищет needle.png с прозрачным белым цветом и вариацией 10.
3) ищет все совпадения needle.bmp.
Также можно изменить направление поиска SearchDirection.
1 = left->right, top->bottom | 2 = left->right, bottom->top | 3 = right->left, bottom->top | 4 = right->left, top->bottom

GoSub, StartSection
needle1 := createNeedle("needle.bmp")
needle2 := createNeedle("needle.png", 0xffffff)

f11::
loop 10
{
   tooltip % A_Index
   loop
   {
      VarSetCapacity(DXGI_OUTDUPL_FRAME_INFO, 48, 0)
      AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, INFINITE := 0xFFFFFFFF, &DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
      LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, "int64")
      if (LastPresentTime != 0)
      {
         if (DesktopImageInSystemMemory = 1)
         {
            VarSetCapacity(DXGI_MAPPED_RECT, A_PtrSize*2, 0)
            IDXGIOutputDuplication_MapDesktopSurface(Duplication, &DXGI_MAPPED_RECT)
            haystack.Stride := NumGet(DXGI_MAPPED_RECT, 0, "int")
            haystack.Scan := NumGet(DXGI_MAPPED_RECT, A_PtrSize, "ptr")
         }
         else
         {
            tex := ID3D11Texture2D_Query(desktop_resource)
            ID3D11DeviceContext_CopyResource(d3d_context, staging_tex, tex)
            VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
            ID3D11DeviceContext_Map(d3d_context, staging_tex, 0, D3D11_MAP_READ := 1, 0, &D3D11_MAPPED_SUBRESOURCE)
            haystack.Scan := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
            haystack.Stride := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
         }

         if !Gdip_FastImageSearch(Haystack, needle1, 0, 0, 1920, 1080)
            msgbox % needle1.x " - " needle1.y

         if !Gdip_FastImageSearch(Haystack, needle2, 0, 0, 1920, 1080, variation := 10, SearchDirection := 2)
            msgbox % needle2.x " - " needle2.y

         list := Gdip_FastImageSearchList(Haystack, needle1, 0, 0, 1920, 1080)
         loop % list.count
            msgbox % list.x[A_Index] "-" list.y[A_Index]

         if (DesktopImageInSystemMemory = 1)
            IDXGIOutputDuplication_UnMapDesktopSurface(Duplication)
         else
         {
            ID3D11DeviceContext_Unmap(d3d_context, staging_tex, 0)
            ObjRelease(tex)
         }
         ObjRelease(desktop_resource)
         IDXGIOutputDuplication_ReleaseFrame(duplication)
         break
      }
      ObjRelease(desktop_resource)
      IDXGIOutputDuplication_ReleaseFrame(duplication)
   }
}
return



StartSection:
setbatchlines -1
IDXGIFactory := CreateDXGIFactory()
if !IDXGIFactory
{
   MsgBox, 16, Error, Create IDXGIFactory failed.
   ExitApp
}
loop
{
   IDXGIFactory_EnumAdapters(IDXGIFactory, A_Index-1, IDXGIAdapter)
   loop
   {
      hr := IDXGIAdapter_EnumOutputs(IDXGIAdapter, A_Index-1, IDXGIOutput)
      if (hr = "DXGI_ERROR_NOT_FOUND")
         break
      VarSetCapacity(DXGI_OUTPUT_DESC, 88+A_PtrSize, 0)
      IDXGIOutput_GetDesc(IDXGIOutput, &DXGI_OUTPUT_DESC)
      width := NumGet(DXGI_OUTPUT_DESC, 72, "int")
      height := NumGet(DXGI_OUTPUT_DESC, 76, "int")
      AttachedToDesktop := NumGet(DXGI_OUTPUT_DESC, 80, "int")
      if (AttachedToDesktop = 1)
         break 2         
   }
}
if (AttachedToDesktop != 1)
{
   MsgBox, 16, Error, No adapter attached to desktop
   ExitApp
}
D3D11CreateDevice(IDXGIAdapter, D3D_DRIVER_TYPE_UNKNOWN := 0, 0, 0, 0, 0, D3D11_SDK_VERSION := 7, d3d_device, 0, d3d_context)
IDXGIOutput1 := IDXGIOutput1_Query(IDXGIOutput)
IDXGIOutput1_DuplicateOutput(IDXGIOutput1, d3d_device, Duplication)
VarSetCapacity(DXGI_OUTDUPL_DESC, 36, 0)
IDXGIOutputDuplication_GetDesc(Duplication, &DXGI_OUTDUPL_DESC)
DesktopImageInSystemMemory := NumGet(DXGI_OUTDUPL_DESC, 32, "uint")
sleep 50   ; As I understand - need some sleep for successful connecting to IDXGIOutputDuplication interface
VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
NumPut(width, D3D11_TEXTURE2D_DESC, 0, "uint")   ; Width
NumPut(height, D3D11_TEXTURE2D_DESC, 4, "uint")   ; Height
NumPut(1, D3D11_TEXTURE2D_DESC, 8, "uint")   ; MipLevels
NumPut(1, D3D11_TEXTURE2D_DESC, 12, "uint")   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, "uint")   ; Format 
NumPut(1, D3D11_TEXTURE2D_DESC, 20, "uint")   ; SampleDescCount
NumPut(0, D3D11_TEXTURE2D_DESC, 24, "uint")   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, "uint")   ; Usage
NumPut(0, D3D11_TEXTURE2D_DESC, 32, "uint")   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, D3D11_TEXTURE2D_DESC, 36, "uint")   ; CPUAccessFlags
NumPut(0, D3D11_TEXTURE2D_DESC, 40, "uint")   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &D3D11_TEXTURE2D_DESC, 0, staging_tex)
haystack := {}
DllCall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, 8+2*A_PtrSize, 0)
NumPut(0x1, si, "uint")
DllCall("gdiplus\GdiplusStartup", "ptr*", pToken, "ptr", &si, "ptr", 0)
return

createNeedle(path, ByRef TransColor="", ByRef pBitmap="", ByRef BitmapData="", ByRef Scan="")
{
   DllCall("gdiplus\GdipCreateBitmapFromFile", "ptr", &path, "ptr*", pBitmap)
   DllCall("gdiplus\GdipGetImageWidth", "ptr", pBitmap, "uint*", width)
   DllCall("gdiplus\GdipGetImageHeight", "ptr", pBitmap, "uint*", height)
   VarSetCapacity(Rect, 16, 0)
   NumPut(width, Rect, 8, "uint")
   NumPut(height, Rect, 12, "uint")
   VarSetCapacity(BitmapData, 16+2*A_PtrSize, 0)
   DllCall("gdiplus\GdipBitmapLockBits", "ptr", pBitmap, "ptr", &Rect, "uint", ReadWrite := 3, "int", Format32bppArgb := 2498570, "ptr", &BitmapData)
   Stride := NumGet(BitmapData, 8, "int")
   Scan := NumGet(BitmapData, 16, "ptr")
   if (TransColor != "")
   {
      loop % height
      {
         A_IndexY := A_Index-1
         loop % width
         {
            If ((NumGet(Scan+0, (A_Index-1)*4 + A_IndexY*Stride, "uint") & 0xFFFFFF) = TransColor)
               Numput(TransColor, Scan+0, (A_Index-1)*4 + A_IndexY*Stride, "uint")
         }
      }
   }
   else
      TransColor := 0
   obj := {TransColor: &TransColor, width: width, height: height, pBitmap: pBitmap, BitmapData: &BitmapData, Scan: Scan, Stride: Stride}
   return obj
}

Gdip_FastImageSearchList(Haystack, needle, x1, y1, x2, y2, Variation=0, SearchDirection=1)
{
   OutputList := {}
   OutputList.count := 0
   While !Gdip_FastImageSearch(Haystack, needle, x1, y1, x2, y2, Variation, SearchDirection)
   {
      OutputList.count++
      y1 := needle.y+1
      OutputList.x[OutputList.count] := needle.x
      OutputList.y[OutputList.count] := needle.y
      innerX1 := needle.x+1
      innerY1 := needle.y
      innerY2 := innerY1+needle.height
      While !Gdip_FastImageSearch(Haystack, needle, innerX1, innerY1, x2, innerY2, Variation, SearchDirection)
      {
         OutputList.count++
         OutputList.x[OutputList.count] := needle.x
         OutputList.y[OutputList.count] := needle.y
         innerX1 := needle.x+1
      }
   }
   return OutputList
}

CreateDXGIFactory()
{
   if !DllCall("GetModuleHandle","str","DXGI")
      DllCall("LoadLibrary","str","DXGI")
   if !DllCall("GetModuleHandle","str","D3D11")
      DllCall("LoadLibrary","str","D3D11")
   GUID(riid, "{7b7166ec-21c7-44ae-b21a-c9ae321ae369}")
   hr := DllCall("DXGI\CreateDXGIFactory1", "ptr", &riid, "ptr*", ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return ppFactory
}

IDXGIFactory_EnumAdapters(this, Adapter, ByRef ppAdapter)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Adapter, "ptr*", ppAdapter)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIAdapter_EnumOutputs(this, Output, ByRef ppOutput)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Output, "ptr*", ppOutput)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0002   ; DXGI_ERROR_NOT_FOUND
         return "DXGI_ERROR_NOT_FOUND"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

IDXGIAdapter_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_GetDesc(this, pDesc)
{
   DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_AcquireNextFrame(this, TimeoutInMilliseconds, pFrameInfo, ByRef ppDesktopResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "uint", TimeoutInMilliseconds, "ptr", pFrameInfo, "ptr*", ppDesktopResource)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0027   ; DXGI_ERROR_WAIT_TIMEOUT
         return "DXGI_ERROR_WAIT_TIMEOUT"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ByRef ppDevice, ByRef pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall("D3D11\D3D11CreateDevice", "ptr", pAdapter, "int", DriverType, "ptr", Software, "uint", Flags, "ptr", pFeatureLevels, "uint", FeatureLevels, "uint", SDKVersion, "ptr*", ppDevice, "ptr*", pFeatureLevel, "ptr*", ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Device_CreateTexture2D(this, pDesc, pInitialData, ByRef ppTexture2D)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr", pDesc, "ptr", pInitialData, "ptr*", ppTexture2D)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_MapDesktopSurface(this, pLockedRect)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr", pLockedRect)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0x887A0004   ; DXGI_ERROR_UNSUPPORTED
         return "DXGI_ERROR_UNSUPPORTED"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

IDXGIOutputDuplication_UnMapDesktopSurface(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutputDuplication_ReleaseFrame(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput1_DuplicateOutput(this, pDevice, ByRef ppOutputDuplication)
{
   hr := DllCall(NumGet(NumGet(this+0)+22*A_PtrSize), "ptr", this, "ptr", pDevice, "ptr*", ppOutputDuplication)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGIOutput1_Query(IDXGIOutput)
{ 
   hr := ComObjQuery(IDXGIOutput, "{00cddea8-939b-4b83-a340-a685226666cc}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

ID3D11Texture2D_Query(desktop_resource)
{ 
   hr := ComObjQuery(desktop_resource, "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

ID3D11DeviceContext_CopyResource(this, pDstResource, pSrcResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+47*A_PtrSize), "ptr", this, "ptr", pDstResource, "ptr", pSrcResource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_CopySubresourceRegion(this, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox)
{
   hr := DllCall(NumGet(NumGet(this+0)+46*A_PtrSize), "ptr", this, "ptr", pDstResource, "uint", DstSubresource, "uint", DstX, "uint", DstY, "uint", DstZ, "ptr", pSrcResource, "uint", SrcSubresource, "ptr", pSrcBox)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Map(this, pResource, Subresource, MapType, MapFlags, pMappedResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource, "uint", MapType, "uint", MapFlags, "ptr", pMappedResource)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Unmap(this, pResource, Subresource)
{
   hr := DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

GUID(ByRef GUID, sGUID)
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "WStr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
}

_Error(val)
{
   msgbox % val
   ExitApp
}



;**********************************************************************************
;
; 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(haystack, needle, x1, y1, x2, y2, Variation=0, SearchDirection=1)
{
    static _ImageSearch1, _ImageSearch2, _PixelAverage, Ptr, PtrA
    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)
    }

    ;The dllcall parameters are the same for easier C code modification even though they arn't all used on the _ImageSearch1 version
    E := DllCall((Variation = 0 ? &_ImageSearch1 : &_ImageSearch2), "int*", x, "int*", y, "ptr", haystack.Scan, "ptr", needle.Scan, "int", needle.Width
    , "int", needle.Height, "int", haystack.Stride, "int", needle.Stride, "int", x1, "int", y1, "int", x2-needle.Width+1, "int", y2-needle.Height+1, "ptr", needle.TransColor, "int", Variation
    , "int", SearchDirection, "int", 0, "int", 0, "cdecl int")
    needle.x := x, needle.y := y
    return (E = "") ? -13 : E
}

Чтобы проверить какой получается снимок с экрана нужно поставить следующий код перед Gdip_FastImageSearch().
Снимок сохранится в test.bmp.

DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", count, "uint*", size)
VarSetCapacity(ci, size)
DllCall("gdiplus\GdipGetImageEncoders", "uint", count, "uint", size, "ptr", &ci)
Loop % count
{
   EncoderExtensions := StrGet(NumGet(ci, (idx:=(48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize, "ptr"), "utf-16")
   if InStr(EncoderExtensions, "*.bmp")
   {
      pCodec := &ci + idx
      break
   }
}
DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width, "int", height, "int", haystack.stride, "int", Format32bppArgb := 2498570, "ptr", haystack.scan, "ptr*", pBitmap)
DllCall("gdiplus\GdipSaveImageToFile", "ptr", pBitmap, "wstr", "test.bmp", "ptr", pCodec, "uint", 0)
DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
msgbox done
ExitApp

2

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Круто, а оно может находить все совпадения?
И пробовал png, не находит.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

3

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Сделал вроде как поудобнее и добавил поиск всех совпадений.
У меня png находит.
По идее скрипту всё-равно в каком формате картинка будет.

4

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

У меня первый пост выглядит теперь как троеточие.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

5

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Поправил.

6

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev, скажите пожалуйста, в чём его превосходство перед стандартным ImageSearch?
Скорость?

7 (изменено: Malcev, 2020-10-12 14:17:04)

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

По идее да.
Надо тестировать на конкретных примерах.
Получение снимка экрана точно быстрее.
Ну и по-моему сам подход у меня логичней, так как я разделил скрипт на 3 части, первая - подготовка картинок для поиска, второе - получение экрана по современному апи, третье - сам поиск (вот тут могут быть косяки со скоростью).
Для самого поиска на входе ничего больше кроме scan+stride не надо, поэтому я убрал оттуда простыню лишних преобразований.

8

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev пишет:

(вот тут могут быть косяки со скоростью).

Так а почему просто не сравнить однократный поиск большого изображения ImageSearch и всего твоего кода?

Foma пишет:

Malcev, скажите пожалуйста, в чём его превосходство перед стандартным ImageSearch?

Думаю даже если этот тест будет в пользу ImageSearch, то однозначно Gdip_FastImageSearch для поиска картинки в цикле будет намного быстрее.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

9

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Можно попробовать.
Но лучше найти кто разбирается в Си и может сравнить алгоритм этого кода с кодом imagesearch или  предложит какой-нибудь более шустрый алгоритм.

10

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev пишет:

найти кто разбирается в Си

Насколько я знаю далеко не все Си-шники знают ассемблер.
Так ты просто время не сравнивал?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

11 (изменено: Malcev, 2020-10-12 22:19:07)

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

serzh82saratov пишет:

Так ты просто время не сравнивал?

Время зависит от конкретных ситуаций.
Иногда находит быстрее imagesearch иногда Gdip_FastImageSearch.
Если использовать variation = 0, то вроде всегда быстрее работает, правда у меня не всегда находило.
Поставил по-дефалту 0.

serzh82saratov пишет:

Насколько я знаю далеко не все Си-шники знают ассемблер.

А зачем ассемблер? Код поиска на си написан.
https://github.com/MasterFocus/AutoHotk … geSearch.c
По идее алгоритм очень простой - в цикле сравниваются пиксели и всё.
Наверняка можно ускорить.

12 (изменено: Malcev, 2020-10-13 00:01:53)

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Потестировал.
Так скорость быстрее в среднем на 25 процентов.
Но бывает, что при просмотре ютуба и в 2 раза.

13

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev пишет:

А зачем ассемблер? Код поиска на си написан.

В Gdip_FastImageSearch разве не ассемблерная вставка?

Malcev пишет:

По идее алгоритм очень простой

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

14

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

serzh82saratov пишет:

В Gdip_FastImageSearch разве не ассемблерная вставка?

Нет.

serzh82saratov пишет:

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

Ну почему же. Есть различные алгоритмы.
Например Рабина — Карпа.
https://ru.wikipedia.org/wiki/%D0%90%D0 … 0%BF%D0%B0

15 (изменено: plank1433, 2020-10-13 02:46:49)

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev, этот скрипт - ищет точное совпадение картинки (пиксель в пиксель) или могут быть небольшие отличия (больше-меньше по размеру) ?

16

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Пиксель в пиксель.

17

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev,  приложите файлы needle.bmp  и  needle.png
А то не понятно как тестировать.

18

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Вы их должны создать сами.

19

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev пишет:
serzh82saratov пишет:

В Gdip_FastImageSearch разве не ассемблерная вставка?

Нет.

Я думал что такие вставки делают только на ассемблере. Я же правильно понимаю что эти данные могут состоять только из машинного кода? Тогда получается что в VS можно кусок кода Си превратить в машинный код?

Malcev пишет:

Есть различные алгоритмы.
Например Рабина — Карпа.

Мало что там понял, сравнивать не по одному пикселю, а по несколько за раз?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

20

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

serzh82saratov пишет:

Тогда получается что в VS можно кусок кода Си превратить в машинный код?

Вроде через эту утилиту можно:
https://www.autohotkey.com/boards/viewt … amp;t=4642

serzh82saratov пишет:

Мало что там понял, сравнивать не по одному пикселю, а по несколько за раз?

Я, если честно, не разбирался.
Надо бы посмотреть какой алгоритм у автохотки.

21

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev пишет:

Вроде через эту утилиту можно:

Круто, не знал что это может быть довольно просто.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

22

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev пишет:

Надо бы посмотреть какой алгоритм у автохотки.

Вроде такой же примерно.
https://github.com/Lexikos/AutoHotkey_L … .cpp#L4889

23

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev пишет:

Вы их должны создать сами.

Ну хотя бы ради примера что ли.
Чтобы понять, что сами-то создавать.

Написано
2) ищет needle.png с прозрачным белым цветом и вариацией 10.
3) ищет все совпадения needle.bmp.

Совпадения needle.bmp еще можно понять.
Точное совпадение некоего фрагмента - на экране монитора.
Но что значит needle.png с прозрачным белым цветом и вариацией 10 - это совершенно непонятно.
Вариацией чего ?
Что значит прозрачным белым цветом ?
Что может означать прозрачный белый цвет - на экране ?

24

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

plank1433 функция ищет картинку на экране, аналог ImageSearch в AHK.
Ну можно было погуглить что такое png формат, чем он отличается от Jpeg, bmp и т.д. Можно было не гуглить, а в Paint попробовать сохранить картинку с альфа каналом в формате png и в других форматах и посмотреть на разницу.

25

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Botsy пишет:

Ну можно было погуглить что такое png формат

Да знаю я что такое png формат, и что такое альфа-канал.

Я не понимаю - каким образом альфа-канал - оказался на рабочем столе.
Ну допустим разместили картинку с прозрачным фоном, ладно.
Изображения рабочего стола, на котором ведется поиск фрагмента - это PrintScreen.
PrintScreen - никакого альфа-канала не передает.
Так где осуществляет поиск этот скрипт, и что он конкретно ищет и что означает - искать на экране фрагмент с прозрачным фоном ?

(Автору наверное это все понятно. Но я все эти вопросы задаю, потому что не были приложены файлы картинок - для проверки этого скрипта и непонятен просто принцип его работы.)

26

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Все точно так же как и у imagesearch.
Прозрачность картинок которые ищем подхватывается автоматом.
Так же можно сделать прозрачным любой цвет указав его 2-ым параметром в createNeedle("needle.png", 0xffffff)
Скрипт делает копию экрана и ищет в нем совпадения.

27

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Ясно.
Видимо файлы - засекреченные, поэтому на примере продемонстрировать нельзя.

28

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Ну например файл может быть таким:
http://lurkmore.so/images/d/d8/Rtfm.jpg

29

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Malcev, то есть надпись RTFM - это и есть пнг с альфаканалом.

30

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Да. И если эта картинка есть на экране, то скрипт ее должен найти.

31

Re: AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch

Теперь все ясно.