Reputation: 1100
I have some Python code that edits image files and would like to know how
to add image data to the Operating System clipboard and get it from there.
When searching for a cross-platform solution to replace or get clipboard text in Python,
there were many simple answers to do it (e.g. using the built-in Tkinter module with some code).
However, these methods could only use plain text, not other clipboard data like images.
My version of Python is 3.x on Windows but the answer needs to be cross-platform
(work on different operating systems) and should also support other Python versions like 2.x.
I think it should only use built-in Python modules and the code shouldn't be too complex (or have an explanation of what it does). It can be a Python module because the files can be included in the same folder as portable program code to avoid installing.
There are some other related questions to this one that probably work for images but they only support an individual operating system. The best were Copy image to clipboard in Python3 and Write image to Windows clipboard in python with PIL and win32clipboard?.
The methods described there (for Windows only) appear to use the following steps:
from cStringIO import StringIO
is used but with Python 3, theio.BytesIO
binary stream object type is used - the older ones now only allow text..convert("RGB")
on the variable containing it.bytes
object),win32clipboard
part of an extension module -Also, there's a simple cross-platform clipboard text module called Pyperclip, which is
only a single file for version 1.5.6 and maybe has code that could process image data.
Upvotes: 6
Views: 10272
Reputation: 15533
Question: How to add/get image data in the OS clipboard using Python?
I show only get:
This example is using the built-in Tkinter module to get image data from CLIPBOARD
.
Tested only on Linux, but should be a cross-platform solution.
Note: The first
paste
of the shown 387x388 GIF, takes 4 seconds.
Core point: You have to use a MIME-Type, to requests a image.
.clipboard_get(type='image/png')
Verfied with, 'GIF'
, 'PNG'
and 'JPEG'
, as source image data, using application, GIMP
and PyCharm
. With type='image/png'
you allways get image data of type 'PNG'
if the source app support this.
Reference:
clippboard_get(type=<string>)
Retrieve data from the clipboard. Type specifies the form in which the data is to be returned and should be an atom name such as STRING or FILE_NAME. Type defaults on modern X11 systems to UTF8_STRING.
Data format:
0x89 0x50 0x4e 0x47 0xd 0xa 0x1a 0xa 0x0 0x0 0x0 0xd 0x49 0x48 0x44
The data is divided into fields separated by white space; each field is converted to its atom value, and the 32-bit atom value is transmitted instead of the atom name.
After removing the white space and casting with int(<field>, 0)
:
bytearray(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHD...')
<PIL.PngImagePlugin.PngImageFile image mode=P size=387x388 at 0xF555E20C>
Exception: If no selection at all or the source app does not provide 'image/png'
.
TclError:CLIPBOARD selection doesn't exist or form "image/png" not defined
import tkinter as tk
from PIL import Image, ImageTk
import io
class App(tk.Tk):
def __init__(self):
super().__init__() # options=(tk.Menu,))
self.menubar = tk.Menu()
self.config(menu=self.menubar)
self.menubar.add_command(label='paste', command=self.on_paste)
self.label = tk.Label(self, text="CLIPBOARD image", font=("David", 18),
image='', compound='center')
self.label.grid(row=0, column=0, sticky='w')
def on_paste(self):
self.label.configure(image='')
self.update_idletasks()
try:
b = bytearray()
h = ''
for c in self.clipboard_get(type='image/png'):
if c == ' ':
try:
b.append(int(h, 0))
except Exception as e:
print('Exception:{}'.format(e))
h = ''
else:
h += c
except tk.TclError as e:
b = None
print('TclError:{}'.format(e))
finally:
if b is not None:
with Image.open(io.BytesIO(b)) as img:
print('{}'.format(img))
self.label.image = ImageTk.PhotoImage(img.resize((100, 100), Image.LANCZOS))
self.label.configure(image=self.label.image)
Tested with Python: 3.5 - 'TclVersion': 8.6 'TkVersion': 8.6
Upvotes: 1
Reputation: 1100
Here's a Python function based on this answer that replaces/returns clipboard text using Tkinter.
def use_clipboard(paste_text=None):
import tkinter # For Python 2, replace with "import Tkinter as tkinter".
tk = tkinter.Tk()
tk.withdraw()
if type(paste_text) == str: # Set clipboard text.
tk.clipboard_clear()
tk.clipboard_append(paste_text)
try:
clipboard_text = tk.clipboard_get()
except tkinter.TclError:
clipboard_text = ''
r.update() # Stops a few errors (clipboard text unchanged, command line program unresponsive, window not destroyed).
tk.destroy()
return clipboard_text
This method creates a quickly hidden window which is closed quickly so
that shouldn't be a problem. Also, it only supports using plain text in the
clipboard, not images which I asked for in the question above.
Upvotes: 0
Reputation: 1832
As stated by Martin---
Pyperclip is definitely a good option and works like a charm.
I don't know why you shouldn't be using it.
Its as simple as 3 lines below,
import pyperclip
pyperclip.copy('The text to be copied to the clipboard.')
paste= pyperclip.paste()
Upvotes: -2
Reputation: 680
I don't think you could interact with the clipboard without external module.
Clipboard APIs are different from different Operating systems.
I suggest you to use the clipboard module.
https://pypi.python.org/pypi/clipboard/0.0.4
Upvotes: 0