Example #1
0
 def get_image(self, x, y, width, height, logger=None):
     start = time.time()
     desktop_wnd = win32gui.GetDesktopWindow()
     metrics = get_virtualscreenmetrics()
     if self.metrics is None or self.metrics != metrics:
         #new metrics, start from scratch:
         self.metrics = metrics
         self.ddc, self.cdc, self.memdc, self.bitmap = None, None, None, None
     dx, dy, dw, dh = metrics
     #clamp rectangle requested to the virtual desktop size:
     if x < dx:
         width -= x - dx
         x = dx
     if y < dy:
         height -= y - dy
         y = dy
     if width > dw:
         width = dw
     if height > dh:
         height = dh
     try:
         if not self.ddc:
             self.ddc = win32gui.GetWindowDC(desktop_wnd)
             assert self.ddc, "cannot get a drawing context from the desktop window %s" % desktop_wnd
             self.cdc = win32ui.CreateDCFromHandle(self.ddc)
             assert self.cdc, "cannot get a compatible drawing context from the desktop drawing context %s" % self.ddc
             self.memdc = self.cdc.CreateCompatibleDC()
             self.bitmap = win32ui.CreateBitmap()
             self.bitmap.CreateCompatibleBitmap(self.cdc, width, height)
         self.memdc.SelectObject(self.bitmap)
         select_time = time.time()
         log("get_image up to SelectObject took %ims",
             (select_time - start) * 1000)
         self.memdc.BitBlt((0, 0), (width, height), self.cdc, (x, y),
                           win32con.SRCCOPY)
         bitblt_time = time.time()
         log("get_image BitBlt took %ims",
             (bitblt_time - select_time) * 1000)
         pixels = self.bitmap.GetBitmapBits(True)
         log("get_image GetBitmapBits took %ims",
             (time.time() - bitblt_time) * 1000)
     finally:
         pass
     assert pixels, "no pixels returned from GetBitmapBits"
     v = ImageWrapper(0,
                      0,
                      width,
                      height,
                      pixels,
                      "BGRX",
                      24,
                      width * 4,
                      planes=ImageWrapper.PACKED,
                      thread_safe=True)
     if logger == None:
         logger = log
     log("get_image%s=%s took %ims", (x, y, width, height), v,
         (time.time() - start) * 1000)
     return v
Example #2
0
 def take_screenshot(self):
     from PIL import Image               #@UnresolvedImport
     x, y, w, h = get_virtualscreenmetrics()
     image = self.get_image(x, y, w, h)
     assert image.get_width()==w and image.get_height()==h
     assert image.get_pixel_format()=="BGRX"
     img = Image.frombuffer("RGB", (w, h), image.get_pixels(), "raw", "BGRX", 0, 1)
     out = StringIOClass()
     img.save(out, format="PNG")
     screenshot = (img.width, img.height, "png", img.width*3, out.getvalue())
     out.close()
     return screenshot
Example #3
0
 def take_screenshot(self):
     from PIL import Image               #@UnresolvedImport
     x, y, w, h = get_virtualscreenmetrics()
     image = self.get_image(x, y, w, h)
     assert image.get_width()==w and image.get_height()==h
     assert image.get_pixel_format()=="BGRX"
     img = Image.frombuffer("RGB", (w, h), image.get_pixels(), "raw", "BGRX", 0, 1)
     out = StringIOClass()
     img.save(out, format="PNG")
     screenshot = (img.width, img.height, "png", img.width*3, out.getvalue())
     out.close()
     return screenshot
Example #4
0
 def take_screenshot(self):
     x, y, w, h = get_virtualscreenmetrics()
     image = self.get_image(x, y, w, h)
     if not image:
         return None
     assert image.get_width()==w and image.get_height()==h
     assert image.get_pixel_format()=="BGRX"
     img = Image.frombuffer("RGB", (w, h), image.get_pixels(), "raw", "BGRX", 0, 1)
     out = BytesIOClass()
     img.save(out, format="PNG")
     screenshot = (img.width, img.height, "png", img.width*3, out.getvalue())
     out.close()
     return screenshot
Example #5
0
 def get_image(self, x, y, width, height, logger=None):
     start = time.time()
     desktop_wnd = win32gui.GetDesktopWindow()
     metrics = get_virtualscreenmetrics()
     if self.metrics is None or self.metrics!=metrics:
         #new metrics, start from scratch:
         self.metrics = metrics
         self.ddc, self.cdc, self.memdc, self.bitmap = None, None, None, None
     dx, dy, dw, dh = metrics
     #clamp rectangle requested to the virtual desktop size:
     if x<dx:
         width -= x-dx
         x = dx
     if y<dy:
         height -= y-dy
         y = dy
     if width>dw:
         width = dw
     if height>dh:
         height = dh
     try:
         if not self.ddc:
             self.ddc = win32gui.GetWindowDC(desktop_wnd)
             assert self.ddc, "cannot get a drawing context from the desktop window %s" % desktop_wnd
             self.cdc = win32ui.CreateDCFromHandle(self.ddc)
             assert self.cdc, "cannot get a compatible drawing context from the desktop drawing context %s" % self.ddc
             self.memdc = self.cdc.CreateCompatibleDC()
             self.bitmap = win32ui.CreateBitmap()
             self.bitmap.CreateCompatibleBitmap(self.cdc, width, height)
         self.memdc.SelectObject(self.bitmap)
         select_time = time.time()
         log("get_image up to SelectObject took %ims", (select_time-start)*1000)
         self.memdc.BitBlt((0, 0), (width, height), self.cdc, (x, y), win32con.SRCCOPY)
         bitblt_time = time.time()
         log("get_image BitBlt took %ims", (bitblt_time-select_time)*1000)
         pixels = self.bitmap.GetBitmapBits(True)
         log("get_image GetBitmapBits took %ims", (time.time()-bitblt_time)*1000)
     finally:
         pass
     assert pixels, "no pixels returned from GetBitmapBits"
     v = ImageWrapper(0, 0, width, height, pixels, "BGRX", 24, width*4, planes=ImageWrapper.PACKED, thread_safe=True)
     if logger==None:
         logger = log
     log("get_image%s=%s took %ims", (x, y, width, height), v, (time.time()-start)*1000)
     return v
