Jump to content
Macro Express Forums

Glacial speed of pixel hunting

Recommended Posts

Arising out of the current posts by@sdspieg I see that on my Win 10 Pro PC (i7, 4.0 GHz) pixel-hunting macros are now even slower than I last recall. What performance do others get please? For example, try the following macro (modified to suit). Here it takes about 15 seconds to get from y=0 to 842, that's less than 60 pixels/sec!






Variable Set Integer %nMouseY% to 0
Repeat Until %nPixCol% Equals "12870323"
  Get Pixel Color at (187, %nMouseY%) Relative to Current Window into %nPixCol%
  Variable Modify Integer %nMouseY%: Increment
End Repeat
Text Box Display: Result



<VARIABLE SET INTEGER Option="\x00" Destination="%nMouseY%" Value="0"/>
<REPEAT UNTIL Variable="%nPixCol%" Condition="\x00" Value="12870323"/>
<GET PIXEL COLOR Option="\x01" Rel_To_Screen="FALSE" X="187" Y="%nMouseY%" Destination="%nPixCol%"/>
<VARIABLE MODIFY INTEGER Option="\x07" Destination="%nMouseY%"/>
<TEXT BOX DISPLAY Title="Result" Content="{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang2057{\\fonttbl{\\f0\\fnil\\fcharset0 Tahoma;}{\\f1\\fnil Tahoma;}}\r\n\\viewkind4\\uc1\\pard\\qc\\b\\f0\\fs20 \r\n\\par The colour required has been found at the location specified.\r\n\\par nMouseY = %nMouseY%\r\n\\par \\f1 \r\n\\par }\r\n" Left="676" Top="Center" Width="423" Height="200" Monitor="0" OnTop="TRUE" Keep_Focus="TRUE" Mode="\x00" Delay="0"/>


BTW, @sdspieg, the macro above avoids that unnecessary extra variable you used.


I get the the same speed if I move the mouse cursor itself.


