Write image to Windows clipboard in python with PIL and win32clipboard?
Asked Answered
R

4

5

I'm trying to open an image file and copy the image to the Windows clipboard. Is there a way to fix this:

import win32clipboard
from PIL import Image

def send_to_clipboard(clip_type, data): 
    win32clipboard.OpenClipboard()
    win32clipboard.EmptyClipboard()
    win32clipboard.SetClipboardData(clip_type, data) 
    win32clipboard.CloseClipboard()

clip_type = win32clipboard.CF_BITMAP
filepath = 'c:\\temp\\image.jpg'

im = Image.open(filepath) 
data = im.tobitmap() # fails with valueerror: not a bitmap
# data = im.tostring() runs, but receiving programs can't read the results
send_to_clipboard(clip_type, data)

I could install PythonMagick, etc., but would prefer not installing yet another library for a one-off program

Retread answered 13/8, 2011 at 12:35 Comment(0)
A
9
from cStringIO import StringIO
import win32clipboard
from PIL import Image

def send_to_clipboard(clip_type, data):
    win32clipboard.OpenClipboard()
    win32clipboard.EmptyClipboard()
    win32clipboard.SetClipboardData(clip_type, data)
    win32clipboard.CloseClipboard()

filepath = 'image.jpg'
image = Image.open(filepath)

output = StringIO()
image.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()

send_to_clipboard(win32clipboard.CF_DIB, data)
Auspicate answered 13/8, 2011 at 17:15 Comment(5)
Why the magic number 14? Will it break on Python 3 or 64 bit Python? Many thanks for an extremely useful answer.Warp
@MichaelPlatings 14 because a BMP file has a 14-byte header. This header remains 14 bytes whether the BMP file is copied to a 32-bit or 64-bit system. Under Python 3 you need to change StringIO to BytesIO.Satang
For python 3, need to modify two lines as follows - from io import BytesIO ... output = BytesIO()Diarthrosis
@DamianYerrick What is the value for PNG?Phocomelia
@CoolCloud See yfyang's answer. PNG's header is 8 bytes but Windows clipboard doesn't use PNG.Satang
C
1

The file header off-set of BMP is 14 bytes. Well, BMP is also known as the device independent bitmap (DIB) file format, so you don't need to worried about the magic number 14.

FYI, it does need a windows clipboard API. Hence you can use BMP but can't use

image.convert("RGB").save(output, "PNG")
data = output.getvalue()[8:]

even you know the offset is 8 for PNG.

Conni answered 8/7, 2014 at 15:5 Comment(0)
B
1

This worked for me in Python 3.8 (solution found here)

It's the same answer as the cgohike's but:

output = StringIO()

changed into:

output = io.BytesIO()

Full code:

import io
import win32clipboard
from PIL import Image

def send_to_clipboard(clip_type, data):
    win32clipboard.OpenClipboard()
    win32clipboard.EmptyClipboard()
    win32clipboard.SetClipboardData(clip_type, data)
    win32clipboard.CloseClipboard()

image = Image.open('image.jpg')

output = io.BytesIO()
image.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()

send_to_clipboard(win32clipboard.CF_DIB, data)
Bangle answered 22/5, 2022 at 14:14 Comment(0)
H
1

Addendum to the other answers, it's also possible to copy PNG (and probably other formats) to the clipboard. I've used the following:

buffer = io.BytesIO()
img_out.save(fp=buffer, format='PNG')

clipboard_format = win32clipboard.RegisterClipboardFormat('PNG')
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(clipboard_format, buffer.getvalue())
win32clipboard.CloseClipboard()

buffer.close()

This answer to a related question details support by some programs for the non-standard clipboard format "PNG", which I used in my answer. If the program you want to copy to accepts a custom clipboard format, this is an alternative. You can also of course define many standard and/or non-standard clipboard formats together.

Hubby answered 25/11, 2022 at 5:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.