Example #6
0
 def get_capture_coords(self, x, y, width, height):
     metrics = get_virtualscreenmetrics()
     if self.metrics is None or self.metrics != metrics:
         #new metrics, start from scratch:
         self.metrics = metrics
         self.clean()
     log("get_image%s metrics=%s", (x, y, width, height), metrics)
     dx, dy, dw, dh = metrics
     if width == 0:
         width = dw
     if height == 0:
         height = dh
     #clamp rectangle requested to the virtual desktop size:
     if x < dx:
         width -= x - dx
         x = dx
     if y < dy:
         height -= y - dy
         y = dy
     if width > dw:
         width = dw
     if height > dh:
         height = dh
     return x, y, width, height
Example #7
0
 def get_image(self, x=0, y=0, width=0, height=0):
     start = time.time()
     metrics = get_virtualscreenmetrics()
     if self.metrics is None or self.metrics != metrics:
         #new metrics, start from scratch:
         self.metrics = metrics
         self.clean()
     log("get_image%s metrics=%s", (x, y, width, height), metrics)
     dx, dy, dw, dh = metrics
     if width == 0:
         width = dw
     if height == 0:
         height = dh
     #clamp rectangle requested to the virtual desktop size:
     if x < dx:
         width -= x - dx
         x = dx
     if y < dy:
         height -= y - dy
         y = dy
     if width > dw:
         width = dw
     if height > dh:
         height = dh
     if not self.dc:
         self.wnd = GetDesktopWindow()
         self.dc = GetWindowDC(self.wnd)
         assert self.dc, "failed to get a drawing context from the desktop window %s" % self.wnd
         self.bit_depth = GetDeviceCaps(self.dc, win32con.BITSPIXEL)
         self.memdc = CreateCompatibleDC(self.dc)
         assert self.memdc, "failed to get a compatible drawing context from %s" % self.dc
     bitmap = CreateCompatibleBitmap(self.dc, width, height)
     assert bitmap, "failed to get a compatible bitmap from %s" % self.dc
     r = SelectObject(self.memdc, bitmap)
     if r == 0:
         log.error("Error: cannot select bitmap object")
         return None
     select_time = time.time()
     log("get_image up to SelectObject (%s) took %ims",
         REGION_CONSTS.get(r, r), (select_time - start) * 1000)
     try:
         if BitBlt(self.memdc, 0, 0, width, height, self.dc, x, y,
                   win32con.SRCCOPY) == 0:
             e = ctypes.get_last_error()
             #rate limit the error message:
             now = time.time()
             if now - self.bitblt_err_time > 10:
                 log.error("Error: failed to blit the screen, error %i", e)
                 self.bitblt_err_time = now
             return None
     except Exception as e:
         log("BitBlt error", exc_info=True)
         log.error("Error: cannot capture screen")
         log.error(" %s", e)
         return None
     bitblt_time = time.time()
     log("get_image BitBlt took %ims", (bitblt_time - select_time) * 1000)
     rowstride = roundup(width * self.bit_depth // 8, 2)
     buf_size = rowstride * height
     pixels = ctypes.create_string_buffer(b"", buf_size)
     log("GetBitmapBits(%#x, %#x, %#x)", bitmap, buf_size,
         ctypes.addressof(pixels))
     r = GetBitmapBits(bitmap, buf_size, ctypes.byref(pixels))
     if r == 0:
         log.error("Error: failed to copy screen bitmap data")
         return None
     if r != buf_size:
         log.warn(
             "Warning: truncating pixel buffer, got %i bytes but expected %i",
             r, buf_size)
         pixels = pixels[:r]
     log("get_image GetBitmapBits took %ims",
         (time.time() - bitblt_time) * 1000)
     DeleteObject(bitmap)
     assert pixels, "no pixels returned from GetBitmapBits"
     if self.bit_depth == 32:
         rgb_format = "BGRX"
     elif self.bit_depth == 30:
         rgb_format = "r210"
     elif self.bit_depth == 24:
         rgb_format = "BGR"
     elif self.bit_depth == 16:
         rgb_format = "BGR565"
     elif self.bit_depth == 8:
         rgb_format = "RLE8"
     else:
         raise Exception("unsupported bit depth: %s" % self.bit_depth)
     bpp = self.bit_depth // 8
     v = ImageWrapper(0,
                      0,
                      width,
                      height,
                      pixels,
                      rgb_format,
                      self.bit_depth,
                      rowstride,
                      bpp,
                      planes=ImageWrapper.PACKED,
                      thread_safe=True)
     if self.bit_depth == 8:
         count = GetSystemPaletteEntries(self.dc, 0, 0, None)
         log("palette size: %s", count)
         palette = []
         if count > 0:
             buf = (PALETTEENTRY * count)()
             r = GetSystemPaletteEntries(self.dc, 0, count,
                                         ctypes.byref(buf))
             #we expect 16-bit values, so bit-shift them:
             for p in buf:
                 palette.append(
                     (p.peRed << 8, p.peGreen << 8, p.peBlue << 8))
         v.set_palette(palette)
     log("get_image%s=%s took %ims", (x, y, width, height), v,
         (time.time() - start) * 1000)
     return v