我的应用程序应该能够将32位图像(RGB + alpha通道)复制到剪贴板并从剪贴板粘贴这些图像.为此我打算使用,CF_DIBV5因为BITMAPV5HEADER结构有一个字段bV5AlphaMask.
问题是,对于图像数据应该如何存储在剪贴板中似乎没有达成共识.在进行一些测试时,我发现应用程序之间存在一些差异,使得它几乎无法提出通用解决方案.
以下是我的观察:
当我将Alpha 2010通道图像从Word 2010或XnView复制到剪贴板时,它将被存储而不会预乘像素数据.
但是,当我使用Firefox或Chrome复制图像时,像素数据似乎被alpha通道预乘.
Firefox设置bV5AlphaMask为0xff000000,而大多数其他应用程序根本不设置它,但保留0.这很奇怪,因为这些应用程序将DIB放到剪贴板上,实际上包含最高8位的alpha通道但仍然设置bV5AlphaMask为0.必须假设如果位深度为32,即使bV5AlphaMask为0 ,也存在alpha通道.
简而言之,我的基本问题是:是否有关于如何将Alpha通道数据存储在剪贴板上的官方信息?我特别想知道数据是否必须预乘.正如您在上面所看到的,Word 2010和XnView不会预先相互映射,而Firefox和Chrome则可以.但是,知道颜色通道是否应该预乘是至关重要的.
非常感谢您对此有所了解!
更新2 粘贴到Paint.NET现在工作正常.它是由我的代码中的一个错误引起的,如果alpha通道为0,则没有将颜色通道设置为0,即在这种情况下前导相应没有正确完成,这似乎混淆了Paint.NET.
仍未解决的问题是Internet Explorer 10.当将带有alpha通道的PNG复制到剪贴板时,IE 10只是将24位CF_DIBV5放在剪贴板上,但Paint.NET可以将此位图粘贴到alpha通道,因此必须有另一种格式IE 10暴露给剪贴板.也许它暴露了PNG使用CFSTR_FILECONTENTS和CFSTR_FILEDESCRIPTOR.
更新 我现在已经按照下面arx描述的方式实现了它,它运行得很好.然而,仍然有两件事令我困惑:
1)将我的应用程序中的alpha通道图像粘贴到Paint.NET中不会保留alpha通道.Paint.NET中的图像看起来不透明.但是,从Firefox和Chrome粘贴到Paint.NET完美地运行,alpha通道被保留了!我已经抛弃了完整的DIBV5并且它与我的应用程序完全相同,但它仍适用于FF和Chrome,但不适用于我的应用程序,因此必须有其他内容!Firefox和Chrome必须做一些我的应用不做的事情!?
2)对于Internet Explorer 10也是如此.将IE 10中的Alpha通道图像粘贴到我的应用程序根本不起作用...我得到的深度为24的DIB,即没有alpha通道所有.然而,当从IE 10粘贴到Paint.NET时,alpha通道就在那里!所以这里必须有更多东西......
我有一些编辑图像文件的 Python 代码,并且想知道如何将
图像数据添加到操作系统剪贴板并从那里获取它。
当在 Python 中搜索跨平台解决方案来替换或获取剪贴板文本
时,
有许多简单的答案可以实现(例如,使用内置的 Tkinter 模块和一些代码)。
然而,这些方法只能使用纯文本,而不能使用图像等其他剪贴板数据。
我的 Python 版本在 Windows 上是 3.x,但答案需要是跨平台的
(在不同操作系统上工作),并且还应该支持其他 Python 版本,如 2.x。
我认为它应该只使用内置的Python模块,并且代码不应该太复杂(或者对其作用进行解释)。它可以是 Python 模块,因为这些文件可以包含在与可移植程序代码相同的文件夹中以避免安装。
还有一些其他相关问题可能适用于图像,但它们仅支持单个操作系统。最好的是在Python3中将图像复制到剪贴板和使用PIL和win32clipboard在python中将图像写入Windows剪贴板?。
那里描述的方法(仅适用于 Windows)似乎使用以下步骤:
from cStringIO import StringIO使用,但对于 Python 3,使用io.BytesIO.convert("RGB")包含它的变量。bytes对象),首先,在python中将 SO 复制图像复制到剪贴板的问题导致回答使用PIL和win32clipboard在python中将图像写入Windows剪贴板?,这对Python 2.x只有好处. - 我试了一下它没用.我克服了一个问题:StringIO和cStringIO模块在Python 3.0中消失了:但是碰到了另一个:
TypeError: string argument expected, got 'bytes'
Run Code Online (Sandbox Code Playgroud)
因此,再次为Python 3重新提出同样的问题 - 如何在Python 3中将图像复制到剪贴板?这是我到目前为止的代码:
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)
Run Code Online (Sandbox Code Playgroud)
谢谢
我已经看到这个问题,我遵循了每一步,更改代码以满足我的要求,即 Python3、Pillow 和 ctypes。库越少越好。
import ctypes
from PIL import ImageGrab, Image
from io import BytesIO
user32 = ctypes.windll.user32
img = ImageGrab.grab()
output = BytesIO()
img.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()
user32.OpenClipboard()
user32.EmptyClipboard()
user32.SetClipboardData(user32.CF_DIB, data)
user32.CloseClipboard()
Run Code Online (Sandbox Code Playgroud)
这是从我的脚本中删除的代码,我认为它与移植到我的要求的问题中的代码相同。执行时,它应该将当前桌面复制到剪贴板。我得到这个:
File "C:\Users\Gcq\Documents\python\Screen\Screen.py", line 132, in shot
user32.OpenClipboard()
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
Run Code Online (Sandbox Code Playgroud)
很抱歉我在这里问这样一个(可能)简单的问题,但我真的不知道什么失败了,而且 ctypes 不是我的菜。