Yes that may be true.
AHK source code:
Code: Select all
BYTE red, green, blue;
BYTE search_red, search_green, search_blue;
BYTE red_low, green_low, blue_low, red_high, green_high, blue_high;
// The following loop is very similar to its counterpart above that finds an exact match, so maintain
// them together and see above for more detailed comments about it.
for (i = 0; i < screen_pixel_count; ++i)
{
// The following is commented out to trade code size reduction for performance (see comment above).
//red = GetBValue(screen_pixel[i]); // Because it's RGB vs. BGR, the B value is fetched, not R (though it doesn't matter as long as everything is internally consistent here).
//green = GetGValue(screen_pixel[i]);
//blue = GetRValue(screen_pixel[i]);
//if ((red >= red_low1 && red <= red_high1
// && green >= green_low1 && green <= green_high1
// && blue >= blue_low1 && blue <= blue_high1 // All three color components are a match, so this screen pixel matches the image's first pixel.
// || image_mask && image_mask[0] // Or: It's an icon's transparent pixel, which matches any color.
// || image_pixel[0] == trans_color) // This should be okay even if trans_color==CLR_NONE, since CLR none should never occur naturally in the image.
// && image_height <= screen_height - i/screen_width // Image is short enough to fit in the remaining rows of the search region.
// && image_width <= screen_width - i%screen_width) // Image is narrow enough not to exceed the right-side boundary of the search region.
// Instead of the above, only this abbreviated check is done:
if (image_height <= screen_height - i/screen_width // Image is short enough to fit in the remaining rows of the search region.
&& image_width <= screen_width - i%screen_width) // Image is narrow enough not to exceed the right-side boundary of the search region.
{
// Since the first pixel is a match, check the other pixels.
for (found = true, x = 0, y = 0, j = 0, k = i; j < image_pixel_count; ++j)
{
search_red = GetBValue(image_pixel[j]);
search_green = GetGValue(image_pixel[j]);
search_blue = GetRValue(image_pixel[j]);
SET_COLOR_RANGE
red = GetBValue(screen_pixel[k]);
green = GetGValue(screen_pixel[k]);
blue = GetRValue(screen_pixel[k]);
if (!(found = red >= red_low && red <= red_high
&& green >= green_low && green <= green_high
&& blue >= blue_low && blue <= blue_high
|| image_mask && image_mask[j] // Or: It's an icon's transparent pixel, which matches any color.
|| image_pixel[j] == trans_color)) // This should be okay even if trans_color==CLR_NONE, since CLR_NONE should never occur naturally in the image.
break; // At least one pixel doesn't match, so this candidate is discarded.
if (++x < image_width) // We're still within the same row of the image, so just move on to the next screen pixel.
++k;
else // We're starting a new row of the image.
{
x = 0; // Return to the leftmost column of the image.
++y; // Move one row downward in the image.
k = i + y*screen_width; // Verified correct.
}
}
if (found) // Complete match found.
break;
}
}
I was not really trying to test autohotkey's ability in this benchmark more trying to benchmark the 2 if comparisons in the hope that this
Code: Select all
if (!(found = red >= red_low && red <= red_high
&& green >= green_low && green <= green_high
&& blue >= blue_low && blue <= blue_high
could be reduced to something like this
Code: Select all
if (!(found = ((unsigned)(red) < red_diff)
&& ((unsigned)(Green) < Green_diff)
&& ((unsigned)(Blue) < Blue_diff)
but do see that a more correct way maybe this
Code: Select all
if (!(found = ((unsigned)(red - red_low) < red_diff)
&& ((unsigned)(Green - Green_low) < Green_diff)
&& ((unsigned)(Blue - Blue_low) < Blue_diff)
the issue with testing that in AHK code is that any of the methods ("I knew at the time") to make the value of
red - red_low unsigned also takes the added time of doing the function call, in the OP code i was hoping to cut that function time out of the benchmark result but do see that this was most likely wrong.
my hope was/is that in c++
(unsigned) is simply a flag, so takes close to no time, where as in ahk it takes some time to do the convert to unsigned
2 examples:
OP code with the math within the timer
Code: Select all
#Persistent
#SingleInstance force
SetBatchLines, -1
f1:: ; speed testing fastest way to determine if an integer is between two integers (inclusive)
time1:=time2:=inrange:=inrange2:="" ; clear variables
lower := 50
upper := 100
InputBox, number, time test, Please Enter a number `n`ni.e 88
diff := (upper-lower)+1
QPX( True ) ; Initialise Counter
loop 2073600 ; loop 1920x1080 times
if (((number-lower) & 0xFFFFFFFF) < diff)
inrange := true
time1 := QPX( false ) ; Retrieve Time consumed ( & reset internal vars )
QPX( True ) ; Initialise Counter
loop 2073600 ; loop 1920x1080 times
if (number >= lower && number <= upper)
inrange2 := true
time2 := QPX( false ) ; Retrieve Time consumed ( & reset internal vars )
msgbox % "First check method:`nIf number " number " is between " lower "-" upper " is " (inrange?"true":"false") " and it took " time1 "`n`nSecond check method:`nIf number " number " is between " lower "-" upper " is " (inrange2?"true":"false") " and it took " time2
return
QPX( N=0 ) { ; Wrapper for QueryPerformanceCounter()by SKAN | CD: 06/Dec/2009
Static F,A,Q,P,X ; www.autohotkey.com/forum/viewtopic.php?t=52083 | LM: 10/Dec/2009
If ( N && !P )
Return DllCall("QueryPerformanceFrequency",Int64P,F) + (X:=A:=0) + DllCall("QueryPerformanceCounter",Int64P,P)
DllCall("QueryPerformanceCounter",Int64P,Q), A:=A+Q-P, P:=Q, X:=X+1
Return ( N && X=N ) ? (X:=X-1)<<64 : ( N=0 && (R:=A/X/F) ) ? ( R + (A:=P:=X:=0) ) : 1
}
Code: Select all
First check method: If number 44 is between 50-100 is false and it took 0.568369
Second check method: If number 44 is between 50-100 is false and it took 0.277781
First check method: If number 88 is between 50-100 is true and it took 0.763220
Second check method: If number 88 is between 50-100 is true and it took 0.757578
First check method: If number 222 is between 50-100 is false and it took 0.589628
Second check method: If number 222 is between 50-100 is false and it took 0.511960
more like what i think is happening in the c++ code
Code: Select all
#Persistent
#SingleInstance force
SetBatchLines, -1
f1:: ; speed testing fastest way to determine if an integer is between two integers (inclusive)
time1:=time2:=inrange:=inrange2:="" ; clear variables
lower := 50
upper := 100
InputBox, number, time test, Please Enter a number `n`ni.e 88
diff := (upper-lower)+1
QPX( True ) ; Initialise Counter
loop 20736 ; loop 1920x1080 times / 100
{
Y := ((number-lower) & 0xFFFFFFFF)
loop 100
if (Y < diff)
inrange := true
}
time1 := QPX( false ) ; Retrieve Time consumed ( & reset internal vars )
QPX( True ) ; Initialise Counter
loop 20736 ; loop 1920x1080 times / 100
loop 100
if (number >= lower && number <= upper)
inrange2 := true
time2 := QPX( false ) ; Retrieve Time consumed ( & reset internal vars )
msgbox % "First check method:`nIf number " number " is between " lower "-" upper " is " (inrange?"true":"false") " and it took " time1 "`n`nSecond check method:`nIf number " number " is between " lower "-" upper " is " (inrange2?"true":"false") " and it took " time2
return
QPX( N=0 ) { ; Wrapper for QueryPerformanceCounter()by SKAN | CD: 06/Dec/2009
Static F,A,Q,P,X ; www.autohotkey.com/forum/viewtopic.php?t=52083 | LM: 10/Dec/2009
If ( N && !P )
Return DllCall("QueryPerformanceFrequency",Int64P,F) + (X:=A:=0) + DllCall("QueryPerformanceCounter",Int64P,P)
DllCall("QueryPerformanceCounter",Int64P,Q), A:=A+Q-P, P:=Q, X:=X+1
Return ( N && X=N ) ? (X:=X-1)<<64 : ( N=0 && (R:=A/X/F) ) ? ( R + (A:=P:=X:=0) ) : 1
}
Code: Select all
First check method: If number 44 is between 50-100 is false and it took 0.292560
Second check method: If number 44 is between 50-100 is false and it took 0.292357
First check method: If number 88 is between 50-100 is true and it took 0.534627
Second check method: If number 88 is between 50-100 is true and it took 0.773438
First check method: If number 222 is between 50-100 is false and it took 0.288689
Second check method: If number 222 is between 50-100 is false and it took 0.521938
to me that last example mimics the pixel/image search code better as it is checking the same image pixel ageist many screen pixels