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 …

35 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. 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!

  18. Every weekend i used to pay a visit this site, as i wish for enjoyment, as this this web site conations really nice funny information too.

  19. Hi there! I’m at work surfing around your blog from my new iphone!
    Just wanted to say I love reading your blog and look forward to all your posts!
    Keep up the superb work!

  20. I read this article completely regarding the resemblance of most recent and preceding technologies, it’s remarkable article.

  21. I’m gone to say to my little brother, that he should also pay a quick visit this blog on regular basis to take updated from newest reports.

  22. I have been exploring for a bit for any high quality articles or blog posts in this sort of house .
    Exploring in Yahoo I eventually stumbled upon this site.
    Reading this information So i am happy to convey that I’ve an incredibly
    good uncanny feeling I came upon just what I needed.
    I such a lot without a doubt will make sure to don?t omit this site and give it a look regularly.

  23. Link exchange is nothing else however it is just placing the other person’s website link on your page
    at suitable place and other person will also do same in support of you.

  24. Hi friends, how is all, and what you want to say concerning this piece of writing, in my view its really amazing in favor
    of me.

  25. If you are going for most excellent contents like I do,
    just go to see this web site daily as it presents
    feature contents, thanks

  26. I will immediately grab your rss feed as I can’t
    in finding your email subscription link or
    newsletter service. Do you have any? Please allow me know in order that I may just subscribe.
    Thanks.

  27. Good day I am so excited I found your web site,
    I really found you by mistake, while I was looking on Aol for something else, Anyhow I am here now and
    would just like to say many thanks for a fantastic post and a all round entertaining blog
    (I also love the theme/design), I don’t have time to
    go through it all at the minute but I have bookmarked it and also added your RSS feeds,
    so when I have time I will be back to read more,
    Please do keep up the great jo.

  28. It’s awesome for me to have a web site, which is useful designed
    for my knowledge. thanks admin

  29. Hi! I could have sworn I’ve been to this site before but after
    reading through some of the post I realized it’s new to me.
    Anyhow, I’m definitely happy I found it and
    I’ll be book-marking and checking back often!

  30. Hey! Do you use Twitter? I’d like to follow you if that
    would be okay. I’m absolutely enjoying your blog and look
    forward to new updates.

  31. I’ve been surfing on-line greater than three hours nowadays,
    yet I by no means found any fascinating article like yours.
    It is pretty worth sufficient for me. Personally, if all web owners and bloggers made just right
    content material as you probably did, the internet might be a lot more useful than ever before.

  32. I like the valuable info you supply in your articles.
    I will bookmark your blog and test once more here frequently.
    I am relatively sure I’ll be informed many new stuff right here!
    Good luck for the next!

  33. Quality articles or reviews is the key to be a focus for the visitors to go to see the web page, that’s what
    this website is providing.

  34. I’m not sure where you’re getting your info, but great topic.
    I needs to spend some time learning much more or understanding more.
    Thanks for wonderful information I was looking for this information for my mission.

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