开发者

How do I set the background colour of a transparent PNG (WPF)?

开发者 https://www.devze.com 2023-02-10 20:00 出处:网络
I\'m loading up some images (jpg, bmp, png etc.), doing some manipulation, and saving them back out again as jpg images. When I save PNG images with a transparent background, they are saved with a bla

I'm loading up some images (jpg, bmp, png etc.), doing some manipulation, and saving them back out again as jpg images. When I save PNG images with a transparent background, they are saved with a black background, and I'd really prefer it to be white. Is there a way to do this?

The important thing is that this is a 'UI-less' routine in a product, so I've not got much leeway when it comes to radically changing the way things are done. Surely there must be a 'set background = white' or something?

A short snippet of my code...

// 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 str开发者_如何学Goeam = new FileStream("SomeOtherFile.jpg", FileMode.Create))
{
    var encoder = new JpegBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create((BitmapSource)image));
    encoder.Save(stream);
}


I've tried to replace transparent pixels directly (with WriteableBitmap CopyPixels/WritePixels), but this wont work with semi-transparent pixels (for example, shadows will produce black outline artifacts).

So I decided to draw my image on top of white rectangle before saving. It works just fine:

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

Usage:

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


There is no simple method to this, further you make some false assumptions when saying that transparent PNGs will be saved with a black background, that is not the case for all PNGs and it is solely dependent on the program that was used for saving the PNG.

If you make a pixel completely transparent that does not necessarily purge all its color from it, the pixel still has its three colour channels, e.g. pictures of the IPU certainly contain colour information, if you use your code to convert that image you'll see it.

One way to set all completely transparent pixels to white would be to get all the pixels as byte array, check the alpha channel of every pixel and if it is 0 you set every other channel of that pixel to 255.

0

精彩评论

暂无评论...
验证码 换一张
取 消