WPF Bitmap Effects Revisited

Technorati Tags: ,,

Ok, so the first pass was ok (apart from the messed up file uploads πŸ™ thanks alot WLW! ) but there are still a few minor niggles. Firstly was the whole com registration deal. Whilst its not really a bit deal in development (you can register the effect as part of the build process) when it comes to deployment, well, it means your xcopy deployable project just got a whole load more complex!.

Whilst looking at the possibility of using isolated com & the reg-free support with manifests, I came across a couple of blog entries by John Melville detailing how to build a managed C++ single assembly for bitmap effects.

So, I brushed off my C++ cap, and jumped straight in. Using a single managed C++ assembly approach is a much more elegant solution, and gives us back the ability to distribute the bitmap effect assembly with our application rather than jumping through the usual com registration hoops.

Anyway, I have created 2 new bitmap effects, and I’ve also re-factored the GreyScale bitmap effect in the last post into a single assembly.

The 2 new Bitmap effects are a

  • SaturationBitmapEffect

    Has a single DependencyProperty called , surprisingly , "Saturation". The range for this value must be from 0.0, to 1.0 which represents an unsaturated image up to a fully saturated image.

    Although you can use the HSLBitmapEffect, the SaturationBitmapEffect uses only 3 multiplies so is significantly faster than doing a full colorspace transform just to reduce the saturation. Just like the GreyScaleBitmapEffect, the SaturationBitmapEffect also uses correctly scaled colour components to represent a the greyscale image.

  • HLSBitmapEffect

    The HLS bitmap effect allows you to control all three components; Hue, Saturation and Lightness. Each RGB colour is transformed into its double hexacone equivalent in the HLS space, and then scaled or shifted by the DependencyProperty’s exposed on the Effect called… heh, you guessed it, Hue,Saturation and Lightness!

Here you see the Bitmap Effect being applied in Blend. If you click the little triangle next to the BitmapEffect Name, you should see the effects dependency properties.

hlseffect

 

Note that both Saturation are [0.0 .. 1.0] whereas the hue is a SHIFT value of [0.0 .. 1.0] where the range represents a 0-360 SHIFT in the hue, ie 0.5 is a 180 degree shift in hue.

Although bitmap effects are very costly in terms of rendering in WPF since they force the whole stack to render your control hierarchy in software – the effects aren’t really all that slow and although the advice to avoid bitmap effects if possible still stands, I find judicious use of them acceptable, especially if used on something that is static.

Speedwise, the GreyscaleBitmapEffect is the fastest since it only involves a straight weighting of the input colours. Next is the SaturationBitmapEffect, which is only marginally slower than the Greyscale effect. I’ve tried this on the top level window to fade it to grey when the application loses focus, and it still runs at an acceptable frame rate on my Laptop (Centrion Duo with Nvidia Quadro NVS 110) ie… not the fastest hardware on the planet, but still desaturates an 800×600 window quite easily.

Lastly is the HLS effect. On a per pixel basis, it’s quite heavy duty, transforming each RGB triplet into the HLS colour space, and then back again, so i suggest using this only for testing or prototyping work. Once you know the HLS values in any bitmap you’re working with, its definitely worth cracking out Paint.NET and baking in those HLS values. I don’t think you’d get away with leaving the HLS bitmap effect in place on anything but top end hardware.

Which brings me to my next point, I’ve read on the Rob Relyea’s MIX08 blog entries that the WPF team will open up the Direct X pipeline and allow us to plug in our own pixel shaders. This will allow some staggeringly cool effects, and easily make transforms like HSL work in real time with no noticable performance loss! If this does make it into the 3.5 update it will really improve WPF’s extensibility beyond writing the odd bitmap effect! I can’t wait!

One last bonus (heh, i’m starting to sound like I should be working on the Shopping Channel; – "but wait THERE’s MORE!") – I’ve put together a skeleton single assembly BitmapEffectProject , and a bunch of steps to modify the code (if you’re not au-fait with C++)

All the steps are in Visual Studio’s TODO list format, so they’re right there in the source code. IIRC Step #9 is the bit where you twiddle the pixels which should probably be the last thing you do, but I couldn’t be bothered re-numbering the steps πŸ˜‰

