screenBitmap.py
2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import ctypes
import winGDI
user32=ctypes.windll.user32
gdi32=ctypes.windll.gdi32
class ScreenBitmap(object):
"""Provides a way to capture a bitmap of any part of the screen. The object caches needed DCs and bitmaps therefore an instance of an object only handles one size of bitmap."""
def __init__(self,width,height):
"""
@param width: the width of the resulting bitmap in rgb pixels.
@param height: the height of the bitmap in rgb pixels.
"""
self.width=width
self.height=height
#Fetch the device context for the screen
self._screenDC=user32.GetDC(0)
#Create a memory device context with which we can copy screen content to on request.
self._memDC=gdi32.CreateCompatibleDC(self._screenDC)
#Create a new bitmap of the chosen size, and set this as the memory device context's bitmap, so that what is drawn is captured.
self._memBitmap=gdi32.CreateCompatibleBitmap(self._screenDC,width,height)
self._oldBitmap=gdi32.SelectObject(self._memDC,self._memBitmap)
#We always want standard RGB data
bmInfo=winGDI.BITMAPINFO()
bmInfo.bmiHeader.biSize=ctypes.sizeof(bmInfo)
bmInfo.bmiHeader.biWidth=width
bmInfo.bmiHeader.biHeight=height*-1
bmInfo.bmiHeader.biPlanes=1
bmInfo.bmiHeader.biBitCount=32
bmInfo.bmiHeader.biCompression=winGDI.BI_RGB
self._bmInfo=bmInfo
def __del__(self):
gdi32.SelectObject(self._memDC,self._oldBitmap)
gdi32.DeleteObject(self._memBitmap)
gdi32.DeleteDC(self._memDC)
user32.ReleaseDC(0,self._screenDC)
def captureImage(self,x,y,w,h):
"""
Captures the part of the screen starting at x,y and extends by w (width) and h (height), and stretches/shrinks it to fit in to the object's bitmap size.
"""
#Copy the requested content from the screen in to our memory device context, stretching/shrinking its size to fit.
gdi32.StretchBlt(self._memDC,0,0,self.width,self.height,self._screenDC,x,y,w,h,winGDI.SRCCOPY)
#Fetch the pixels from our memory bitmap and store them in a buffer to be returned
buffer=(winGDI.RGBQUAD*w*h)()
gdi32.GetDIBits(self._memDC,self._memBitmap,0,self.height,buffer,ctypes.byref(self._bmInfo),winGDI.DIB_RGB_COLORS);
return buffer
def rgbPixelBrightness(p):
"""Converts a RGBQUAD pixel in to one grey-scale brightness value."""
return int((0.3*p.rgbBlue)+(0.59*p.rgbGreen)+(0.11*p.rgbRed))