Как мне установить цвет фона прозрачного PNG (WPF)?

Я загружаю некоторые изображения (jpg, bmp, png и т. Д.), Выполняю некоторые манипуляции и сохраняю их снова как изображения jpg. Когда я сохраняю изображения в формате PNG с прозрачным фоном, они сохраняются на черном фоне, и я бы предпочел, чтобы он был белым. Есть ли способ сделать это?

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

Короткий фрагмент моего кода...

// Load the image
var image = new BitmapImage();
image.BeginInit();        
image.CacheOption = BitmapCacheOption.None;
image.UriSource = "SomeImage.png";
image.EndInit();


// Some manipulation of the image here...
image.Shake().Twist().ThrowItAllAbout();


// Save it back out, in a different format
using (FileStream stream = new FileStream("SomeOtherFile.jpg", FileMode.Create))
{
    var encoder = new JpegBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create((BitmapSource)image));
    encoder.Save(stream);
}

2 ответа

Решение

Для этого нет простого метода, кроме того, вы делаете некоторые ложные предположения, когда говорите, что прозрачные PNG будут сохранены на черном фоне, что не относится ко всем PNG и зависит исключительно от программы, которая использовалась для сохранения PNG.,

Если вы делаете пиксель полностью прозрачным, который не обязательно очищает весь его цвет от него, у пикселя все еще есть три цветовых канала, например, изображения IPU, безусловно, содержат информацию о цвете, если вы используете свой код для преобразования этого изображения, которое вы увидите Это.

Один из способов установить все полностью прозрачные пиксели в белый цвет - это получить все пиксели в виде байтового массива, проверить альфа-канал каждого пикселя, и если он равен 0, вы установите для каждого другого канала этого пикселя значение 255.

Я пытался заменить прозрачные пиксели напрямую (с помощью WriteableBitmap CopyPixels/WritePixels), но это не будет работать с полупрозрачными пикселями (например, тени будут давать артефакты с черным контуром).

Поэтому я решил нарисовать свое изображение поверх белого прямоугольника перед сохранением. Работает просто отлично:

public static BitmapSource ReplaceTransparency(this BitmapSource bitmap, Color color)
{
    var rect = new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight);
    var visual = new DrawingVisual();
    var context = visual.RenderOpen();
    context.DrawRectangle(new SolidColorBrush(color), null, rect);
    context.DrawImage(bitmap, rect);
    context.Close();

    var render = new RenderTargetBitmap(bitmap.PixelWidth, bitmap.PixelHeight,
        96, 96, PixelFormats.Pbgra32);
    render.Render(visual);
    return render;
}

Использование:

var white = bitmap.ReplaceTransparency(Colors.White);
var enc = new JpegBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(white));
using (var fs = File.Create(filename))
    enc.Save(fs);
Другие вопросы по тегам