Animated gifs in XAML/C# :)


image

Someone the other day tweeted a link to some very cool animated gifs. I love animated gifs Smile !!

I have always wanted animated gifs in Silverlight/WPF BUT for reasons unknown they never came. They would have been perfect for A LOT of scenarios where creating storyboard animations would have been overkill.

Well turns out WinRT XAML, firmly rooted in Silverlight XAML, also doesn’t have GIF support nor will it probably ever get it. BUT it does have WinRT support and it has access to DirectX & WIC via SharpDx!!

And today on Twitter Jeremiah Morrill tweeted that WIC has support for GIF’s, this intrigued me. Can I build my own support for animated gifs in XAML using DirectX & WIC (via SharpDx) ?!

Challenge is on ……

This is the animated gif I will try to render…

Source : “Savannah Rain” (frommetoyou)

Default XAML/C# metro app project + SharpDx

I created an empty managed metro project and added the necessary SharpDx bits, basically like I have been over the last several posts.

As always this project has a effect renderer that will render to a (Direct2D or Direct3D) surface via a (SwapChainBackgroundPanel or SurfaceImageSource). Again this is what I’ve been doing in all my SharpDx posts to date so just go back to those or the samples if you’ve forgotten Smile

image

 

Animated GIF resource

Now just add the Animated GIF as a content resource to the project. I could load it in via a URI BUT I thought it would be easier to just include it for now .

image

 

Load GIF via WIC

Ok this is where it gets interesting, SharpDx gives us access to WIC from C#. Question is does it have the GIF bits.

As I’ve said many times before SharpDx is a very thin/performant wrapper over C++ libraries (but just to clarify there will always be an overhead to using WIC via this wrapper even thou it is small). This wrapper is a metadata mapping generated api so technically the GIF bits of WIC should have come across. Lets test it out.

Lets instantiate a WIC GIFDecoder that will be used to read the animated GIF resource. The “asset” is simple the internal uri to the gif content.

image

Next when we animate this gif we need to know how many frames to animate. The GIF spec defines this…

image

