如何使用Python在OS剪贴板中添加/获取图像数据?

时间:2014-06-29 08:51:10

标签: python python-3.x clipboard clipboarddata

我有一些编辑图像文件的Python代码,想知道如何使用 将图像数据添加到操作系统剪贴板并从那里获取它。

在Python中搜索替换或获取剪贴板 text 的跨平台解决方案时 有很多简单的答案可以做到(例如使用带有some code的内置Tkinter模块) 但是,这些方法只能使用纯文本,而不能使用其他剪贴板数据,如图像。

我的Python版本在Windows上是3.x,但答案需要是跨平台的 (适用于不同的操作系统),还应支持其他Python版本,如2.x.
我认为它应该只使用内置的Python模块,并且代码不应该太复杂(或者解释它的作用)。它可以是Python模块,因为文件可以包含在与可移植程序代码相同的文件夹中,以避免安装。

还有一些与此相关的问题可能适用于图像,但它们仅支持单个操作系统。最好的是Copy image to clipboard in Python3Write image to Windows clipboard in python with PIL and win32clipboard? 其中描述的方法(仅适用于Windows)似乎使用以下步骤:

  • 获取图像的原始二进制数据 - 该方法使用Python Imaging
    加载图像文件 库(PIL/Pillow)模块,因为这有其他处理功能,稍后会用到简单的中 和流行的标准API。这可以通过不同的模块来完成(例如 Pygame )。
  • 使用内置的 io 创建文件对象变量(用于内存输入/输出流) 模块。对于Python 2.x,使用了from cStringIO import StringIO,但是使用Python 3, 使用了更好的io.BytesIO二进制流对象类型 - 旧版本现在只允许文本。
  • 以BMP(Windows位图/设备无关位图)文件格式保存图像数据,
    到上一步的文件对象变量。使用PIL / Pillow的方法首先转换为
    这个数据包含.convert("RGB")包含它的变量。
  • 获取文件对象变量内存缓冲区的全部内容作为二进制数据(bytes对象),
    从位置14切片以删除BMP / DIB文件格式的14字节标头,然后保存它 作为变量。该方法表明,此数据的切片适用于32或64位系统,但是 需要Windows剪贴板API,因此不适用于不同的文件格式。
  • 关闭内存缓冲区并将上一步中的图像数据复制到剪贴板 该方法使用扩展模块的win32clipboard部分在Windows上执行此操作 -
    它打开剪贴板供使用,清除它,将其值设置为来自
    的图像数据变量 上一步(使用BMP / DIB类型)然后关闭打开的剪贴板。

此外,还有一个简单的跨平台剪贴板文本模块,名为 Pyperclip ,它是
版本1.5.6只有一个file,并且可能有代码可以处理图像数据。

5 个答案:

答案 0 :(得分:0)

我不认为你可以在没有外部模块的情况下与剪贴板互动。

剪贴板API与不同的操作系统不同。

我建议你使用剪贴板模块。

https://pypi.python.org/pypi/clipboard/0.0.4

答案 1 :(得分:0)

xerox库简单而且功能强大。

答案 2 :(得分:0)

这是一个基于this answer的Python函数,它使用 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

此方法创建一个快速隐藏的窗口,因此很快关闭 那应该不是问题。此外,它仅支持使用纯文本 剪贴板,而不是我在上面的问题中要求的图像。

答案 3 :(得分:0)

问题:如何使用Python在操作系统剪贴板中添加/获取图像数据?

我只显示得到
此示例使用内置的Tkinter模块从CLIPBOARD获取图像数据。
仅在 Linux 上进行了测试,但是应该是跨平台的解决方案。

enter image description here enter image description here

注意:显示的387x388 GIF中的第一个paste耗时4秒。


核心点:您必须使用MIME类型来请求图像。

.clipboard_get(type='image/png')

使用应用程序'GIF''PNG'验证了'JPEG'GIMPPyCharm作为源图像数据。如果源应用程序支持,type='image/png'始终可以得到'PNG'类型的图像数据。


参考

  • clippboard_get(type=<string>)

    从剪贴板中检索数据。类型指定返回数据的形式,并且应为原子名称,例如STRING或FILE_NAME。在现代X11系统上,默认键入UTF8_STRING。


数据格式

0x89 0x50 0x4e 0x47 0xd 0xa 0x1a 0xa 0x0 0x0 0x0 0xd 0x49 0x48 0x44

数据分为用空格隔开的字段;每个字段都被转换为其原子值,并传输32位原子值而不是原子名称。

删除空白并使用int(<field>, 0)进行投射后:

bytearray(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHD...')
<PIL.PngImagePlugin.PngImageFile image mode=P size=387x388 at 0xF555E20C>

例外:如果根本没有选择,或者源应用未提供'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)

使用Python测试:3.5-'TclVersion':8.6'TkVersion':8.6

答案 4 :(得分:-1)

如马丁所述---

Pyperclip绝对是一个不错的选择,就像魅力一样。

我不知道为什么你不应该使用它。

它简单如下3行,

import pyperclip
pyperclip.copy('The text to be copied to the clipboard.')
paste= pyperclip.paste()