将 DIB 转换为 DDB?

问题描述 投票:0回答:3

我正在开发一个剪贴板管理器(可以在这里看到:http://flamefusion.net/software/shapeshifter)。

但是,我目前遇到位图 (

bmp
) 的问题,该位图无法真正正确地将其自身插入剪贴板。我的第一个方法如下,使用
SetClipboardData

var hBitmap = bmp.GetHBitmap();
SetClipboardData(CF_BITMAP, hBitmap);

我知道其中潜在的内存泄漏,并且它只是作为测试而进行的。测试失败了。粘贴到剪贴板中的图像在粘贴时无法被 Paint 读取。

经过大量的研究和失败的尝试,我得到了一个新的理论。我使用的位图是从

MemoryStream
创建的,它是通过之前调用
Bitmap.Save(Stream, ImageFormat)
方法创建的。这让我相信
System.Drawing.Bitmap
GetHBitmap
不是
HBITMAP
函数期望的那种
SetClipboardData

所以我尝试了以下方法,取得了一些成功。

var memDC = CreateCompatibleDC(IntPtr.Zero);
var memBitmap = CreateCompatibleBitmap(memDC, bmp.Width, bmp.Height);
SetClipboardData(CF_BITMAP, memBitmap);

现在图像已插入正确的尺寸,但作为黑色图像。这是非常明显的,因为除了宽度和高度之外,

bmp
中的任何内容实际上都没有用于创建“兼容”位图。

我假设我必须以某种方式使用 BitBlt 将原始位图复制到现在“兼容”的位图,但我不知道从哪里开始。

你们中有 GDI 巫师知道吗?这里显然需要魔法。

编辑1 正如 dthorpe 很好地指出的那样,我的问题似乎是我试图保存的图像实际上是 DIB。现在问题变了。我需要弄清楚如何从 DIB 转换为 DDB。我知道在执行此操作时会损失 alpha,但它仍然是必要的。

编辑2 使用

Clipboard.SetImage
是不可接受的。这在我的场景中不起作用。我需要使用 API。

c# pinvoke gdi+ clipboard gdi
3个回答
2
投票

CF_BITMAP 可能是位图使用的错误格式。 CF_BITMAP 剪贴板格式指定设备位图,但当今几乎所有位图都是 DIB - 与设备无关的位图。设备位图与系统/硬件设备调色板相关(例如 EGA 图形),并且必须与当前显示模式的像素格式匹配。 DIB 携带自己的颜色信息,其像素格式与显示模式无关。

文档说,如果应用程序在从剪贴板读取时请求 CF_DIB,则剪贴板管理器会将 CF_BITMAP 转换为 CF_DIB,但这假设原始图像实际上是当前显示模式像素格式的设备位图。如果不是,转换将产生垃圾,因为输入是垃圾。

再次尝试使用 CF_DIB 而不是 CF_BITMAP。


2
投票

我认为你把这个问题过于复杂化了。实际上根本不需要 p/invoke – 框架已经为您处理了这个问题。您可以将其作为一句台词来完成:

Clipboard.SetImage(bmp);

0
投票

最后你是如何解决这个问题的?

© www.soinside.com 2019 - 2024. All rights reserved.