如何将PIL图像复制到剪贴板?

3

我正在使用Tkinter中的画布,并尝试将该画布的内容复制到剪贴板。

我可以通过创建文件并将该文件的内容复制到剪贴板来解决此问题,例如用xclip -selection clipboard -t image/png -i temp_file.png,但我想使用缓冲区,使用户能够直接将其复制到剪贴板而不触及用户的文件系统。

要使用xclip的输入功能,我需要提供一个文件名,而不是一个字符串。我可以通过在Bash命令行中使用echo/cat作为cat temp_file.png < echo | xclip -selection clipboard -t image/png -icat file_name.png | xclip -selection clipboard -t image/png -i来规避这个问题。

我已经成功地使用缓冲区存储画布,如下所示:

memory = io.BytesIO()
img.save(memory, format="png")
return memory

并且可以将图片保存到文件中,方法如下:

img = pil.Image.open(memory)
img.save("file_name.png", format="png")

据我所了解,根据PIL的文档,pil.Image.open与内置函数open()是相同的。然而,当尝试使用open()来读取文件时,它声称BytesIO不是有效的文件。不过,我想这不是什么大问题。
我可以使用memory.getvalue()读取缓冲区的内容,然后用[2:-1]去掉周围的b'...'。我再用\'替换字符串中所有的',这样就可以用单引号将其括起来,并最终通过之前对某个文件使用的命令来输出该字符串。
img_data = str(img_memory.getvalue())[2:-1]
img_data = img_data.replace("'", "\'")#.replace("`", "\`")
img_data = "'" + img_data + "'"
< p > cat file_name.png 的输出与我在子进程中给出的字符串的echo 命令的输出几乎相同,但是以下操作对我似乎没有用,因为我的剪贴板保持不变:

bash_cmd = f"echo -n {img_data} | xclip -selection clipboard -t image/png -i"
p = sp.Popen(bash_cmd, shell=True, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE)

但是
bash_cmd = f"xclip -selection clipboard -t image/png -i file_name.png"
p = sp.Popen(bash_cmd, shell=True, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE)

有用。

简而言之

我做错了什么?我是否修改了文件内容,从而创建了一个损坏的图像,然后进行复制?

我应该如何正确地将io.BufferIO的内容输出到剪贴板中(主要是在Unix/Linux上,但也适用于MacOS/Windows)?

1个回答

1

我成功地通过调整Can I pipe a io.BytesIO() stream to subprocess.popen() in Python?的答案,使用xclip从Python中复制了图像数据。这里不需要使用echo,只需将memory的内容写入进程stdin即可:

memory = io.BytesIO()
img.save(memory, format="png")

output = subprocess.Popen(("xclip", "-selection", "clipboard", "-t", "image/png", "-i"), 
                          stdin=subprocess.PIPE)
# write image to stdin
output.stdin.write(memory.getvalue())
output.stdin.close()

对于更多平台的解决方案,我发现klembord软件包可在Linux和Windows上使用。以下命令将图片复制到剪贴板中(仅在Linux中测试通过):

import klembord
klembord.set({"image/png": memory.getvalue()})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接