views:

119

answers:

2

I need to get the color of some pixels on the screen or from the active window, and I need to do so quickly. I've tried using win32gui and ctypes/windll, but they're much too slow. Each of these programs gets the color of 100 pixels:

import win32gui
import time
time.clock()
for y in range(0, 100, 10):
    for x in range(0, 100, 10):
        color = win32gui.GetPixel(win32gui.GetDC(win32gui.GetActiveWindow()), x , y)
print(time.clock())

and

from ctypes import windll
import time
time.clock()
hdc = windll.user32.GetDC(0)
for y in range(0, 100, 10):
    for x in range(0, 100, 10):
        color = windll.gdi32.GetPixel(hdc, x, y)
print(time.clock())

Each of these takes about 1.75 seconds. I need a program like this to take less than 0.1 seconds. What's making it so slow?

I'm working with Python 3.x and Windows 7. If your solution requires I use Python 2.x, please link me to an article showing how to have Python 3.x and 2.x both installed. I looked, but couldn't figure out how to do this.

Thanks!

+2  A: 

I had this same exact problem, and solved it (in Java, in C#). The main idea behind the solution is GetPixel form screen is Slow, and you can't fix that. But as you need some pixels, you can get a bunch of them all at once.

Time that took to get 64 pixels was 98 times faster.

Margus
So it sounds like you're suggesting that I capture the whole screen (say as a bitmap) then get the pixel values from that. This sounds like it might be a job for Python Imaging Library (PIL) (which requires python 2.x) or ImageMagick (which I'm not sure what what version of python it requires). If anyone has suggestions, feel free to chime in.
dln385
Yes, basically you need CopyFromScreen method equivalent from .net, with Bitmap class where you can access single pixel by its coordinates. And yes, people have done this before and there are lots of libraries that you can import, choose what fits you best.
Margus
A: 

Thanks to Margus' direction, I focused on getting the image before extracting the pixel information. Here's a workable solution using the Python Imaging Library (PIL), which requires Python 2.x.

import ImageGrab
import time
time.clock()
image = ImageGrab.grab()
for y in range(0, 100, 10):
    for x in range(0, 100, 10):
        color = image.getpixel((x, y))
print(time.clock())

I don't think it gets any simpler than that. This takes (on average) 0.1 seconds, which is a little slower than I'd like but fast enough.

As for having Python 3.x and 2.x both installed, I separated that into a new question. I'm still having some trouble with it, but it's generally working.

dln385