gpt4 book ai didi

c# - 在Windows 10上使用Clipboard.GetImage()后从屏幕快照中删除的文本?

转载 作者:太空宇宙 更新时间:2023-11-03 18:23:05 24 4
gpt4 key购买 nike

这是一个奇怪的:
我最近将工作站从Windows 7升级到Windows10。我有一个Chat客户端,它使用以下代码从剪贴板接受图像:

if (Clipboard.ContainsImage())
{
BitmapSource source = Clipboard.GetImage();
BitmapFrame frame = BitmapFrame.Create(source);
var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
encoder.Frames.Add(frame);
var stream = new MemoryStream();
encoder.Save(stream);
byte[] daten = stream.ToArray();
if (daten != null && daten.Length > 0)
{
sendFile(DateTime.Now.ToString("yyyyMMddHHmmss_") + "clipboard.png", stream.ToArray());
}
}


这是我的屏幕截图的外观(例如,如果我将其粘贴到MS-Paint中或直接从Snipping Tool保存):
Actual Screenshot

在使用 Clipboard.GetImage();导入屏幕截图之后,现在看起来是这样。
Screenshot after using Glipboard.GetImage()

如您所见,所有文本都被删除,如果您仔细观察,可以看到通常是白色的背景现在是透明的。

如果我使用 JpegBitmapEncoder而不是 PngBitmapEncoder,它可以正常工作,因此很可能是编码问题,但是让我感到困惑的是:


这在Windows 7上从未发生过-Windows 10中发生了什么变化
可能会使屏幕截图有所不同?
如果我将截图保存到Snipping Tool中的文件中,则会创建一个PNG(数据本身带有PNG-Header)。那么,为什么PNG不是正确的编码?

最佳答案

我一直在研究Windows剪贴板,我想我知道发生了什么事。请耐心等待,这是一个很长的解释,并且花了很多时间才能获得有关DIB格式的足够信息,而这正是这种混乱的核心。

默认情况下,由于遗留原因,剪贴板根本不支持透明度。最初设计剪贴板时,还没有alpha通道之类的东西。您可能知道,不过,可以将多种格式放在一起放在剪贴板上,以使读取剪贴板的程序有更广泛的获取数据的可能性,而且在最近的Windows版本中,图像显然也放到了剪贴板上。 DIB(与设备无关的位图)格式的剪贴板。现在,.Net框架v3.5通常从剪贴板中获取标准的非透明“图像”格式版本,因此它从未提供透明性,但似乎4.5可能实际上代替了该DIB。

剪贴板上的DIB技术上是每像素32位RGB图像。注意,RGB,而不是ARGB。这意味着每个像素有四个字节,但是在正常填充红色,绿色和蓝色字节的同时,第四个字节实际上是未定义的,因此不应指望实际表示“ alpha”。只是为了使数据与四个字节的倍数精确对齐。

该DIB的内部格式设置为32位“ BITFIELDS”,这与标准的32位“ RGB”类型不同,因为它在标头中专门定义了每种颜色要使用的每个32位像素的哪些位。但是它只定义了三个这样的位字段;用于红色,绿色和蓝色。没有第四个领域。它不应该具有alpha。考虑一下,如果该图像是由实际上只将其视为不带alpha的RGB的系统创建的,并且它不会事先清除其内存(因为许多C / C ++系统不这样做),并且实际上只写那些图像R,G和B字节,则第四个字节可能只是先前操作遗留在内存中的随机垃圾。您甚至无法确保将其清除为值0或设置为标准不透明值255。

这就是问题所在……因为很多应用程序(包括Windows 10和.Net Framework 4.5)确实将其视为此类应用。当我在由具有不同高度的2个屏幕组成的Windows 10桌面上按“打印屏幕”时,所得图像实际上是Windows本身以透明的bastard-BITFIELDS-DIB格式放在剪贴板中的。当我使用将DIB保存为ARGB图像的功能转储图像时,图像上落在我实际监视器之外的区域确实是透明的,而不仅仅是黑色。它是图像的唯一一块,其“ alpha”字节设置为0。因此,这似乎表明Windows 10本身也考虑了支持alpha的格式。

因此,Microsoft自身使用的规范似乎不正确,这似乎是一个问题。 (如果您想知道,是的,他们制定了DIB规范。)他们可以完美地切换到带有较大标头的最新DIB格式,该标头确实支持真正的Alpha,但相反,它们使用的是残酷的老式RGB格式,显然每个人(我是从Google Chrome复制图像时发现的)都假定包含alpha。

反过来,这似乎会导致像您一样的奇怪行为。我怀疑“资源管理器”窗口的绘图机制中的某些内容会用这些内容填充这些alpha字节,甚至可能是其自己的绘图层之一的alpha填充,并且在将最终图像放在剪贴板上时从未清除过。然后,正如您所注意到的,.Net框架4.5显然假设这些额外的字节确实是所获取图像的alpha通道。

解决方案是将这些字节清除为255,或者使系统将结果解释为RGB而不是ARGB。我可以为您提供第二个帮助:我详细介绍了如何在GetImageData函数in this answer中从图像数据中获取字节,并且this one具有用于将字节写回到新图像的BuildImage方法。因此,如果仅使用它来获取32位ARGB数据,然后将其写回到新的32位RGB图像中,则可以使框架将图像数据视为非透明的,而不必修改单个字节。

关于c# - 在Windows 10上使用Clipboard.GetImage()后从屏幕快照中删除的文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44287407/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com