def set_clipboard_image(self, img_format, img_data): image_formats = {} if COMPRESSED_IMAGES: #first save it as binary compressed data: fmt_name = LPCSTR(img_format.upper().encode("latin1")+b"\0") #ie: "PNG" fmt = RegisterClipboardFormatA(fmt_name) if fmt: buf = create_string_buffer(img_data) pbuf = cast(byref(buf), c_void_p) l = len(img_data) data_handle = GlobalAlloc(GMEM_MOVEABLE, l) if not data_handle: log.error("Error: failed to allocate %i bytes of global memory", l) return True data = GlobalLock(data_handle) if not data: log("failed to lock data handle %#x (may try again)", data_handle) return False log("got data handle lock %#x for %i bytes of '%s' data", data, l, img_format) try: memmove(data, pbuf, l) finally: GlobalUnlock(data) image_formats[fmt] = data_handle #also convert it to a bitmap: from PIL import Image buf = BytesIO(img_data) img = Image.open(buf) if img.mode!="RGBA": img = img.convert("RGBA") rgb_data = img.tobytes("raw", "BGRA") w, h = img.size log("set_clipboard_image(%s, %s) image size=%s, BGR buffer=%i bytes", img_format, ellipsizer(data), img.size, len(rgb_data)) header = BITMAPINFOHEADER() memset(byref(header), 0, sizeof(BITMAPINFOHEADER )) header.biSize = sizeof(BITMAPINFOHEADER) header.biWidth = w header.biHeight = -h header.biPlanes = 1 header.biBitCount = 32 header.biCompression = BI_RGB header.biSizeImage = 0 header.biXPelsPerMeter = 10 header.biYPelsPerMeter = 10 bitmapinfo = BITMAPINFO() bitmapinfo.bmiColors = 0 memmove(byref(bitmapinfo.bmiHeader), byref(header), sizeof(BITMAPINFOHEADER)) rgb_buf = create_string_buffer(rgb_data) pbuf = cast(byref(rgb_buf), c_void_p) hdc = GetDC(None) CBM_INIT = 4 bitmap = CreateDIBitmap(hdc, byref(header), CBM_INIT, pbuf, byref(bitmapinfo), win32con.DIB_RGB_COLORS) ReleaseDC(None, hdc) image_formats[win32con.CF_BITMAP] = bitmap self.do_set_clipboard_image(image_formats)
def format_name(fmt): name = CLIPBOARD_FORMATS.get(fmt) if name: return name ulen = 128 buf = LPCSTR(b" " * ulen) r = GetClipboardFormatNameA(fmt, buf, ulen - 1) if r == 0: return str(fmt) return (buf.value[:r]).decode("latin1")
def got_clipboard_lock(): if COMPRESSED_IMAGES: fmt_name = LPCSTR(img_format.upper().encode("latin1") + b"\0") #ie: "PNG" fmt = RegisterClipboardFormatA(fmt_name) if fmt: data_handle = GetClipboardData(fmt) if data_handle: size = GlobalSize(data_handle) data = GlobalLock(data_handle) log("GetClipboardData(%s)=%#x size=%s, data=%#x", img_format.upper(), data_handle, size, data) if data and size: try: cdata = (c_char * size).from_address(data) finally: GlobalUnlock(data) got_image(bytes(cdata), False) return True data_handle = GetClipboardData(win32con.CF_DIBV5) log("CF_BITMAP=%s", data_handle) data = GlobalLock(data_handle) if not data: log("failed to lock data handle %#x (may try again)", data_handle) return False try: header = cast(data, PBITMAPV5HEADER).contents offset = header.bV5Size + header.bV5ClrUsed * 4 w, h = header.bV5Width, abs(header.bV5Height) bits = header.bV5BitCount log( "offset=%s, width=%i, height=%i, compression=%s", offset, w, h, BI_FORMATS.get(header.bV5Compression, header.bV5Compression)) log("planes=%i, bitcount=%i", header.bV5Planes, bits) log("colorspace=%s", COLOR_PROFILES.get(header.bV5CSType, header.bV5CSType)) #if header.bV5Compression in (BI_JPEG, BI_PNG): # pass if header.bV5Compression != BI_RGB: errback( "cannot handle %s compression yet" % BI_FORMATS.get( header.bV5Compression, header.bV5Compression)) return True if bits == 24: save_format = "RGB" rgb_format = "BGR" stride = roundup(w * 3, 4) elif bits == 32: save_format = "RGBA" rgb_format = "BGRA" stride = w * 4 else: errback( "cannot handle image data with %i bits per pixel yet" % bits) return True img_size = stride * h rgb_data = (c_char * img_size).from_address(data + offset) from PIL import Image, ImageOps img = Image.frombytes(save_format, (w, h), rgb_data, "raw", rgb_format, stride, 1) if header.bV5Height > 0: img = ImageOps.flip(img) buf = BytesIO() img.save(buf, format=save_format) data = buf.getvalue() buf.close() got_image(data, True) return True finally: GlobalUnlock(data)