Of course, in many situations the target may be a large enough solid colour to significantly improve the speed by using a larger increment than 1.  But take care that it really is a uniform exact colour. Despite appearances, the example here is not. (That's on the original MX Forum screen; the purple circle in my JPG will contain many more variations.)


And in a real life macro i would naturally start with y = a value much closer to my target.


Obscuring the issue: I use a macro of this type that does occasionally run much faster. Pointing perhaps to some sort of frequent but not permanent timing conflict? Win 10 only? My PC only?




Link to post
Share on other sites

P.S.  Getting pixel relative to window, I wanted to use the Windows clock as a timer.  So I started the macro, then within a second or so I clicked down in the lower right of the screen to open up the calendar and clock display.  As soon as I clicked and took focus away from the original window, the macro would complete almost instantly.  I displayed the Repeat counter in a text box at the end of the repeats, so I know it was completing "normally".  I would guess that when the window loses focus, ME bypasses whatever system interaction that otherwise would take all the time.  If getting pixel relative to screen, then taking focus away didn't make a difference in timing. 

Link to post
Share on other sites

That's intriguing! But I don't seem able to reproduce it. I'm running from debug mode (F9) if that matters. Choose the browser title and hit Enter. Then quickly click anywhere else. Not only does the macro not immediately complete, but it doesn't complete at all and has to be terminated.


Link to post
Share on other sites

Pixel hunting under Windows 10 is molasses-slow.


Earlier this year I reported the issue to the folks at Insight. They responded that it's due to a change in Windows, and there is little or nothing they can do about it.


The best workaround I have come up: Instead of checking every pixel along a path, I now check in 50 or 100 pixel intervals. I've managed to make this work, although I had to completely rewrite several macros.


There are times when the target is small, maybe one or two pixels wide. I haven't tried to repair these yet. I'm not sure what I will do, but maybe something like this:


We are searching for a red, vertical line that is one pixel wide.


1. Move the mouse pointer to the left edge of the window that contains the red line.

2. Search right, 64 pixels at a time until the pixel colour is [not] some colour, or is red.

3. Search left, 32 pixels at a time until the pixel colour is [not] some colour, or is red.



In other words, zero in on the target pixel.


I anticipate a macro that checks in two directions will run acceptably fast. But I foresee complications that might make this strategy unreliable, hard to maintain, or both!

Link to post
Share on other sites
On 12/31/2020 at 11:57 AM, acantor said:

We are searching for a red, vertical line that is one pixel wide.


1. Move the mouse pointer to the left edge of the window that contains the red line.

2. Search right, 64 pixels at a time until the pixel colour is [not] some colour, or is red.

3. Search right, 32 pixels at a time until the pixel colour is [not] some colour, or is red.


Binary search, of sorts.  This would work extremely well to find the dividing line between two colors.  Even a full-screen search 1920 pixels wide would only require retrieving about a dozen pixels.  But for more than two colors it gets sketchy. 

Link to post
Share on other sites

I spoke too soon. I tried a bi-directional search for a thin vertical line. The approach doesn't seem to work efficiently when the position of the vertical line along the x-axis is not known. Maybe someone will come up with a better implementation than mine!


However, I now have a bi-directional search that locates the border between two regions, rather than a one-pixel wide line. It seems to work OK when the regions are reasonably large.


Imagine a window with two colours. The left half is entirely black and the right half is entirely white. We want to move the mouse cursor so it's at, or near the border.


From the left edge of the window, check right, once every 64 pixels, for a white pixel. (The maximum number of checks is based on the window width.)


When found, check left, once every 32 pixels for a non-white pixel.


When found, check right, once every 16 pixels, for a white pixel.


Repeat as many times as needed to achieve the needed precision.


 My script doesn't try to hit the exact border because it doesn't need to.


Sigh. I miss the capability of searching hundreds (or thousands) of pixels in the blink of an eye!


Link to post
Share on other sites

For a black/white split area, where left and right margins are known and black is on the left, this script will find the dividing line within two or three pixels.  It only retrieves 13 pixels.  13 may be one or two more than necessary -- I haven't done the exact math.  For an area bigger than 1900 you might have to increase the Repeat count to 14 or 15.  To get the exact dividing line a little more code would have to be added, to step through the last two or three pixels one at a time.

I moved the mouse, and inserted a half-second delay during each Repeat, so I could watch it run.  Get rid of the delay and it runs very quickly.  


// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Variable Set Integer %left% to 1
Variable Set Integer %right% to 1900
Repeat Start (Repeat 13 times)
  Variable Modify Integer: %midpoint% = %left% + %right% // midpoint of area to search is left margin plus right margin divided by 2
  Variable Modify Integer: %midpoint% = %midpoint% / 2
  Mouse Move: %midpoint%, 400 Relative to Screen // move mouse to midpoint, get pixel color
  Get Pixel Color from Beneath the Mouse into %color%
  If Variable %color% Equals "0"
    Variable Modify Integer set %left% to the contents of %midpoint%
    Variable Modify Integer set %right% to the contents of %midpoint%
  End If
  Delay: 500 milliseconds
End Repeat
Text Box Display: Diagnostics
Macro Return


<COMMENT Value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/>
<VARIABLE SET INTEGER Option="\x00" Destination="%left%" Value="1"/>
<VARIABLE SET INTEGER Option="\x00" Destination="%right%" Value="1900"/>
<COMMENT Value=" "/>
<REPEAT START Start="1" Step="1" Count="13" Save="FALSE"/>
<VARIABLE MODIFY INTEGER Option="\x00" Destination="%midpoint%" Value1="%left%" Value2="%right%" _COMMENT="midpoint of area to search is left margin plus right margin divided by 2"/>
<VARIABLE MODIFY INTEGER Option="\x03" Destination="%midpoint%" Value1="%midpoint%" Value2="2"/>
<COMMENT Value=" "/>
<MOUSE MOVE Option="\x01" X="%midpoint%" Y="400" _PROMPT="0x000A" _COMMENT="move mouse to midpoint, get pixel color"/>
<GET PIXEL COLOR Option="\x00" Rel_To_Screen="TRUE" Destination="%color%"/>
<COMMENT Value=" "/>
<IF VARIABLE Variable="%color%" Condition="\x00" Value="0" IgnoreCase="FALSE"/>
<VARIABLE MODIFY INTEGER Option="\x06" Destination="%left%" Variable="%midpoint%"/>
<VARIABLE MODIFY INTEGER Option="\x06" Destination="%right%" Variable="%midpoint%"/>
<DELAY Flags="\x12" Time="500"/>
<COMMENT Value=" "/>
<TEXT BOX DISPLAY Title="Diagnostics" Content="{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fnil\\fcharset0 Tahoma;}{\\f1\\fnil Tahoma;}}\r\n\\viewkind4\\uc1\\pard\\f0\\fs20 Black/White margin is at %midpoint%\\f1 \r\n\\par }\r\n" Left="Center" Top="Center" Width="278" Height="200" Monitor="0" OnTop="FALSE" Keep_Focus="TRUE" Mode="\x00" Delay="0"/>
<COMMENT Value=" "/>


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...