Reputation: 23084
First of all, the question on SO copy image to clipboard in python leads to answer Write image to Windows clipboard in python with PIL and win32clipboard?, which was only good for Python 2.x. -- I tried it and it didn't work. I overcame one problem: StringIO and cStringIO modules are gone in Python 3.0:, but bumped into another one:
TypeError: string argument expected, got 'bytes'
Hence, re-asking the same question again for Python 3 -- How to copy image to clipboard in Python 3? Here is the code I've got so far:
from io 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)
Thanks
Upvotes: 18
Views: 26093
Reputation: 11
from io import BytesIO
import win32clipboard
from PIL import Image
import pyperclip
def copy_img(filepath):
def send_to_clipboard(clip_type, data):
win32clipboard.OpenClipboard()
# win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(clip_type, data)
win32clipboard.CloseClipboard()
image = Image.open(filepath)
output = BytesIO()
image.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()
send_to_clipboard(win32clipboard.CF_DIB, data)
return None
def copy_text(filepath):
with open(filepath, "r") as file:
st = file.read()
pyperclip.copy(st)
file.close()
return None
Will this break anything on windows?
I commented out the empty clipboard part because I have pinned thing in my clipboard, will it delete them?
Upvotes: 0
Reputation: 121
The winclip32 suggestion doesn't work by itself, but works pretty well combined with the other answers:
from io import BytesIO
import winclip32
output = BytesIO()
image.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()
winclip32.set_clipboard_data(winclip32.BITMAPINFO_STD_STRUCTURE, data)
Upvotes: 1
Reputation: 600
With those imports above, a masterpiece
def send_to_clipboard(clip_type, filepath):
image = Image.open(filepath)
output = BytesIO()
image.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(clip_type, data)
win32clipboard.CloseClipboard()
send_to_clipboard(win32clipboard.CF_DIB, 'imagem.png')
Upvotes: 3
Reputation: 155704
You don't want StringIO
here. Images are raw binary data, and in Py3, str
is purely for text; bytes
and bytes
-like objects (bytearray
, contiguous memoryview
s, mmap
s) are for binary data. To replace Py2's StringIO.StringIO
for binary data, you want to use io.BytesIO
in Python 3, not io.StringIO
.
Upvotes: 12
Reputation: 23463
This is a working app to grab part of the screen as images, once you click on the yellow button it appears in a window made with tkinter, you have to click on top left and then bottom down of an imaginary rectangle that will be the portion of the screen captured. Once you clicked ont the bottom down part of this imaginary rectangle the portion of the screen will be captured. Now open some app like work and press control + v to see the image that has been copied pasted on the app.
# grabscreen.py
import pyscreenshot as ImageGrab
import os
from pynput.mouse import Listener
import sys
import tkinter as tk
from PIL import Image
from io import BytesIO
import win32clipboard
''' Derives from my script grab (use this to show text in a pic and
transform in audio)
'''
def send_to_clipboard(clip_type, data):
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(clip_type, data)
win32clipboard.CloseClipboard()
def grab(x, y, w, h):
im = ImageGrab.grab(bbox=(x, y, w, h))
im.save('im.png')
image = Image.open("im.png")
output = BytesIO()
image.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()
send_to_clipboard(win32clipboard.CF_DIB, data)
click1 = 0
x1 = 0
y1 = 0
def on_click(x, y, button, pressed):
global click1, x1, y1, listener
if pressed:
if click1 == 0:
x1 = x
y1 = y
click1 = 1
else:
grab(x1, y1, x, y)
listener.stop()
sys.exit()
def start():
global listener
# root.destroy()
print("Click once on top left and once on bottom right")
# with Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll) as listener:
with Listener(on_click=on_click) as listener:
listener.join()
# listener.stop()
# sys.exit()
root = tk.Tk()
root.geometry("400x200")
'''
when you click on this button goes to start
in start there i a listener and when you click it sends you to on_click
in on_click it makes you click twice and then goes to grab
in grab it uses pyscreenshot functions to grab the image and save it
we do not use ocr here, to do it use the grab.py file
'''
but = tk.Button(root, text="GRAB GET IMAGE", command=start, width=20,height=10, bg="gold")
but.pack()
root.mainloop()
See ya
Upvotes: 2
Reputation: 166
I did copy the code and replace the StringIO with BytesIO and it worked! (with *.jpg and *.png files) Thank you so much!
from io import BytesIO
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 = 'Ico2.png'
image = Image.open(filepath)
output = BytesIO()
image.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()
send_to_clipboard(win32clipboard.CF_DIB, data)
Upvotes: 15
Reputation: 3856
For those who want to copy-paste
# parameter must be a PIL image
def send_to_clipboard(image):
output = BytesIO()
image.convert('RGB').save(output, 'BMP')
data = output.getvalue()[14:]
output.close()
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
win32clipboard.CloseClipboard()
Upvotes: 5
Reputation: 11
You can copy bitmap image to clipboard using winclip32 install:
pip install winclip32
copy:
import winclip32
winclip32.set_clipboard_data(winclip32.BITMAPINFO_STD_STRUCTURE, your_binary_here)
Upvotes: 1