Copy PIL/PILLOW Image to Windows Clipboard

前端 未结 2 1441
一向
一向 2020-12-12 01:13

I\'ve seen this question and i followed every step, changing the code to satisfy my requirements, that are Python3, Pillow, and ctypes. The less libraries, the better.

相关标签:
2条回答
  • 2020-12-12 01:46

    The example uses pywin32, which is Python wrapper around Win32 API that hides some low level details you need to take care yourself of if you want to use ctypes.

    Here is how you do it using ctypes, it adds a functionally of creating globally allocated buffer and copy the data into that buffer:

    #!python
    
    from PIL import Image
    #from cStringIO import StringIO
    from io import BytesIO
    from ctypes import *
    from ctypes.wintypes import *
    
    HGLOBAL = HANDLE
    SIZE_T = c_size_t
    GHND = 0x0042
    GMEM_SHARE = 0x2000
    
    GlobalAlloc = windll.kernel32.GlobalAlloc
    GlobalAlloc.restype = HGLOBAL
    GlobalAlloc.argtypes = [UINT, SIZE_T]
    
    GlobalLock = windll.kernel32.GlobalLock
    GlobalLock.restype = LPVOID
    GlobalLock.argtypes = [HGLOBAL]
    
    GlobalUnlock = windll.kernel32.GlobalUnlock
    GlobalUnlock.restype = BOOL
    GlobalUnlock.argtypes = [HGLOBAL]
    
    CF_DIB = 8
    
    OpenClipboard = windll.user32.OpenClipboard
    OpenClipboard.restype = BOOL 
    OpenClipboard.argtypes = [HWND]
    
    EmptyClipboard = windll.user32.EmptyClipboard
    EmptyClipboard.restype = BOOL
    EmptyClipboard.argtypes = None
    
    SetClipboardData = windll.user32.SetClipboardData
    SetClipboardData.restype = HANDLE
    SetClipboardData.argtypes = [UINT, HANDLE]
    
    CloseClipboard = windll.user32.CloseClipboard
    CloseClipboard.restype = BOOL
    CloseClipboard.argtypes = None
    
    #################################################
    
    image = Image.new("RGB", (200, 200), (255, 0, 0))
    
    #output = StringIO()
    output = BytesIO()
    image.convert("RGB").save(output, "BMP")
    data = output.getvalue()[14:]
    output.close()
    
    hData = GlobalAlloc(GHND | GMEM_SHARE, len(data))
    pData = GlobalLock(hData)
    memmove(pData, data, len(data))
    GlobalUnlock(hData)
    
    OpenClipboard(None)
    EmptyClipboard()
    SetClipboardData(CF_DIB, pData)
    CloseClipboard()
    
    0 讨论(0)
  • 2020-12-12 01:57

    Whew. Apparently the win32clipboard library does simplify some things when compared to ctypes. Your attempt to simply replace one with the other is far from correct.

    So I booted up my Windows virtual machine, installed Pillow and rewrote your program, learning from two other answers:

    import io
    
    import ctypes
    msvcrt = ctypes.cdll.msvcrt
    kernel32 = ctypes.windll.kernel32
    user32 = ctypes.windll.user32
    
    from PIL import ImageGrab
    
    img = ImageGrab.grab()
    output = io.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()
    
    0 讨论(0)
提交回复
热议问题