Jump to content
Sign in to follow this  

Spooky delay in PixelGetColor?

Recommended Posts


In my script i check a small area (say 20x20 pixels) with looped PixelGetColor. This has worked without any real problems for months and has taken about 20ms to complete.

To test my script, I'm running Photoshop and activate different layers to show different photos. This has also worked great. After a GPU replace (to the better) a week ago it worked great the first few days, but now I've come to a dead end.

This is the deal:

  • I open my .psd file and runs my script - performance is ok
  • I switch to layer 2 and runs my script - performance is ok
  • I switch back to layer 1 and runs my script - performance is horrible, almost 50ms.
  • At this point it doesn't matter what I do, every use of PixelGetColor() is slow.
  • Now, if I close Photoshop completely, reopens my .psd file and run the script again - performance is ok

What could possible be the problem!?

Could it be anything with the new Nvidia drivers - PhysX/hyperthreading and all that new shit (which I didnt use earlier)?

After a search through the forums I've found some interesting stuff making me far from the only one having general performance issues using the PixelGetColor() function.

I'm gonna take a shot using _GDIPlus_BitmapLockBits instead and see if that helps. But I wonder if there might be something more at work in my case?

As mentioned, I'm using the same script as I have for months. I've tested with Photoshop again and again - same result. Also tried using Paint but then its horrible speed constantly. It's just now the problems started.

Related links on the matter



GPU 1GB GeForce



Window Classic theme with all Performance Visual Effects turned off.

AutoIt v3.3.8.1

Edited by Xibalba

Share this post

Link to post
Share on other sites

I was gonna try out _GDIPlus_BitmapLockBits instead of PixelGetColor as described >here.

But my AutoIt crashes running that example, and after some debugging I have this script:

#include <GUIConstantsEx.au3>
#include <GDIPlus.au3> ; for GDI+
Global Const $width = 600
Global Const $height = 400
Global $title = "GDI+ Test"

Opt("GUIOnEventMode", 1)
$wnd = GUICreate($title, $width, $height)
GUISetOnEvent($GUI_EVENT_CLOSE, "close")

; PixelGet method
$n1 = 100 ; set to ~100 if DWM enabled, otherwise ~100,000 (larger samples are more accurate)
$start_time = TimerInit()
For $i = 1 To $n1
    PixelGetColor( 1, 1, $wnd)
MsgBox(0, "mBox", "PixelGet avg (ms/pixel): " & $time1)

; GDI+ method
_GDIPlus_Startup ()

$hGraphic = _GDIPlus_GraphicsCreateFromHWND($wnd)
$BitmapData = _GDIPlus_BitmapLockBits($hGraphic, 0, 0, 10, 10, $GDIP_ILMREAD, $GDIP_PXF32RGB)

$Scan0 = DllStructGetData($BitmapData, "Scan0")
$Stride = DllStructGetData($BitmapData, "Stride")
$pixel = $Scan0 + $Stride + 4

$n2 = 100000 ; 100,000
;$n2 = 1000000 ; one million iterations should take ~3 sec
For $i = 1 To $n2
    DllStructCreate("dword", $pixel)

MsgBox(0, "mBox", "GDIPlus  avg (ms/pixel):" & $time2)
MsgBox(0, "mBox", "GDIPlus = " & round($time1/$time2,1) & "x PixelGet")

_GDIPlus_BitmapUnlockBits($hGraphic, $BitmapData)
_GDIPlus_GraphicsDispose ($hGraphic)
_GDIPlus_ShutDown ()

As you can see, I've commented everything below the line $hGraphic = .

This script runs for me, but the next line is the problem.

If i move the line BitmapData = above the commented section (so it runs) AutoIt just crashes

blabla has encountered a problem and was closed, send report to Microsoft Y/N, error signature:

AppName: autoit3.exe     AppVer:     ModName: gdiplus.dll
ModVer: 5.2.6002.23084     Offset: 000464c9


Why is it crashing?

