<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=17670</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=17670&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch».]]></description>
		<lastBuildDate>Sun, 12 Mar 2023 14:52:57 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[AHK: поиск картинки с IDXGIOutputDuplication + Gdip_FastImageSearch]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=157116#p157116</link>
			<description><![CDATA[<p>Работает на win8+.<br />IDXGIOutputDuplication удобен тем, что делает снимок экрана только после обновления рабочего стола.<br />Gdip_FastImageSearch(), немного измененный мной (удалил некоторые бесполезные функции) отсюда:<br /><a href="https://github.com/MasterFocus/AutoHotkey/blob/912011380caf37a690ff911d9ded388f4ada2f4e/Functions/GDI%2B%20ImageSearch/Gdip_FastImageSearch.ahk">https://github.com/MasterFocus/AutoHotk … Search.ahk</a><br />Cкрипт делает 10 снимков экрана и <br />1) ищет &quot;needle.bmp&quot; в координатах x1: = 0, y1: = 0, x2: = 1920, y2: = 1080.<br />2) ищет needle.png с прозрачным белым цветом и вариацией 10.<br />3) ищет все совпадения needle.bmp.<br />Также можно изменить направление поиска SearchDirection.<br />1 = left-&gt;right, top-&gt;bottom | 2 = left-&gt;right, bottom-&gt;top | 3 = right-&gt;left, bottom-&gt;top | 4 = right-&gt;left, top-&gt;bottom<br /></p><div class="codebox"><pre><code>GoSub, StartSection
oNeedles := [needle1 := {path:&quot;needle.bmp&quot;}, needle2 := {path: &quot;needle.png&quot;, trans: 0xffffff}]
GoSub, createNeedle
return

f11::
loop 10
{
   tooltip % A_Index
   loop
   {
      VarSetCapacity(DXGI_OUTDUPL_FRAME_INFO, 48, 0)
      AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, INFINITE := 0xFFFFFFFF, &amp;DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
      LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, &quot;int64&quot;)
      if (LastPresentTime != 0)
      {
         if (DesktopImageInSystemMemory = 1)
         {
            VarSetCapacity(DXGI_MAPPED_RECT, A_PtrSize*2, 0)
            IDXGIOutputDuplication_MapDesktopSurface(Duplication, &amp;DXGI_MAPPED_RECT)
            haystack.Stride := NumGet(DXGI_MAPPED_RECT, 0, &quot;int&quot;)
            haystack.Scan := NumGet(DXGI_MAPPED_RECT, A_PtrSize, &quot;ptr&quot;)
         }
         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, &amp;D3D11_MAPPED_SUBRESOURCE)
            haystack.Scan := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, &quot;ptr&quot;)
            haystack.Stride := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, &quot;uint&quot;)
         }

         if !Gdip_FastImageSearch(Haystack, needle1, 0, 0, 1920, 1080)
            msgbox % &quot;needle1:`n&quot; needle1.x &quot; - &quot; needle1.y

         if !Gdip_FastImageSearch(Haystack, needle2, 0, 0, 1920, 1080, variation := 10, SearchDirection := 2)
            msgbox % &quot;needle2:`n&quot; needle2.x &quot; - &quot; needle2.y

         list := Gdip_FastImageSearchList(Haystack, needle1, 0, 0, 1920, 1080)
         loop % list.count
            msgbox % &quot;needleList:`n&quot; list.x[A_Index] &quot; - &quot; 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 = &quot;DXGI_ERROR_NOT_FOUND&quot;)
         break
      VarSetCapacity(DXGI_OUTPUT_DESC, 88+A_PtrSize, 0)
      IDXGIOutput_GetDesc(IDXGIOutput, &amp;DXGI_OUTPUT_DESC)
      width := NumGet(DXGI_OUTPUT_DESC, 72, &quot;int&quot;)
      height := NumGet(DXGI_OUTPUT_DESC, 76, &quot;int&quot;)
      AttachedToDesktop := NumGet(DXGI_OUTPUT_DESC, 80, &quot;int&quot;)
      if (AttachedToDesktop = 1)
         break 2
      ObjRelease(IDXGIOutput)  
   }
   ObjRelease(IDXGIAdapter)
}
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, &amp;DXGI_OUTDUPL_DESC)
DesktopImageInSystemMemory := NumGet(DXGI_OUTDUPL_DESC, 32, &quot;uint&quot;)
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, &quot;uint&quot;)   ; Width
NumPut(height, D3D11_TEXTURE2D_DESC, 4, &quot;uint&quot;)   ; Height
NumPut(1, D3D11_TEXTURE2D_DESC, 8, &quot;uint&quot;)   ; MipLevels
NumPut(1, D3D11_TEXTURE2D_DESC, 12, &quot;uint&quot;)   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, &quot;uint&quot;)   ; Format 
NumPut(1, D3D11_TEXTURE2D_DESC, 20, &quot;uint&quot;)   ; SampleDescCount
NumPut(0, D3D11_TEXTURE2D_DESC, 24, &quot;uint&quot;)   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, &quot;uint&quot;)   ; Usage
NumPut(0, D3D11_TEXTURE2D_DESC, 32, &quot;uint&quot;)   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, D3D11_TEXTURE2D_DESC, 36, &quot;uint&quot;)   ; CPUAccessFlags
NumPut(0, D3D11_TEXTURE2D_DESC, 40, &quot;uint&quot;)   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &amp;D3D11_TEXTURE2D_DESC, 0, staging_tex)
haystack := {}
DllCall(&quot;LoadLibrary&quot;, &quot;str&quot;, &quot;gdiplus&quot;)
VarSetCapacity(si, 8+2*A_PtrSize, 0)
NumPut(0x1, si, &quot;uint&quot;)
DllCall(&quot;gdiplus\GdiplusStartup&quot;, &quot;ptr*&quot;, pToken, &quot;ptr&quot;, &amp;si, &quot;ptr&quot;, 0)
return

createNeedle:
for index, oNeedle in oNeedles
{
   DllCall(&quot;gdiplus\GdipCreateBitmapFromFile&quot;, &quot;wstr&quot;, oNeedle.path, &quot;ptr*&quot;, pBitmap%index%)
   DllCall(&quot;gdiplus\GdipGetImageWidth&quot;, &quot;ptr&quot;, pBitmap%index%, &quot;uint*&quot;, width%index%)
   DllCall(&quot;gdiplus\GdipGetImageHeight&quot;, &quot;ptr&quot;, pBitmap%index%, &quot;uint*&quot;, height%index%)
   VarSetCapacity(Rect%index%, 16, 0)
   NumPut(width%index%, Rect%index%, 8, &quot;uint&quot;)
   NumPut(height%index%, Rect%index%, 12, &quot;uint&quot;)
   VarSetCapacity(BitmapData%index%, 16+2*A_PtrSize, 0)
   DllCall(&quot;gdiplus\GdipBitmapLockBits&quot;, &quot;ptr&quot;, pBitmap%index%, &quot;ptr&quot;, &amp;Rect%index%, &quot;uint&quot;, ReadWrite := 3, &quot;int&quot;, Format32bppArgb := 2498570, &quot;ptr&quot;, &amp;BitmapData%index%)
   Stride%index% := NumGet(BitmapData%index%, 8, &quot;int&quot;)
   Scan%index% := NumGet(BitmapData%index%, 16, &quot;ptr&quot;)
   if oNeedle.trans
   {
      if !MCode_SetBmpTrans
         MCode_SetBmpTrans := MCode(&quot;2,x86:VVdWU4PsBIt0JCyLTCQgi2wkGItEJByLfCQki1QkKMcGAAAAAIXJfmeFwH5jjUyFADH2MduNdgCJHCSNRDUA6w6NtCYAAAAAg8AEOcF0MQ+2WgI4WAJ18A+2WgE4WAF15w+2GjgYdeCLXCQsxkADAIPABIMDATnBddWNtgAAAACLHCQB+QH+g8MBOVwkIHWog8QEMcBbXl9dww==,x64:VlNIi1wkQMcDAAAAAInQSItUJDhFhcB+e4XAfndNY9lEjUj/SPfYSo1MiQRMjRSFAAAAAEUxyWYPH4QAAAAAAEmNBArrE2YuDx+EAAAAAABIg8AESDnIdC8PtnICQDhwAnXtD7ZyAUA4cAF14w+2MkA4MHXbxkADAEiDwASDAwFIOch11A8fAEGDwQFMAdlFOch1rDHAW17D&quot;)
      VarSetCapacity(TransColor, 4)
      NumPut(oNeedle.trans, TransColor, 0, &quot;int&quot;)
      E := DllCall(MCode_SetBmpTrans, &quot;ptr&quot;, Scan%index%, &quot;int&quot;, width%index%, &quot;int&quot;, height%index%, &quot;int&quot;, Stride%index%, &quot;ptr&quot;, &amp;TransColor, &quot;int*&quot;, MCount, &quot;cdecl int&quot;)
   }
   oNeedle.width := width%index%, oNeedle.height := height%index%, oNeedle.pBitmap := pBitmap%index%, oNeedle.BitmapData := &amp;BitmapData%index%, oNeedle.Scan := Scan%index%, oNeedle.Stride := Stride%index%
}
return

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(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;DXGI&quot;)
      DllCall(&quot;LoadLibrary&quot;,&quot;str&quot;,&quot;DXGI&quot;)
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;D3D11&quot;)
      DllCall(&quot;LoadLibrary&quot;,&quot;str&quot;,&quot;D3D11&quot;)
   GUID(riid, &quot;{7b7166ec-21c7-44ae-b21a-c9ae321ae369}&quot;)
   hr := DllCall(&quot;DXGI\CreateDXGIFactory1&quot;, &quot;ptr&quot;, &amp;riid, &quot;ptr*&quot;, ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return ppFactory
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

GUID(ByRef GUID, sGUID)
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall(&quot;ole32\CLSIDFromString&quot;, &quot;WStr&quot;, sGUID, &quot;Ptr&quot;, &amp;GUID) &gt;= 0 ? &amp;GUID : &quot;&quot;
}

_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 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition exclusively for these users:
; - tic , Rseding91 , guest3456
;
;**********************************************************************************
;
;   Search direction:
;   0 = auto detect best direction [default]
;   1 = left-&gt;right, top-&gt;bottom ;; 2 = left-&gt;right, bottom-&gt;top
;   3 = right-&gt;left, bottom-&gt;top ;; 4 = right-&gt;left, top-&gt;bottom

Gdip_FastImageSearch(haystack, needle, x1, y1, x2, y2, Variation=0, SearchDirection=1)
{
   static MCode_ImageSearch1, MCode_ImageSearch2
   if !MCode_ImageSearch1
   {
      MCode_ImageSearch1 := MCode(&quot;2,x86:VVdWU4PsNItcJFiLRCR0OUQkbA+NaQEAAI1D/4ndiUQkCItEJFyNcP+LRCRsD69EJGCJdCQgiUQkHItEJGwB8A+vRCRgD690JGSJRCQki0QkaIl0JCgB2MHgAolEJCyLRCRoweACiUQkMItEJFSNBJiJRCQMi0QkcDlEJGgPjeAAAACLRCQwiUQkEItEJCyJRCQEi0QkaIkEJI22AAAAAIN8JHwBD4TdAQAAg3wkfAIPhHICAACDfCR8Aw+EHwEAAIN8JHwED4XtAAAAi0QkXIXAD47hAAAAi0QkBANEJFAx2zH/iUQkFIt0JByLTCQIhckPiKwAAACLRCQMi1QkFIlcJBgB2AHy6xqNtgAAAACAeP8AdTKD6QGD6ASD6gSD+f90fA+2Wv44WP514w+2Wv04WP112g+2Wvw4WPx014B4/wB00Y12AIMEJAGLBCSDRCQEBINEJBAEOUQkcA+FPf///4t8JGCDRCRsAQF8JByLRCRsAXwkJDlEJHQPhfP+//+LRCRIxwD/////i0QkTMcA/////7j/////6zGNdgCLXCQYg8cBA1wkZAN0JGA5fCRcD4Uz////i0QkSIs0JIt8JGyJMItEJEyJODHAg8Q0W15fXcONtCYAAAAAjXYAi3wkIIX/eNGLRCQEA0QkUIt0JCSLXCQoiUQkFItMJAiFyXhoi0QkDItUJBSJXCQYAdgB8usijbQmAAAAAI12AIB4/wAPhR7///+D6QGD6ASD6gSD+f90MA+2Wv44WP513w+2Wv04WP111g+2Wvw4WPx1zYPpAYPoBIPqBIP5/3XXjbQmAAAAAItcJBiD7wErXCRkK3QkYIP//3WA6Tj///+NtCYAAAAAi0wkXIXJD44l////i0QkEANEJFAx2zH/iUQkFIt0JByLTCQUi0QkVI0UMQHYMcmF7X5RiVwkGOsejbQmAAAAAIB4AwAPhXb+//+DwQGDwASDwgQ5zXQpD7ZaAjhYAnXgD7ZaAThYAXXXD7YaOBh10IPBAYPABIPCBDnNddqNdgCLXCQYg8cBA1wkZAN0JGA5fCRcdYvpl/7//422AAAAAItUJCCF0g+Ihf7//4tEJBADRCRQi3QkJItcJCiJRCQUi3wkIItMJBSLRCRUjRQxAdgxyYXtfk2JXCQY6xqNdgCAeAMAD4XW/f//g8EBg8AEg8IEOc10KQ+2WgI4WAJ14A+2WgE4WAF11w+2GjgYddCDwQGDwASDwgQ5zXXajXYAi1wkGIPvAStcJGQrdCRgg///dZDp+P3//w==,x64:QVdBVkFVQVRVV1ZTSIPsKIusJJgAAABEi5wk2AAAAIuEJMgAAABIiUwkcEyJxkyJy0iJVCR4OYQkuAAAAA+NfgEAAIuEJJAAAACNTf+JTCQURI1A/4uEJLgAAAAPr4QkoAAAAEKNPIUAAAAASGP/iUQkEIuEJLgAAAAByA+vhCSgAAAAD6+MJKgAAACJRCQYRInASY1EgQSJTCQcSIlEJAiLhCTAAAAAOYQksAAAAA+N4QAAAESLjCSwAAAARIuUJLAAAABFAcEPH4QAAAAAAEGD+wEPhBYCAABBg/sCD4TMAgAAQYP7Aw+EQgEAAEGD+wQPhQoBAACF7Q+OAgEAAEaNNI0AAAAARItsJBBFMeRFMf9NY/ZFhcAPiMYAAABJY8RJY9VEiWQkBESJwUgB+EwB8kgB2EgB8usfDx9EAACAeAMAdTqD6QFIg+gESIPqBIP5/w+EhgAAAEQPtmICRDhgAnXbRA+2YgFEOGABddBED7YiRDggdM2AeAMAdMeQQYPCAUGDwQFEOZQkwAAAAA+FOv///4uMJKAAAACDhCS4AAAAAQFMJBCLhCS4AAAAAUwkGDmEJMgAAAAPheD+//9Ii0QkcMcA/////0iLRCR4xwD/////uP/////rPGaQRItkJARBg8cBRAOkJKgAAABEA6wkoAAAAEQ5/Q+FFP///0iLRCRwi7wkuAAAAESJEEiLRCR4iTgxwEiDxChbXl9dQVxBXUFeQV/DDx9EAABEi3wkFEWF/3jIRo00jQAAAABEi2wkGESLZCQcTWP2RYXAeHFJY8RJY9VEiWQkBESJwUgB+EwB8kgB2EgB8usagHgDAA+FBv///4PpAUiD6ARIg+oEg/n/dDZED7ZiAkQ4YAJ120QPtmIBRDhgAXXQRA+2IkQ4IHXHg+kBSIPoBEiD6gSD+f910Q8fgAAAAABEi2QkBEGD7wFEK6QkqAAAAEQrrCSgAAAAQYP//w+FbP///+ka////Dx+EAAAAAACF7Q+OCv///0aNNJUAAAAARItsJBBFMeRFMf9NY/aLlCSQAAAAhdJ+bElj1UljzESJZCQETAHySI0EC0gDTCQISAHy6xoPHwCAeAMAD4U+/v//SIPABEiDwgRIOcF0MUQPtmICRDhgAnXeRA+2YgFEOGABddNED7YiRDggdcpIg8AESIPCBEg5wXXUDx9EAABEi2QkBEGDxwFEA6QkqAAAAEQDrCSgAAAARDn9D4Vs////6Vv+//9mDx+EAAAAAABEi3wkFEWF/w+IRP7//0aNNJUAAAAARItsJBhEi2QkHE1j9ouEJJAAAACFwH5vSWPVSWPMRIlkJARMAfJIjQQLSANMJAhIAfLrHWYPH0QAAIB4AwAPhXb9//9Ig8AESIPCBEg5wXQxRA+2YgJEOGACdd5ED7ZiAUQ4YAF100QPtiJEOCB1ykiDwARIg8IESDnBddQPH0QAAESLZCQEQYPvAUQrpCSoAAAARCusJKAAAABBg///D4Vo////6ZL9//8=&quot;)
      MCode_ImageSearch2 := MCode(&quot;2,x86:VVdWU4PsWIu8JJwAAACLhCSoAAAAi5wkmAAAADmcJJAAAAAPjY8CAACLjCSIAAAAi7QkpAAAAIn9i1wkeA+vyI0UtQAAAACLdCR4A4QkkAAAAA+vhCSEAAAAAdEBzgHQA0QkdIl0JEyNdAsDi4wkgAAAAIl0JDiLdCR8iUQkIIuEJJAAAACNXv+LtCSQAAAAiVwkGA+vtCSEAAAAjVn/AdgPr4QkhAAAAIlcJEAPr5wkiAAAAIl0JDyLdCR8iUQkRItEJHwDhCSMAAAAiVwkSMHgAolEJFSLhCSMAAAAweACiUQkUItEJHiNBLCJRCQwuAEAAAAp8IlEJCiLhCSUAAAAOYQkjAAAAA+NegEAAItEJEyLvCSMAAAAD7YAiUQkHItEJBgBxwOEJJQAAACJRCQsi0QkUIk8JIlEJASLRCRUiUQkCI12AItEJCgDBCSLfCQEi0wkHIlEJCSLRCQgD7YEOI0UKDnRfwYp6DnBfQ2LRCQ4gDgAD4XxAAAAg7wkoAAAAAEPhH0CAACDvCSgAAAAAg+ETwMAAIO8JKAAAAADD4SBAQAAg7wkoAAAAAQPhU8BAACLhCSAAAAAhcAPjkABAACLRCQ8x0QkFAAAAADHRCQMAAAAAIlEJBCLRCQIA0QkdIlEJDSLXCQYhdsPiOQAAACLRCQwi0wkNANEJBQDTCQQ6xyNtCYAAAAAjXYAg+sBg+gEg+kEg/v/D4S2AAAAD7ZR/g+2cP6NPCo5/n83Keo51nwxD7ZR/Q+2cP2NPCo5/n8iKeo51nwcD7ZR/A+2cPyNPCo5/n8NKeo51n2vjbQmAAAAAIB4/wB0ooMEJAGLBCSDRCQIBINEJAQEOUQkLA+Fv/7//4u8JIQAAACDhCSQAAAAAQF8JDyLhCSQAAAAAXwkIAF8JEQ5hCSYAAAAD4VD/v//i0QkbMcA/////4tEJHDHAP////+4/////+tKjXQmAJCDRCQMAYu8JIgAAACLnCSEAAAAAXwkFAFcJBCLRCQMOYQkgAAAAA+F5P7//4tEJGyLfCQkiTiLRCRwi7wkkAAAAIk4McCDxFhbXl9dw412AItEJECFwHjUi3wkRItcJEiJRCQMi0QkCANEJHSJfCQQiVwkFIlEJDSLXCQYhdsPiHwAAACLRCQwi0wkNANEJBQDTCQQ6xKD6wGD6ASD6QSD+/90XI10JgAPtlH+D7Zw/o08Kjn+fzEp6jnWfCsPtlH9D7Zw/Y08Kjn+fxwp6jnWfBYPtlH8D7Zw/I08Kjn+fwcp6jnWfa+QgHj/AA+FpP7//4PrAYPoBIPpBIP7/3Wog2wkDAGLRCQMi7QkiAAAAIucJIQAAAApdCQUKVwkEIP4/w+FUP///+n//v//jXYAi7wkgAAAAIX/D47t/v//i0QkPMdEJBQAAAAAx0QkDAAAAACJRCQQi0QkBANEJHSJRCQ0i3QkfItEJBQx24tMJDQDRCR4A0wkEIX2flyNdgAPtlECD7ZwAo08Kjn+fzEp6jnWfCsPtlEBD7ZwAY08Kjn+fxwp6jnWfBYPthEPtjCNPCo5/n8JKeo51n0NjXYAgHgDAA+FzP3//4PDAYPABIPBBDlcJHx1p4ucJIgAAACDRCQMAQFcJBSLRCQMi5wkhAAAAAFcJBA5hCSAAAAAD4Ve////6SL+//+NtgAAAACLTCRAhckPiBD+//+LRCREiUQkEItEJEiJRCQUi0QkQIlEJAyLRCQEA0QkdIlEJDSLVCR8i0QkFDHbi0wkNANEJHgDTCQQhdJ+X422AAAAAA+2UQIPtnACjTwqOf5/MSnqOdZ8Kw+2UQEPtnABjTwqOf5/HCnqOdZ8Fg+2EQ+2MI08Kjn+fwkp6jnWfQ2NdgCAeAMAD4Xs/P//g8MBg8AEg8EEOVwkfHWng2wkDAGLRCQMi5wkiAAAAIu0JIQAAAApXCQUKXQkEIP4/w+FX////+lG/f//,x64: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&quot;)
   }

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

MCode(mcode)
{
  static e := {1:4, 2:1}, c := (A_PtrSize=8) ? &quot;x64&quot; : &quot;x86&quot;
  if (!regexmatch(mcode, &quot;^([0-9]+),(&quot; c &quot;:|.*?,&quot; c &quot;:)([^,]+)&quot;, m))
    return
  if (!DllCall(&quot;crypt32\CryptStringToBinary&quot;, &quot;str&quot;, m3, &quot;uint&quot;, 0, &quot;uint&quot;, e[m1], &quot;ptr&quot;, 0, &quot;uint*&quot;, s, &quot;ptr&quot;, 0, &quot;ptr&quot;, 0))
    return
  p := DllCall(&quot;GlobalAlloc&quot;, &quot;uint&quot;, 0, &quot;ptr&quot;, s, &quot;ptr&quot;)
  if (c=&quot;x64&quot;)
    DllCall(&quot;VirtualProtect&quot;, &quot;ptr&quot;, p, &quot;ptr&quot;, s, &quot;uint&quot;, 0x40, &quot;uint*&quot;, op)
  if (DllCall(&quot;crypt32\CryptStringToBinary&quot;, &quot;str&quot;, m3, &quot;uint&quot;, 0, &quot;uint&quot;, e[m1], &quot;ptr&quot;, p, &quot;uint*&quot;, s, &quot;ptr&quot;, 0, &quot;ptr&quot;, 0))
    return p
  DllCall(&quot;GlobalFree&quot;, &quot;ptr&quot;, p)
}</code></pre></div><p>Чтобы проверить какой получается снимок с экрана нужно поставить следующий код перед Gdip_FastImageSearch().<br />Снимок сохранится в test.bmp.<br /></p><div class="codebox"><pre><code>DllCall(&quot;gdiplus\GdipGetImageEncodersSize&quot;, &quot;uint*&quot;, count, &quot;uint*&quot;, size)
VarSetCapacity(ci, size)
DllCall(&quot;gdiplus\GdipGetImageEncoders&quot;, &quot;uint&quot;, count, &quot;uint&quot;, size, &quot;ptr&quot;, &amp;ci)
Loop % count
{
   EncoderExtensions := StrGet(NumGet(ci, (idx:=(48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize, &quot;ptr&quot;), &quot;utf-16&quot;)
   if InStr(EncoderExtensions, &quot;*.bmp&quot;)
   {
      pCodec := &amp;ci + idx
      break
   }
}
DllCall(&quot;gdiplus\GdipCreateBitmapFromScan0&quot;, &quot;int&quot;, width, &quot;int&quot;, height, &quot;int&quot;, haystack.stride, &quot;int&quot;, Format32bppArgb := 2498570, &quot;ptr&quot;, haystack.scan, &quot;ptr*&quot;, pBitmap)
DllCall(&quot;gdiplus\GdipSaveImageToFile&quot;, &quot;ptr&quot;, pBitmap, &quot;wstr&quot;, &quot;test.bmp&quot;, &quot;ptr&quot;, pCodec, &quot;uint&quot;, 0)
DllCall(&quot;gdiplus\GdipDisposeImage&quot;, &quot;ptr&quot;, pBitmap)
msgbox done
ExitApp</code></pre></div><p>Для поиска использовал следующие c++ функции:<br /></p><div class="codebox"><pre><code>int Gdip_ImageSearch1(int * Foundx, int * Foundy, unsigned char * HayStack, unsigned char * Needle, int nw, int nh, int Stride1, int Stride2, int sx1, int sy1, int sx2, int sy2, int v, int sd, int suX, int suY)
{
	int y1, y2, x1, x2, tx, ty;
	
	for (y1 = sy1; y1 &lt; sy2; y1++)
	{
		for (x1 = sx1; x1 &lt; sx2; x1++)
		{
			if (sd == 1){
				ty = y1;
				for (y2 = 0; y2 &lt; nh; y2++)
				{
					tx = x1;
					for (x2 = 0; x2 &lt; nw; x2++)
					{
						if (Needle[(4*x2)+(y2*Stride2)+2] == HayStack[(4*tx)+(ty*Stride1)+2]
						&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] == HayStack[(4*tx)+(ty*Stride1)+1]
						&amp;&amp; Needle[(4*x2)+(y2*Stride2)] == HayStack[(4*tx)+(ty*Stride1)]
						|| Needle[(4*x2)+(y2*Stride2)+3] == 0)
							tx++;
						else
							goto NoMatch;
					}
					ty++;
				}
			} else if (sd == 2){
				ty = y1 + nh - 1;
				for (y2 = nh - 1; y2 &gt; -1; y2--)
				{
					tx = x1;
					for (x2 = 0; x2 &lt; nw; x2++)
					{
						if (Needle[(4*x2)+(y2*Stride2)+2] == HayStack[(4*tx)+(ty*Stride1)+2]
						&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] == HayStack[(4*tx)+(ty*Stride1)+1]
						&amp;&amp; Needle[(4*x2)+(y2*Stride2)] == HayStack[(4*tx)+(ty*Stride1)]
						|| Needle[(4*x2)+(y2*Stride2)+3] == 0)
							tx++;
						else
							goto NoMatch;
					}
					ty--;
				}
			} else if (sd == 3){
				ty = y1 + nh - 1;
				for (y2 = nh - 1; y2 &gt; -1; y2--)
				{
					tx = x1 + nw - 1;
					for (x2 = nw - 1; x2 &gt; -1; x2--)
					{
						if (Needle[(4*x2)+(y2*Stride2)+2] == HayStack[(4*tx)+(ty*Stride1)+2]
						&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] == HayStack[(4*tx)+(ty*Stride1)+1]
						&amp;&amp; Needle[(4*x2)+(y2*Stride2)] == HayStack[(4*tx)+(ty*Stride1)]
						|| Needle[(4*x2)+(y2*Stride2)+3] == 0)
							tx--;
						else
							goto NoMatch;
					}
					ty--;
				}
			} else if (sd == 4){
				ty = y1;
				for (y2 = 0; y2 &lt; nh; y2++)
				{
					tx = x1 + nw - 1;
					for (x2 = nw - 1; x2 &gt; -1; x2--)
					{
						if (Needle[(4*x2)+(y2*Stride2)+2] == HayStack[(4*tx)+(ty*Stride1)+2]
						&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] == HayStack[(4*tx)+(ty*Stride1)+1]
						&amp;&amp; Needle[(4*x2)+(y2*Stride2)] == HayStack[(4*tx)+(ty*Stride1)]
						|| Needle[(4*x2)+(y2*Stride2)+3] == 0)
							tx--;
						else
							goto NoMatch;
					}
					ty++;
				}
			}
			
			Foundx[0] = x1; Foundy[0] = y1;
			return 0;
			NoMatch:;
		}
	}
	
	Foundx[0] = -1; Foundy[0] = -1;
	return -1;
}




int Gdip_ImageSearch2(int * Foundx, int * Foundy, unsigned char * HayStack, unsigned char * Needle, int nw, int nh, int Stride1, int Stride2, int sx1, int sy1, int sx2, int sy2, int v, int sd, int suX, int suY)
{
	int y1, y2, x1, x2, tx, ty;
	
	for (y1 = sy1; y1 &lt; sy2; y1++)
	{
		for (x1 = sx1; x1 &lt; sx2; x1++)
		{
			if (Needle[(4*suX)+(suY*Stride2)] &lt;= HayStack[(4*(x1 + suX))+((y1 + suY)*Stride1)]+v
			&amp;&amp; Needle[(4*suX)+(suY*Stride2)] &gt;= HayStack[(4*(x1 + suX))+((y1 + suY)*Stride1)]-v
			|| Needle[(4*suX)+(suY*Stride2)+3] == 0)
			{
				if (sd == 1){
					ty = y1;
					for (y2 = 0; y2 &lt; nh; y2++)
					{
						tx = x1;
						for (x2 = 0; x2 &lt; nw; x2++)
						{
							if (Needle[(4*x2)+(y2*Stride2)+2] &lt;= HayStack[(4*tx)+(ty*Stride1)+2]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+2] &gt;= HayStack[(4*tx)+(ty*Stride1)+2]-v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] &lt;= HayStack[(4*tx)+(ty*Stride1)+1]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] &gt;= HayStack[(4*tx)+(ty*Stride1)+1]-v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)] &lt;= HayStack[(4*tx)+(ty*Stride1)]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)] &gt;= HayStack[(4*tx)+(ty*Stride1)]-v
							|| Needle[(4*x2)+(y2*Stride2)+3] == 0)
								tx++;
							else
								goto NoMatch;
						}
						ty++;
					}
				} else if (sd == 2){
					ty = y1 + nh - 1;
					for (y2 = nh - 1; y2 &gt; -1; y2--)
					{
						tx = x1;
						for (x2 = 0; x2 &lt; nw; x2++)
						{
							if (Needle[(4*x2)+(y2*Stride2)+2] &lt;= HayStack[(4*tx)+(ty*Stride1)+2]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+2] &gt;= HayStack[(4*tx)+(ty*Stride1)+2]-v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] &lt;= HayStack[(4*tx)+(ty*Stride1)+1]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] &gt;= HayStack[(4*tx)+(ty*Stride1)+1]-v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)] &lt;= HayStack[(4*tx)+(ty*Stride1)]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)] &gt;= HayStack[(4*tx)+(ty*Stride1)]-v
							|| Needle[(4*x2)+(y2*Stride2)+3] == 0)
								tx++;
							else
								goto NoMatch;
						}
						ty--;
					}
				} else if (sd == 3){
					ty = y1 + nh - 1;
					for (y2 = nh - 1; y2 &gt; -1; y2--)
					{
						tx = x1 + nw - 1;
						for (x2 = nw - 1; x2 &gt; -1; x2--)
						{
							if (Needle[(4*x2)+(y2*Stride2)+2] &lt;= HayStack[(4*tx)+(ty*Stride1)+2]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+2] &gt;= HayStack[(4*tx)+(ty*Stride1)+2]-v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] &lt;= HayStack[(4*tx)+(ty*Stride1)+1]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] &gt;= HayStack[(4*tx)+(ty*Stride1)+1]-v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)] &lt;= HayStack[(4*tx)+(ty*Stride1)]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)] &gt;= HayStack[(4*tx)+(ty*Stride1)]-v
							|| Needle[(4*x2)+(y2*Stride2)+3] == 0)
								tx--;
							else
								goto NoMatch;
						}
						ty--;
					}
				} else if (sd == 4){
					ty = y1;
					for (y2 = 0; y2 &lt; nh; y2++)
					{
						tx = x1 + nw - 1;
						for (x2 = nw - 1; x2 &gt; -1; x2--)
						{
							if (Needle[(4*x2)+(y2*Stride2)+2] &lt;= HayStack[(4*tx)+(ty*Stride1)+2]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+2] &gt;= HayStack[(4*tx)+(ty*Stride1)+2]-v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] &lt;= HayStack[(4*tx)+(ty*Stride1)+1]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)+1] &gt;= HayStack[(4*tx)+(ty*Stride1)+1]-v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)] &lt;= HayStack[(4*tx)+(ty*Stride1)]+v
							&amp;&amp; Needle[(4*x2)+(y2*Stride2)] &gt;= HayStack[(4*tx)+(ty*Stride1)]-v
							|| Needle[(4*x2)+(y2*Stride2)+3] == 0)
								tx--;
							else
								goto NoMatch;
						}
						ty++;
					}
				}
			} else
				continue;
			
			Foundx[0] = x1; Foundy[0] = y1;
			return 0;
			NoMatch:;
		}
	}
	
	Foundx[0] = -1; Foundy[0] = -1;
	return -1;
}


int Gdip_SetBitmapTransColor(unsigned char * Scan, int Width, int Height, int Stride, unsigned char * Trans, int * MCount)
{
    int x1, y1, index;
    MCount[0] = 0;
    for (y1 = 0; y1 &lt; Height; y1++) {
        for (x1 = 0; x1 &lt; Width; x1++) {
            index = (4*x1)+(y1*Stride);
            if ( Scan[index+2] == Trans[2]
            &amp;&amp;   Scan[index+1] == Trans[1]
            &amp;&amp;   Scan[index+0] == Trans[0] ) {
                Scan[index+3] = 0;
                MCount[0]++;
            }
        }
    }
    return 0;
}</code></pre></div><p><a href="http://forum.script-coding.com/viewtopic.php?id=15719">Тема для обсуждения</a></p>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Sun, 12 Mar 2023 14:52:57 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=157116#p157116</guid>
		</item>
	</channel>
</rss>
