Взаимодействие WPF / GDI: как получить правильную альфу? - PullRequest
3 голосов
/ 31 декабря 2011

Я создал полупрозрачное тестовое изображение, заполненное 128-альфа-черным. Я рисую, чередуя два метода: родной WPF и GDI-взаимодействие. Они выходят совершенно разными; WPF-файл сделан правильно, но GDI, по-видимому, сначала смешивается с белым, а затем рисуется:

example 1

Если нарисовано на фотографии, часть GDI осветляет то, что находится под ней, даже если цвет 0,0,0,128 должен затемнить то, что находится под ней:

example 2

Код выглядит так:

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);
}

Для второго изображения я изменил размер Rect для WPF, чтобы показать, что они не перекрываются.

Как правильно нарисовать полупрозрачное изображение GDI?

(да, это действительно должно быть изображение GDI по сложным причинам - на самом деле это не файл, а какой-то внешний код, но проблема легко воспроизводится из файла)

Ответы [ 2 ]

1 голос
/ 02 января 2012

Я решил избежать этого вызова и просто скопировать необработанные растровые данные. Код:

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 голосов
/ 31 декабря 2011

Как правильно нарисовать полупрозрачное изображение GDI?

Как это:

Bitmap targetBitmap = ...
Bitmap bitmap = new Bitmap(filename);
using (var g = Graphics.FromImage(targetBitmap))
    g.DrawImage(...);

Другими словами, не беспокойтесь о взаимодействии GDI-to-WPF (оно явно не работает). Сохраняйте промежуточные растровые изображения в файлы и используйте только WPF, когда вам нужны только WPF и GDI, когда вам нужен GDI.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...