views:

534

answers:

3

I'm having an issue with converting a BitmapImage (WPF) to grayscale, whilst keeping the alpha channel. The source image is a PNG.

The MSDN article here works fine, but it removes the alpha channel.

Is there any quick and effective way of converting a BitmapImage to a grayscale?

+1  A: 

if relying on API calls fails. You can always try the 'do it yourself' approach: Just get access to the RGBA bytes of the picture, and for every RGBA replace it with MMMA, where M = (R+G+B)/3;

If you want it more perfect, you should add weights to the contribution of the RGB components. I believe your eye is more receptive for green, and as such that value should weigh more.

Toad
Thanks for that. I'm looking into the WriteableBitmap class as the easiest way to access the pixels directly.
Alastair Pitts
+2  A: 

You should have a look at image transformation using matrices.

In particular, this article describes how to convert a bitmap to grayscale using a ColorMatrix. (It is written in VB.NET, but it should be easy enough to translate to C#).

I haven't tested if it works with the alpha channel, but I'd say it's worth a try, and it definitely is a quick and effective way of modifying bitmaps.

Bernhof
I have used this on System.Drawing.Image and it works great. Not ideal for WPF images unless you are converting GDI bitmaps to BitmapSources.
Zooba
My experience with WPF is very limited, so you're probably right.
Bernhof
Marking this as the answer as I was forced to use GDI Bitmaps and convert them into WPF BitmapsSources post change
Alastair Pitts
A: 

While not exactly quick and easy, a ShaderEffect would do the job and perform quite well. I've done it myself, and it works great. This article references how to do it and has source associated. I've not used his source, so I can't vouch for it. If you run into problems, ask, and I may be able to post some of my code.

Not every day you get to use HLSL in your LOB app. :)

dustyburwell
As an aside...this is assuming that you're wanting to display the image in your app after converting it to grayscale. If you're wanting to do this as an image processing step and then save the image or something there may be more work to try to get a ShaderEffect to work outside of the WPF effect pipeline. At that point, GDI or one of the other answers may be your best bet, anyway.
dustyburwell