One minor point to note is you may see this dialog pop up when you open the test project in blend

loaderror

All this means is that Blend doesn’t understand managed C++ projects. This can be safely ignored since you’ll really be twiddling the pixels inside VisualStudio anyway.

To use the bitmap effect simply add a project reference to the desired DLL, and add an appropriate namespace directive in your XAML file like so :

xmlns:HLSEffect="clr-namespace:HLSBitmapEffect;assembly=HLSBitmapEffectLib"

then add the bitmap effect to your bitmap.

        <Image Name="aPic" Source="images/Source.jpg">
            <Image.BitmapEffect>
                <HLSEffect:HLSBitmapEffect>
                    <HLSEffect:HLSBitmapEffect.Saturation>
                        <Binding ElementName="satSlider" Path="Value"/>
                    </HLSEffect:HLSBitmapEffect.Saturation>
                </HLSEffect:HLSBitmapEffect>
            </Image.BitmapEffect>
        </Image>

…and you should be good to go!

Enjoy!

This entry was posted in General. Bookmark the permalink.

11 Responses to WPF Bitmap Effects Revisited

  1. Pingback: Make your own WPF Custom BitmapEffects | robburke.NET

  2. Rob Burke says:

    This is excellent! I suggested in my blog that you package up the Skeleton Project as a Visual Studio Project Template. Thank you for putting the time into this, it is very useful.

  3. rob says:

    Hi Rob,
    Thanks for the nice comment πŸ™‚ Nice to see i’ve made a mention on someones else’s blog hehe!
    I never thought of packaging it up as a VSProject template – I’ll look into this when i have a bit more time!
    At the mo I’m in the middle of a full on WPF based LOB application, and it’s soaking up all my time πŸ™ If I don’t get round to templating it soon, I may end up waiting until i can include pixel shaders to to the dirty work. I think at that point BM FX will be treated as first class WPF citizens, and we’ll really see what the framework will let us do πŸ™‚
    cheers,
    Rob

  4. Rob Burke says:

    Hey Rob — you’re right, we’re all really waiting on the shader effects support, so no need to sink time into it. However, I would be really keen to hear how your LOB app dev goes. You should blog a postmortem on it when you’re finished!

    Is the code to your HLSBitmapEffectLib.dll available? Until custom shader effects hit WPF, would it be OK if I used it in a project I’m working on?

    with best wishes
    Rob

  5. Rob Burke says:

    p.s. the title of your blog makes me want to turn on Rock Band every time I hear it in my head πŸ˜‰

  6. rob says:

    Hi Rob,
    No Problems with using any of my code (nice that someone actually wants to πŸ˜‰ ) – I should really get round to adding a licence to the code/dll’s I make available just to make that explicit, but I don’t know much about them , so I’ve never bothered.
    For the record, the Bitmap Effects are free to completely free to use in any project commercial or otherwise, with no restrictions. The usual disclaimers about ending all life on the planet apply. πŸ™‚

    Cheers!
    Rob

  7. Pwhndvve says:

    Honi soit look closer buy cytotec meat steamed held.

  8. morgan says:

    Hi Rob,

    Your HLSBitmapEffect is superb and exactly what i need in my project (and this is the only realization of this effect i found).

    But i have a problem with it:/

    When you want to create a redish color (HUE value nears 0 or 1) you got the original colors not the red ones.

    Could you check this problem or if you don’t have time publish this effect’s source code so i can check it?

    Thanks!
    Morgan

  9. Adrian says:

    When I try adding a reference to GreyscaleEffectLib.dll to my VS2005 project, I get this error message:
    “A reference to ‘C:…GreyscaleEffectLib.dll’ could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component.”

  10. Adrian says:

    I did get SaturationBitmapEffect working, although I first had to install some of VS2005’s C++ components.

  11. Rob says:

    Hi Adrian, Sorry for the day in responding. One way to avoid this issue is to run depends.exe (part of the VS install) on the dll – it will show you any missing DLL’s or other dependencies that may exist. You can usually track this kind of thing down in minutes like this!
    Thanks!

    Rob

Leave a Reply