WPF/GDI互操作:如何获得正确的Alpha值?

3
我已经创建了一个半透明的测试图像,填充了128-alpha黑色。我在两种方法之间交替绘制:WPF本机和GDI互操作。它们完全不同; WPF正确地完成了它,但是GDI似乎首先与白色混合,然后再进行绘制:
如果在照片上绘制,则GDI部分会使其下面的内容变得更亮,即使0,0,0,128颜色应该使其下面的任何内容变暗:
代码如下:
if (iteration % 2 == 0)
    context.DrawImage(new BitmapImage(new System.Uri("I:/test.png")),
                      new Rect(0, 0, 80, 24));
else
{
    var bmp = (D.Bitmap) D.Bitmap.FromFile("I:/test.png");
    var handle = bmp.GetHbitmap();
    var bmpSource = Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero,
                    Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
    context.DrawImage(bmpSource, new Rect(0, 0, 80, 24));
    WinAPI.DeleteObject(handle);
    GC.KeepAlive(bmp);
}

对于第二张图片,我更改了WPF的矩形大小,以显示它们不重叠。
如何正确绘制半透明的GDI图像?
(是的,由于某些复杂的原因,它必须是GDI图像 - 实际上它不是来自文件,而是来自一些外部代码,但这个问题可以很容易地通过一个文件来再现)
2个回答

1

我已经决定现在避免调用它,只是复制原始位图数据。 代码:

var writable = new WriteableBitmap(bmp.Width, bmp.Height,
                      bmp.HorizontalResolution, bmp.VerticalResolution,
                      PixelFormats.Bgra32, null);

var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                      ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

writable.WritePixels(new Int32Rect(0, 0, bmp.Width, bmp.Height),
                      data.Scan0, data.Stride * bmp.Height, data.Stride);

GC.KeepAlive(bmp);
context.DrawImage(writable, new Rect(0, 0, 80, 24));

(这可能需要使用一两个)using

另外,如果可写位图直接用作 Image 的源,则调用 Freeze 有助于防止更新时的闪烁,尽管我不认为这是必要的。


0
我该如何正确地绘制半透明的GDI图像?
Bitmap targetBitmap = ...
Bitmap bitmap = new Bitmap(filename);
using (var g = Graphics.FromImage(targetBitmap))
    g.DrawImage(...);

换句话说,不要费心于GDI到WPF的互操作(显然它并不起作用)。将中间位图保存到文件中,并在需要WPF时仅使用WPF,在需要GDI时仅使用GDI。

至少你不是在建議我使用JPEG作為我的中間格式...信不信由你,但有一堆搜索結果確實建議這樣做!... - Roman Starkov

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