Si JCHD passe dans le coin, j'ai une question concernant PixelSearch, j'aimerai savoir comment il fonctionne en interne, en effet, après analyse : J'ai voulu faire de même, je récupère bien les octets correspondants aux couleurs, mais je bloque sur la fonction de recherche.
D'un coté je cherche avec DllStructGetData qui est relativement rapide si le pixel à trouver est proche du début de la recherche et d'un autre je cherche avec StringInStr qui est (contre toute attente) beaucoup plus performant que la 1ere solution quand le pixel se trouve vers la fin.
Alors que PixelSearch reste constant à ~40ms quel que soit la position du pixel à trouver.
#include <Color.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StructureConstants.au3>
#include <WinAPI.au3>
#include <WinAPIGdi.au3>
#include <WindowsConstants.au3>
Opt("MustDeclareVars", 1)
Global $color = 0xEF7812
Global $posGui = [[0, 0], [@DesktopWidth - 1, @DesktopHeight - 1]]
Global $gui = GUICreate("", 1, 1, 0, 0, $WS_POPUP)
GUISetBkColor($color, $gui)
GUISetState(@SW_SHOW, $gui)
WinSetOnTop($gui, "", 1)
For $i = 0 To UBound($posGui, 1) - 1
WinMove($gui, "", $posGui[$i][0], $posGui[$i][1])
pixelSearch_PixelSearch(0, 0, @DesktopWidth - 1, @DesktopHeight - 1, $color)
pixelSearch_StringMid(0, 0, @DesktopWidth - 1, @DesktopHeight - 1, $color)
pixelSearch_DLLStructGetData(0, 0, @DesktopWidth - 1, @DesktopHeight - 1, $color)
ConsoleWrite(@CRLF)
Next
Func pixelSearch_PixelSearch($l, $t, $r, $b, $color)
Local $timer = TimerInit()
Local $pos = PixelSearch($l, $t, $r, $b, $color)
If(Not(IsArray($pos))) Then
Dim $pos[2] = [-1, -1]
EndIf
ConsoleWrite("PixelSearch : " & TimerDiff($timer) & " ms" & @CRLF)
ConsoleWrite("Pos : " & $pos[0] & ", " & $pos[1] & @CRLF)
EndFunc
Func pixelSearch_StringMid($l, $t, $r, $b, $color)
Local $timer = TimerInit()
Local $pos = pixelSearch2($l, $t, $r, $b, $color, True)
ConsoleWrite("pixelSearch_StringMid : " & TimerDiff($timer) & " ms" & @CRLF)
ConsoleWrite("Pos : " & $pos[0] & ", " & $pos[1] & @CRLF)
EndFunc
Func pixelSearch_DLLStructGetData($l, $t, $r, $b, $color)
Local $timer = TimerInit()
Local $pos = pixelSearch2($l, $t, $r, $b, $color, False)
ConsoleWrite("pixelSearch_DLLStructGetData : " & TimerDiff($timer) & " ms" & @CRLF)
ConsoleWrite("Pos : " & $pos[0] & ", " & $pos[1] & @CRLF)
EndFunc
Func pixelSearch2($l, $t, $r, $b, $color, $isStringMid)
Local $w = $r - $l + 1
Local $h = $b - $t + 1
Local $hdc = _WinAPI_GetDC(0)
Local $hBmp = _WinAPI_CreateCompatibleBitmap($hdc, $w, $h)
Local $hdc2 = _WinAPI_CreateCompatibleDC($hdc)
Local $oldObj = _WinAPI_SelectObject($hdc2, $hBmp)
Local $ret = _WinAPI_StretchBlt($hdc2, $l, $t, $w, $h, $hdc, $l, $t, $w, $h, $SRCCOPY)
Local $lpBitmapInfo = DllStructCreate($tagBITMAPINFO)
DllStructSetData($lpBitmapInfo, "biSize", 40)
DllStructSetData($lpBitmapInfo, "biWidth", $w)
DllStructSetData($lpBitmapInfo, "biHeight", -1 * $h)
DllStructSetData($lpBitmapInfo, "biPlanes", 1)
DllStructSetData($lpBitmapInfo, "biBitCount", 32)
DllStructSetData($lpBitmapInfo, "biCompression", 0)
DllStructSetData($lpBitmapInfo, "biSizeImage", 0)
DllStructSetData($lpBitmapInfo, "biXPelsPerMeter", 0)
DllStructSetData($lpBitmapInfo, "biYPelsPerMeter", 0)
DllStructSetData($lpBitmapInfo, "biClrUsed", 0)
DllStructSetData($lpBitmapInfo, "biClrImportant", 0)
DllStructSetData($lpBitmapInfo, "biRGBQuad", 0)
$ret = _WinAPI_GetDIBits($hdc2, $hBmp, 0, 0, Null, $lpBitmapInfo, 0)
Local $size = DllStructGetData($lpBitmapInfo, "biSizeImage")
Local $pos = [-1, -1]
If($isStringMid) Then
Local $buffer = DllStructCreate("byte[" & $size & "]")
$ret = _WinAPI_GetDIBits($hdc2, $hBmp, 0, $h, DllStructGetPtr($buffer), $lpBitmapInfo, 0)
Local $scan0 = Hex(DllStructGetData($buffer, 1))
Local $rgb = _ColorGetRGB($color)
Local $search = Hex($rgb[2], 2) & Hex($rgb[1], 2) & Hex($rgb[0], 2) & "FF"
Local $colorPos = 0
Local $max = StringLen($scan0)
Do
$colorPos = StringInStr($scan0, $search, 0, $colorPos + 1)
If($colorPos > $max) Then
$colorPos = 0
EndIf
Until(Mod($colorPos-1, 8) == 0 Or $colorPos = 0)
$colorPos = ($colorPos - 1) / 8
If($colorPos >= 0) Then
$pos[1] = Floor($colorPos / ($w))
$pos[0] = $colorPos - $pos[1] * ($w)
EndIf
Else
Local $buffer = DllStructCreate("int[" & $size/4 & "]")
$ret = _WinAPI_GetDIBits($hdc2, $hBmp, 0, $h, DllStructGetPtr($buffer), $lpBitmapInfo, 0)
$color = BitOR(0xFF000000, $color)
Local $offset
Local $pixel
For $y = 0 To $h - 1
$offset = $y * $w + 1
For $x = 0 To $w - 1
$pixel = DllStructGetData($buffer, 1, $offset + $x)
If($color = $pixel) Then
$pos[0] = $x
$pos[1] = $y
ExitLoop 2
EndIf
Next
Next
EndIf
_WinAPI_SelectObject($hdc2, $oldObj)
_WinAPI_DeleteObject($hBmp)
_WinAPI_DeleteDC($hdc2)
_WinAPI_ReleaseDC(Null, $hdc)
Return $pos
EndFunc
Func quit()
Exit
EndFunc
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StructureConstants.au3>
#include <WinAPI.au3>
#include <WinAPIGdi.au3>
#include <WindowsConstants.au3>
Opt("MustDeclareVars", 1)
Global $color = 0xEF7812
Global $posGui = [[0, 0], [@DesktopWidth - 1, @DesktopHeight - 1]]
Global $gui = GUICreate("", 1, 1, 0, 0, $WS_POPUP)
GUISetBkColor($color, $gui)
GUISetState(@SW_SHOW, $gui)
WinSetOnTop($gui, "", 1)
For $i = 0 To UBound($posGui, 1) - 1
WinMove($gui, "", $posGui[$i][0], $posGui[$i][1])
pixelSearch_PixelSearch(0, 0, @DesktopWidth - 1, @DesktopHeight - 1, $color)
pixelSearch_StringMid(0, 0, @DesktopWidth - 1, @DesktopHeight - 1, $color)
pixelSearch_DLLStructGetData(0, 0, @DesktopWidth - 1, @DesktopHeight - 1, $color)
ConsoleWrite(@CRLF)
Next
Func pixelSearch_PixelSearch($l, $t, $r, $b, $color)
Local $timer = TimerInit()
Local $pos = PixelSearch($l, $t, $r, $b, $color)
If(Not(IsArray($pos))) Then
Dim $pos[2] = [-1, -1]
EndIf
ConsoleWrite("PixelSearch : " & TimerDiff($timer) & " ms" & @CRLF)
ConsoleWrite("Pos : " & $pos[0] & ", " & $pos[1] & @CRLF)
EndFunc
Func pixelSearch_StringMid($l, $t, $r, $b, $color)
Local $timer = TimerInit()
Local $pos = pixelSearch2($l, $t, $r, $b, $color, True)
ConsoleWrite("pixelSearch_StringMid : " & TimerDiff($timer) & " ms" & @CRLF)
ConsoleWrite("Pos : " & $pos[0] & ", " & $pos[1] & @CRLF)
EndFunc
Func pixelSearch_DLLStructGetData($l, $t, $r, $b, $color)
Local $timer = TimerInit()
Local $pos = pixelSearch2($l, $t, $r, $b, $color, False)
ConsoleWrite("pixelSearch_DLLStructGetData : " & TimerDiff($timer) & " ms" & @CRLF)
ConsoleWrite("Pos : " & $pos[0] & ", " & $pos[1] & @CRLF)
EndFunc
Func pixelSearch2($l, $t, $r, $b, $color, $isStringMid)
Local $w = $r - $l + 1
Local $h = $b - $t + 1
Local $hdc = _WinAPI_GetDC(0)
Local $hBmp = _WinAPI_CreateCompatibleBitmap($hdc, $w, $h)
Local $hdc2 = _WinAPI_CreateCompatibleDC($hdc)
Local $oldObj = _WinAPI_SelectObject($hdc2, $hBmp)
Local $ret = _WinAPI_StretchBlt($hdc2, $l, $t, $w, $h, $hdc, $l, $t, $w, $h, $SRCCOPY)
Local $lpBitmapInfo = DllStructCreate($tagBITMAPINFO)
DllStructSetData($lpBitmapInfo, "biSize", 40)
DllStructSetData($lpBitmapInfo, "biWidth", $w)
DllStructSetData($lpBitmapInfo, "biHeight", -1 * $h)
DllStructSetData($lpBitmapInfo, "biPlanes", 1)
DllStructSetData($lpBitmapInfo, "biBitCount", 32)
DllStructSetData($lpBitmapInfo, "biCompression", 0)
DllStructSetData($lpBitmapInfo, "biSizeImage", 0)
DllStructSetData($lpBitmapInfo, "biXPelsPerMeter", 0)
DllStructSetData($lpBitmapInfo, "biYPelsPerMeter", 0)
DllStructSetData($lpBitmapInfo, "biClrUsed", 0)
DllStructSetData($lpBitmapInfo, "biClrImportant", 0)
DllStructSetData($lpBitmapInfo, "biRGBQuad", 0)
$ret = _WinAPI_GetDIBits($hdc2, $hBmp, 0, 0, Null, $lpBitmapInfo, 0)
Local $size = DllStructGetData($lpBitmapInfo, "biSizeImage")
Local $pos = [-1, -1]
If($isStringMid) Then
Local $buffer = DllStructCreate("byte[" & $size & "]")
$ret = _WinAPI_GetDIBits($hdc2, $hBmp, 0, $h, DllStructGetPtr($buffer), $lpBitmapInfo, 0)
Local $scan0 = Hex(DllStructGetData($buffer, 1))
Local $rgb = _ColorGetRGB($color)
Local $search = Hex($rgb[2], 2) & Hex($rgb[1], 2) & Hex($rgb[0], 2) & "FF"
Local $colorPos = 0
Local $max = StringLen($scan0)
Do
$colorPos = StringInStr($scan0, $search, 0, $colorPos + 1)
If($colorPos > $max) Then
$colorPos = 0
EndIf
Until(Mod($colorPos-1, 8) == 0 Or $colorPos = 0)
$colorPos = ($colorPos - 1) / 8
If($colorPos >= 0) Then
$pos[1] = Floor($colorPos / ($w))
$pos[0] = $colorPos - $pos[1] * ($w)
EndIf
Else
Local $buffer = DllStructCreate("int[" & $size/4 & "]")
$ret = _WinAPI_GetDIBits($hdc2, $hBmp, 0, $h, DllStructGetPtr($buffer), $lpBitmapInfo, 0)
$color = BitOR(0xFF000000, $color)
Local $offset
Local $pixel
For $y = 0 To $h - 1
$offset = $y * $w + 1
For $x = 0 To $w - 1
$pixel = DllStructGetData($buffer, 1, $offset + $x)
If($color = $pixel) Then
$pos[0] = $x
$pos[1] = $y
ExitLoop 2
EndIf
Next
Next
EndIf
_WinAPI_SelectObject($hdc2, $oldObj)
_WinAPI_DeleteObject($hBmp)
_WinAPI_DeleteDC($hdc2)
_WinAPI_ReleaseDC(Null, $hdc)
Return $pos
EndFunc
Func quit()
Exit
EndFunc
Code : Tout sélectionner
PixelSearch : 46.5666 ms
Pos : 0, 0
pixelSearch_StringMid : 97.0011 ms
Pos : 0, 0
pixelSearch_DLLStructGetData : 30.6334 ms
Pos : 0, 0
PixelSearch : 36.9423 ms
Pos : 1919, 1079
pixelSearch_StringMid : 1246.8801 ms
Pos : 1919, 1079
pixelSearch_DLLStructGetData : 4511.4611 ms
Pos : 1919, 1079