winapi - Pasting image from clipboard to MS Word has wrong aspect ratio -
this question kind of follow this one.
i'm using code in first answer region of desktop, , copying clipboard. might seem didn't research, did. problem first contact ctypes, winapi , jazz.
ms paint, paint.net , libreoffice can read image perfectly, ms word changes aspect ratio; sets width , height 15cm.
my question is: kind of data word expecting? code example great.
this current code (same other answer):
import ctypes ctypes import wintypes pil import imagegrab io import bytesio msvcrt = ctypes.cdll.msvcrt windll = ctypes.windll kernel32 = windll.kernel32 user32 = windll.user32 gdi32 = windll.gdi32 img = imagegrab.grab() output = bytesio() img.convert("rgb").save(output, "bmp") data = output.getvalue()[14:] output.close() cf_dib = 8 gmem_moveable = 0x0002 global_mem = kernel32.globalalloc(gmem_moveable, len(data)) global_data = kernel32.globallock(global_mem) msvcrt.memcpy(ctypes.c_char_p(global_data), data, len(data)) kernel32.globalunlock(global_mem) user32.openclipboard(none) user32.emptyclipboard() user32.setclipboarddata(cf_dib, global_mem) user32.closeclipboard()
update
i thought maybe easier use winapi instead of using pil. dimensions correct, image black everywhere (libreoffice, word...).
class rect(ctypes.structure): _fields_ = [ ('left', ctypes.c_long), ('top', ctypes.c_long), ('right', ctypes.c_long), ('bottom', ctypes.c_long) ] rect = rect() # self.whandle result of user32.getdesktopwindow() user32.getwindowrect(self.whandle, ctypes.byref(rect)) hdcscreen = user32.getdc(none) hdc = gdi32.createcompatibledc(hdcscreen) hbmp = gdi32.createcompatiblebitmap( hdcscreen, rect.right - rect.left, rect.bottom - rect.top ) gdi32.selectobject(hdc, hbmp) pw_clientonly = 0x00000001 # returns 0 user32.printwindow(self.whandle, hdc, pw_clientonly) cf_bitmap = 2 user32.openclipboard(none) user32.emptyclipboard() user32.setclipboarddata(cf_bitmap, hbmp) user32.closeclipboard() gdi32.deletedc(hdc) gdi32.deleteobject(hbmp) user32.releasedc(none, hdcscreen)
printwindow returns 0 failing :(
update 2
i tried patching image header snippet:
import struct fmt = "lllhhllllll" header_size = struct.calcsize(fmt) # data comes first snippet image_header = data[:header_size] image_data = data[header_size:] unpacked_header = list(struct.unpack_from(fmt, image_header)) # indexes: biwidth = 1 biheight = 2 bixpelspermeter = 7 biypelspermeter = 8 unpacked_header[bixpelspermeter] = 2835 unpacked_header[biypelspermeter] = 2835 image_header = struct.pack(fmt, *unpacked_header) data = image_header + image_data
the values *pelspermeter
extracted here.
the resolution of windows bitmap defined bixpelspermeter
, biypelspermeter
members of `bitmapinfoheader' structure.
the python imaging library (pil) writes resolution 1 pixel per meter in both directions (line 225 of bmpimageplugin.py
). word thinks bitmap hundreds of metres in size , scales badly. pil not provide interface change resolution.
you can make hacky fix patching values data
object. object begins serialised bitmapinfoheader
, though need check bisize
(the first 4 bytes) sure. can find bixpelspermeter
, biypelspermeter
@ offsets 24 , 28 respectively.
a less hacky fix submit patch pil chooses sensible default resolution.
Comments
Post a Comment