I understand that for some things it would be better to write certain things in C++, but I\'d really like to be able to do this in AHK:
I want to be able to retrieve
I found a way to do it 103 times faster than Forivin's solution :D
SetBatchLines, -1
CoordMode, Pixel, screen
FileDelete, Log.txt
searchSpace := 400
jumpSize := 1 ; how many units to skip each interval
total := Round(((searchSpace * searchSpace) / jumpSize), 0)
startTimer := getTimestamp()
getPixelMapSlow(searchSpace, jumpSize)
endTimer := getTimestamp()
duration := endTimer - startTimer
rate := total / duration
FileAppend, % "[getPixelMapSlow] Retrieved " . total . " pixels from bitmap, duration: " . duration . "ms at at a rate of " . rate . " pixels/ms.`n", Log.txt
searchSpace := 400
jumpSize := 1 ; how many units to skip each interval
total := Round(((searchSpace * searchSpace) / jumpSize), 0)
startTimer := getTimestamp()
getPixelMapFast(searchSpace, jumpSize)
endTimer := getTimestamp()
duration := endTimer - startTimer
rate := total / duration
FileAppend, % "[getPixelMapFast] Retrieved " . total . " pixels from bitmap, duration: " . duration . "ms at at a rate of " . rate . " pixels/ms.`n", Log.txt
getPixelMapFast(searchSpace, jumpSize){
width := 1920
height := 1080
centerX := width / 2
centerY := height / 2
searchSpacehalf := searchSpace / 2
searchCounterX := 0
searchCounterY := 0
pixelMap := {}
pBitmap := Gdip_BitmapFromScreen((centerX - searchSpacehalf) . "|" . (centerY - searchSpacehalf) . "|" . searchSpace . "|" . searchSpace)
E1 := Gdip_LockBits(pBitmap, 0, 0, Gdip_GetImageWidth(pBitmap), Gdip_GetImageHeight(pBitmap), Stride, Scan0, BitmapData)
Loop, %searchSpace%
{
tick := A_Index * jumpSize
if (tick < searchSpace) {
New_Index_X := tick
Loop, %searchSpace%
{
tick := A_Index * jumpSize
if (tick < searchSpace) {
New_Index_Y := tick
color1ARGB := Gdip_GetLockBitPixel(Scan0, New_Index_X, New_Index_Y, Stride)
SetFormat, Integer, H
color1RGB := 0x00ffffff & color1ARGB
SetFormat, Integer, D
if (!pixelMap[New_Index_X]){
pixelMap[New_Index_X] := {}
}
pixelMap[New_Index_X][New_Index_Y] := color1RGB
}
}
}
}
Gdip_UnlockBits(pBitmap, BitmapData)
Gdip_DisposeImage(pBitmap)
return pixelMap
}
getPixelMapSlow(searchSpace, jumpSize){
width := 1920
height := 1080
centerX := width / 2
centerY := height / 2
searchSpacehalf := searchSpace / 2
searchCounterX := 0
searchCounterY := 0
pixelMap := {}
pBitmap := Gdip_BitmapFromScreen((centerX - searchSpacehalf) . "|" . (centerY - searchSpacehalf) . "|" . searchSpace . "|" . searchSpace)
Loop, %searchSpace%
{
tick := A_Index * jumpSize
if (tick < searchSpace) {
New_Index_X := tick
Loop, %searchSpace%
{
tick := A_Index * jumpSize
if (tick < searchSpace) {
New_Index_Y := tick
color1ARGB := Gdip_GetPixel(pBitmap, New_Index_X, New_Index_Y)
if (!pixelMap[New_Index_X]){
pixelMap[New_Index_X] := {}
}
color1RGB := ARGBtoRGB(color1ARGB)
pixelMap[New_Index_X][New_Index_Y] := color1RGB
}
}
}
}
Gdip_DisposeImage(pBitmap)
return pixelMap
}
ARGBtoRGB( ARGB ) {
VarSetCapacity( RGB,6,0 )
DllCall( "msvcrt.dll\sprintf", Str,RGB, Str,"%06X", UInt,ARGB<<8 )
Return "0x" RGB
}
getTimestamp()
{
DllCall("QueryPerformanceCounter", "Int64*", timestamp)
DllCall("QueryPerformanceFrequency", "Int64*", frequency)
return Round(timestamp * 1000 / frequency)
}
Of course include the relevant functions of the AHK Gdip library (found on Github) in your code for this to work.
Log:
[getPixelMapSlow] Retrieved 160000 pixels from bitmap, duration: 33161ms at at a rate of 4.824945 pixels/ms.
[getPixelMapFast] Retrieved 160000 pixels from bitmap, duration: 321ms at at a rate of 498.442368 pixels/ms.
To reduce delays between commands to a minimum you should also use SetBatchLines, -1
. This alone can give you a significant performance boost.
I think you have already figured out the rest.
But in case anyone else stumbles across this question. Here is how you can do it with GDI+:
SetBatchLines, -1
#Include Gdip.ahk
pToken := Gdip_Startup()
; Screen area ("X|Y|Width|Height")
pBitmap := Gdip_BitmapFromScreen("500|600|300|100")
; Read RGB color from pixel x290 y65
ARGB := Gdip_GetPixel( pBitmap, 290, 65 )
pixelColor := ARGBtoRGB( ARGB )
MsgBox, % pixelColor
; Read RGB color from pixel x167 y90
ARGB := Gdip_GetPixel( pBitmap, 167, 90 )
pixelColor := ARGBtoRGB( ARGB )
MsgBox, % pixelColor
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
ARGBtoRGB( ARGB ) {
VarSetCapacity( RGB,6,0 )
DllCall( "msvcrt.dll\sprintf", Str,RGB, Str,"%06X", UInt,ARGB<<8 )
Return "0x" RGB
}
The code is mostly what I already posted in another answer right here.