Edward
Edward

Reputation: 1100

How to add/get image data in the OS clipboard using Python?

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:

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

Answers (5)

stovfl
stovfl

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.

enter image description here enter image description here

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

Edward
Edward

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

Chris Johnson
Chris Johnson

Reputation: 22016

The xerox library is simple and capable.

Upvotes: 0

Md. Mohsin
Md. Mohsin

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

fluke
fluke

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

Related Questions