Создание растровых изображений с пурпурным фоном в WPF прозрачным

Я нахожусь в процессе преобразования некоторого устаревшего программного обеспечения, которому 15 лет, в WPF, и его графика часто представляет собой 8-битные растровые изображения с пурпурным фоном, что-то вроде этого:

Тест прозрачности

В Gdi32 было принято использовать пурпурный цвет как ключ прозрачности для рисования графики. С System.Drawing это будет один лайнер, т.е. _myImg.MakeTransparent(Color.Magenta), Но как насчет WPF? Есть ли даже такая вещь, как стандартная практика для вышеупомянутого сценария?

Я действительно надеялся, что это сработает из коробки:

    <Image Width="128">
        <Image.Source>
            <BitmapImage UriSource="Media\opacityTest.bmp" />
        </Image.Source>
        <Image.OpacityMask>
            <SolidColorBrush Color="Magenta" />
        </Image.OpacityMask>
    </Image>

Увы, хотя это разрешено, оно ничего не делает

Результат

Я что-то упустил или это невозможно в WPF?

В конечном счете мне, возможно, придется написать код для преобразования этих растровых изображений в прозрачные png-файлы, где-то их кешировать и вместо этого загрузить. Если это так, кто-нибудь знает какие-либо ресурсы, которые могут помочь мне достичь этого, кроме Gdi+?

Есть похожий вопрос: сделать часть изображения прозрачной. Но нет однозначного ответа (или я действительно не могу поверить, что это невозможно).

1 ответ

Я закончил тем, что создал новое изображение (32bit pargb) на основе исходного изображения и цветового ключа, вот код для чего бы это ни стоило:

BitmapSource MakeTransparent(BitmapSource img, Color maskColor)
{           
    var format = PixelFormats.Pbgra32;
    var stride = ((img.PixelWidth * format.BitsPerPixel + 31) & ~31) >> 3;
    var pixels = new byte[img.PixelHeight * stride];

    img.CopyPixels(pixels, stride, 0);

    for (var i = 0; i < stride * img.PixelHeight; i += 4)
        if (Color.FromRgb(pixels[i + 2], pixels[i + 1], pixels[i]) == maskColor)
            for (var j = i; j < i + 4; j++)
                pixels[j] = 0;

    return BitmapSource.Create(
        img.PixelWidth, img.PixelHeight,
        img.DpiX, img.DpiY,
        format,
        null,
        pixels,
        stride);
}

Не использует System.Drawing поэтому Gdi+ не требуется, он просто изменяет массив пикселей, заменяя указанный maskColor с предварительно умноженными значениями alpha rgb, установленными в 0.

Пример использования:TestImage = MakeTransparent(new BitmapImage(new Uri(@"opacityTest.bmp", UriKind.Relative)), Colors.Magenta);

Результат:

Другие вопросы по тегам