Now for each frame we want to get the bitmap of that layer and store it for rendering. There is a lot going on in this code BUT in a nutshell an object is created that lets us get at the bytes of data for a particular frame in the gif. (its easy to follow just step through the code , that’s how I learnt

image

As it turns out for GIFS the first layer normally has the entire bitmap contents of the GIF and all the other frames above that contain delta information.. Also the ‘delta’ frames are all offseted so we need to get the offset (left,top) of those frames and store them for rendering of that frame later on..

image

 

So assuming that SharpDx’s GIF WIC works fine that’s basically all we need information wise.. We just need a way to store those frames and render them to the UI.

…. hello SpriteBatch Smile

SpriteBatch

The best way to render a series of textures in the graphics world is via a spritebatch. Lets create a very very dirty one that will serve our purposes ..

I’m not going to go into too much detail of how this dirty spritebatch works, it’s not in the truest sense a spritebatch BUT it will do for now..

image

This spritebatch will keep a cache of the GIFs frames that I will render on a DirectX Surface. I’ve defined 2 lists to store the static frames ( 0 ) and the rotating frames ( 1 – 7 )

image

I’ve created a way to add sprites (frames) to my spritebatch via the methods

1. DrawAlways  – sprites that will always get rendered on each loop of the rendering pipeline eg. frame 0 of the aimated gif

2. DrawRotating – sprites that will rotate there appearance with each loop of the rendering pipeline eg. frames 1 to 7 of the animated gif

image

 

These methods are called when we are decoding our GIF (the section prior to this outlined this process)

image

The sprite batch, as expected, has the ability to render itself and all it’s sprites. In my example it will render on a D2D surface and will use the much loved BitmapEffect to render the layer Smile .

Also note that the offset(_texturesRotatedOffset) for the layer needs to be rendered for the 1-7 frames

image

Now if you don’t understand the above just step through the code, it will all make sense..

Does this all work ?!

Does SharpDx’s support for WIC GIF’s work for animated gifs ?!

 

Running the demo

 

Here’s some awesome gifs from a very cool site

 

Here’s the metro xaml/c# demo running one of those animated gifs. Note that the framerate is low because of the simultaneous video recording going on. Without it it runs buttery smooth at 65-70fps. Smile 

 

 

Sample code

 

image

 

Conclusion

 

I started out this experiment fully expecting it NOT to work… I was so surprised that it actually did Smile . Animated gifs in a XAML managed metro app!!! Damn!!

XAML/WinRT + DirectX/WIC (via SharpDx) is turning into a killer combination of features for building pretty amazing new experiences. I’m only now getting familiar with the frameworks, I can’t wait to see what I’ll be creating a month from now!

I’m loving XAML/DirectX …

31 responses to “Animated gifs in XAML/C# :)

  1. Pingback: Animated gifs in XAML/C# :) | Silverlight and other cool things …

  2. Pingback: Windows 8 Developer Links – 2012-05-08 | Dan Rigby

  3. Pingback: Animated gifs in XAML/C# :) :: Learning

  4. I haven’t tried this but looks really cool. Have you tried adding it to a live tile? Would that work?

  5. This is really cool, loving it, but I wonder will this be avaliable for loading in a live tile as well

  6. Pingback: All my XAML/C#/SharpDx demos | Silverlight and other cool things …

  7. can you give a simpler code adding gif animation in xaml/c# for beginner learner?

  8. Seems a great work, but under RTM it doesn’t work. I am not familar with c# so I can’t bringing it to work. Would be great if you can provide a working example.

    Cheers, Franz

  9. Hello, I brought it to run Yeah. So I copy the standardstyle, strange a section shows errror, so commeted it out, in xaml replaced by simple , pointereventargs replaced by PointerRoutedEventArgs.

    So for me as non c# guy i had problems to solve ApplicationView.GetForCurrentView().ViewStateChanged += this.ViewStateChanged; and related private void ViewStateChanged(ApplicationView sender, ApplicationViewStateChangedEventArgs e)
    {
    this.InvalidateVisualState(e.ViewState);
    }

    so I commeted it out, but this should for a c# guy solvable

    For the error
    return new Windows.Foundation.Rect(0, 0, surfaceImageSource.PixelWidth, surfaceImageSource.PixelHeight); I found no solution, so tried with hardcoded
    return new Windows.Foundation.Rect(0, 0, 350, 350);

    With this changes the sample runs at 80Frames and looks very ugly. Is there anybody to bring the code to work at a smooth look?

    Franz

  10. Heya Jose, looking really good! However, as Franz has said, there is an issue with the framerate in RTM (I think I nearly had a fit from watching it!) There is an horrendous amount of flickering.

    Franz has identified the workarounds for getting the code to compile, although instead of the hardcoded 350 values for width and height, he should use the class level pixelWidth and pixelHeight fields passed to the SurfaceImageSourceTarget constructor.

    The rendering has issues in both the draggable canvas and the panel. The issue appears to be a disjoint in the frame rate and the frame delay (?):

    using: _spriteBatch.FrameDelay = 1 results in very little delay between frames and has no flicker. But of course, the delay being very little is an issue as frames just shoot by.

    Anything greater than 1 has the flickering.

    I guess it has to be in the SpriteBatch Render method. The setup works, as all frames are loaded into the collections in the SpriteBatch, and the gif auto repeats. I have played with the calls between the BeginDraw and EndDraw methods and nothing seems to sort it. Unless there is something in the SurfaceImageSourceTarget.RenderAll method; although it’ll take me a while to work out what that code does!

    Any ideas?

  11. Whoops, was meant to remove that ridiculous paragraph about the disjoint…

  12. I have now also tried it with the latest SharpDX Windows 8 assemblies, and no luck.

    Had to change the GifBitmapDecoder to the base BitmapDecoder class, and all the frames were retrieved successfully still.

    Had to get the latest CommonDX library as well.

  13. Spamming the comments, sorry…

    So, I now understand how your code uses the FrameDelay :)

    Rather than having the SurfaceImageSourceTarget’s RenderAll go to waste, I embraced it.

    Instead of:

    _currentFrame++;
    if (_currentFrame < FrameDelay) return;
    _currentFrame = 0;

    I use:

    _currentFrame++;
    //if (_currentFrame < FrameDelay) return;
    //_currentFrame = 0;

    And then, just after the EndDraw call:

    if (_currentFrame == FrameDelay)
    {
    _currentFrame = 0;
    _currentTexture++;
    }

    This way, the same frame is rendered for each time the _currentFrame falls within the delay.

    Fixed!

  14. Fixed… sort of. Now the rendering of the gif uses a fair bit of CPU (well, for rendering a gif!!!)

    As long as I dispose it, I should be all good. It can’t be any worse than playing a video in my app.

  15. This is a lot of work when you could just use HTML5 in a WebView.

    • Try using an animated gif that you have downloaded to one of the local storage folders. There is no issue if the gif is online, or is included in the app (as you can use the ms-appx-web schema to open the html file).

      If you can find a way, let me know.

  16. Magnificent beat ! I wish to apprentice while you amend your website, how can i subscribe for a blog website?
    The account helped me a acceptable deal. I had been tiny bit acquainted of this your broadcast provided
    bright clear concept

  17. Hi there, every time i used to check weblog posts here in the early hours in the
    daylight, as i love to find out more and more.

  18. Hey! This is my 1st comment here so I just wanted to give a quick shout out and
    say I genuinely enjoy reading your posts. Can you
    recommend any other blogs/websites/forums that go
    over the same subjects? Thanks for your time!

  19. Hello terrific blog! Does running a blog like this require a great deal of work?
    I’ve virtually no knowledge of programming but I had been hoping to start my own blog in the near future. Anyways, should you have any suggestions or techniques for new blog owners please share. I understand this is off topic however I simply needed to ask. Appreciate it!

  20. Thanks for sharing your thoughts on germany travel. Regards

  21. Now, you might think that computer optimization is difficult.
    But few simple things like those mentioned above will always keep your
    system running at its highest speed. Other things
    also affect performance, although not as much as RAM tinyness.

  22. ” The next generation of antivirus applications for endpoints must include an integrated and centralised management console. In fact, the more you use your PC, the more it builds-up fragmentation and over time your PC is liable to suffer from random crashes, freeze-ups and eventually the inability to boot up at all. DEFRAGMENTING THE DISK Regularly defragmenting the drive will significantly speed up computer.

  23. Depending on the task, the requirements may change.
    In order to know what problems need to be resolved, it is first good to know what problems
    are currently happening on your computer. DEFRAGMENTING THE DISK Regularly defragmenting the drive
    will significantly speed up computer.

  24. Outstanding post, I conceive blog owners should learn a
    lot from this blog its really user genial . “My father always told me, Find a job you love and youll never have to work a day in your life.” by Jim Fox.

  25. They are the workout that a lot of exercisers do when they are on the way
    to working their ab muscles in the way they want them.
    Sitting on an workout ball to do your crunches is a beautiful example of how crunches
    need changed over the time. Aerobics classes, jogging, or a fitness method like kickboxing can all prove useful for taking off weight in general
    and therefore making your abs more likely to be seen.

  26. It may be very tempting to give up and indulge our hungers.
    There are so many good things that people talk
    about the said book and one of which is its list that
    has the the best abs exercises that are known to everyone.

    3: Butterfly Crunch – This will target your rectus abdominus, which is
    directly responsible for the 6 pack look.

  27. Wonderful article! That is the type of information that are meant to be
    shared around the web. Disgrace on Google for now not positioning this publish upper!
    Come on over and seek advice from my web site .

    Thank you =)

  28. Thank you for the auspicious writeup. It in fact was
    a amusement account it. Look advanced to more added agreeable
    from you! However, how can we communicate?

  29. We’re a group of volunteers and opening a new scheme
    in our community. Your web site offered us with valuable info to work on.

    You have done an impressive job and our whole community will be grateful
    to you.

  30. Hello there, just became alert to your blog through Google, and
    found that it’s really informative. I am going to watch out for brussels.
    I’ll be grateful if you continue this in future.
    Many people will be benefited from your writing. Cheers!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s