Other GDI+ examples are working for me, like >this one.

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • California
      By California
      I wrote a benchmark script to measure variable declarations
      to find out whether you should focus more on static or global variables
      #cs ---------------------------------------------------------------------------- AutoIt Version: #ce ---------------------------------------------------------------------------- #Region Pre-Setting Local $iTally1 = 0 Local $iTally2 = 0 Local $iTally3 = 0 Local $iTally4 = 0 Local $iTally5 = 0 Local $iTally6 = 0 Local $iTally7 = 0 Global $GLOBALCONST1 = 1 Global $GLOBALCONST2 = 1 Global $GLOBALCONST3 = 1 Global $GLOBALCONST4 = 1 Global $GLOBALCONST5 = 1 #EndRegion Pre-Setting #Region Test Functions Func s1() Static $i = $GLOBALCONST1 Return $i EndFunc Func g2() Return $GLOBALCONST2 EndFunc Func g3() Static $i7 = "gsdgdfegbgbrwefw" Return $GLOBALCONST3 EndFunc Func g4() Static $i1 = 1 Static $i2 = "asd" Static $i3 = 234 Static $i4 = True Static $i5 = [0] Static $i6 = "hgsdg" Static $i7 = 1 Static $i8 = 1 Static $i9 = 1 Static $i0 = 1 Return $GLOBALCONST4 EndFunc Func g5() Local $i = $GLOBALCONST5 Return $i EndFunc Func g6() Local $i = 1 Return $i EndFunc Func g7() Return 1 EndFunc #EndRegion Test Functions #Region Benchmark Loop For $i = 0 To 15 Local $tDelta = TimerInit() Do $iTally1 += s1() Until TimerDiff($tDelta) >= 1000 Local $tDelta = TimerInit() Do $iTally2 += g2() Until TimerDiff($tDelta) >= 1000 Local $tDelta = TimerInit() Do $iTally3 += g3() Until TimerDiff($tDelta) >= 1000 Local $tDelta = TimerInit() Do $iTally4 += g4() Until TimerDiff($tDelta) >= 1000 Local $tDelta = TimerInit() Do $iTally5 += g5() Until TimerDiff($tDelta) >= 1000 Local $tDelta = TimerInit() Do $iTally6 += g6() Until TimerDiff($tDelta) >= 1000 Local $tDelta = TimerInit() Do $iTally7 += g7() Until TimerDiff($tDelta) >= 1000 Next #EndRegion Benchmark Loop ConsoleWrite(@CRLF&"Static1: "&$iTally1&" pkt"&@CRLF&"Global2: "&$iTally2&" pkt"&@CRLF&"Global3: "&$iTally3&" pkt"&@CRLF&"Global4: "&$iTally4&" pkt"&@CRLF&"Local5: "&$iTally5&" pkt"&@CRLF&"Local6: "&$iTally6&" pkt"&@CRLF&"Hardcode7:"&$iTally7&" pkt"&@CRLF) #cs Result Static1: 10291881 pkt global to static Global2: 13977324 pkt only global Global3: 9886169 pkt global and static Global4: 2933051 pkt global and many statics Local5: 9937314 pkt global to local Local6: 10306484 pkt only local Hardcode7: 14835319 pkt no variable #ce Result:
      100% no variable, hardcore value
      94% only global variable use
      69% only local variable use with hardcore value set
      69% only static variable use with global variable value set
      67% declaration of local variable with global variable value set
      66% only global variable use with one static variable beside
      20% only global variable use with ten static variables beside
      My thesis of the result:
      Be careful with declarations, whether local, global or static Note: in my test the global variable performance was better than the local one, but in practice the global one would lose performance due to multiple operations
      What is your best practice sharing data between multiple functions?
    • RHolmes
      By RHolmes
      I have a program that has a control that changes color a few seconds into running. So ideally, I would poll this to tell when an event has occurred. 
      I can't seem to retrieve the correct color value for a control. It always seems to return white indicating that its selecting somewhere else in the window.
      In the PixelGetColor call I'm adding half the width to the x value and subtracting half the height to the y value  in order to get the center of the control. (assuming the coords returned by ControlGetPos are top left - which i can't be sure of) But I've also tried without modifying the x/y and with changing the PixelCoordMode option to 2. Maybe I'm making a silly mistake and can't see it? Any help would be appreciated.
      Code is below:
      Opt("PixelCoordMode", 0)
      FileChangeDir( "C:\Where\My\File\Is" );
      Run( "MyProgram.exe" )
      Local $hClient = WinWaitActive( $CLIENT_TITLE, "", 10 )
      Local $systemIndicatorClassNN= "[CLASS:Qt5QWindowIcon; INSTANCE:99]"
      Local $hSystemIndicator = ControlGetHandle ( $hClient, "", $systemIndicatorClassNN)
      Local $xywh = ControlGetPos ( $hClient, "", $hSystemIndicator )
      For $i = 10 To 1 Step -1
            $color = PixelGetColor ( $xywh[0] + ($xywh[2]/2), $xywh[1] - ($xywh[3]/2), $hClient )
            LogToFile( $color )
            Sleep( 2000 )
    • Ian_Mac
      By Ian_Mac
      HotKeySet("^{SPACE}", "get_color") $colorCodeHere = ;<---------------- func get_color() Global $point = MouseGetPos() Global $color = PixelGetColor($point[0], $point[1]) MsgBox(0, "debug", "result: " & $color) EndFunc While 1 Sleep(100) WEnd Hello guys my problem is, how can i store the value that i get in that PixelGetColor($point[0], $point[0])
      i know that when i msgbox the color i will show the = of $color
      but i wanted it to be the value like  $colorCodeHere = 13456254. but  not hardcoding the value.
      or how could i say 
      if $color is = to $color then do this and if  $color is not  equal to $color then do that.
    • Fenzik
      By Fenzik
      my question is based on topic about Nvda Screen reader development atThis Link
      Autoit GUI is totaly nice for blind users, because it's controls are mostly standart.
      But in cooperation with Screen Readers this guis are much slower than other guis.
      Do you have any idea about reason of this behaviour?
      Thanks a lot for any answer.
    • Triblade
      By Triblade
      Hi all,
      I was pondering over a question with regards to the speeds of reading something and did not see this kind of question in a forum search.
      The question: What is (technically) faster? Multiple reads from the same 3d array cell, or only once make a 'temp' variable from that cell and read the value from this? I don't know if either has any real impact at all anyway, but just wanted to ask anyway. :-)
      There may be a difference if the value holds an integer or a string (or something else) but in my case, is a simple integer.
      To hopefully clarify with a small bit of code:
      $process = $start - 15 If $xy[$process][3] <> "x" Then If _ArraySearch($open, $process, 1, $open[0][0], 0, 0, 1, 1) <> -1 Then UpdateOpen($xy[$process][5], $closed[0][0]) ElseIf $start > 0 And _ArraySearch($closed, $process, 1, $closed[0][0], 0, 0, 1, 0) = -1 Then Add_open($start, $closed[0][0], $counter, $process) EndIf EndIf You can read from this, that the array $closed[0][0] is being read 3 times. And this goes on further in the code I did not show.
      My question boils down to this, should I make a 'temp' variable to hold that $closed[0][0] value until the function is done?
      It may not have a real impact on my small script, but I really am interested in the answer at least.