LowProfileImageLoader with GIF support for WP7

LowProfileImageLoader

I’ve recently bumped into the need to display images from various RSS feeds in a Windows Phone 7 app. UI binding and loading of images can easily degrade the performance of any wp7 app, which led me to the excellent LowProfileImageLoader (LPIL) by David Anson. The LPIL attaches a property, UriSource, to an Image and offloads as much of the image handling work as possible to a background thread, very nice. But, all is not well yet..

Update 2012-01-10

According to the comment by nati, a better way of doing this would be to check the first bytes of the actual image. I have not tested this, but please give it a try – looks better to me! /A

GIF

Windows Phone 7 does not have built-in support for GIF. JPG and PNG are supported, and the JPG handling is much faster so that is preferred. However, when consuming web data, you will very soon find yourself needing to handle gif images. ImageTools to the rescue! There are other decoders for gif out there, read more in “Working with GIF” by Jaime Rodriguez.

Using the gif decoder is easy. This code shows how to download and image, use the gif decoder, and create an ImageSource that an Image can bind to. The alternative way of using the ImageTools is to first register the decoders that you need, then use the ExtendedImage in a more indirect way. This method also allows you to decode BMP and the other formats supported by ImageTools.

Alternative 1 – Using the GIF decoder directly


 

 

Alternative 2 – Using the ExtendedImage class

This method can utilize more than one decoder. The decoders must be registered first, then the ExtendedImage can be used.


 

The combination

So, how do we mix these two nice things together? Let me show you, it’s really not a lot of code. The LPIL processes image tasks in batches for maximum efficiency, very clever. Shown below is the unmodified code from LPIL that processes all downloaded streams and creates a BitmapImage for each one, this is all done on the UI thread (which it needs to be).

The original code of LowProfileImageLoader

 


 

That was the hard part – all thanks to David Anson. Here comes the easy part. What I do is simply to check if the file is a GIF file – in that case:

  • Create a gif decoder
  • Decode the stream
  • Extract the resulting bitmap using the ToBitmap method on ExtendedImage

That does it! GIF images are decoded and pops up in the UI.

The modified LowProfileImageLoader


 

Room for improvement

Not a lot right? The code above worked well for me in the app I was building. Something that is nagging me though, is the fact that it’s all being done in the batch “all-background-work-done-now-just-populate-the-gui”, hence the GIF decoding is done on the UI thread. I have not found this to be a big problem, but it would be nicer to split the decoding and image creation into two different tasks, with the first task being done in one of the background batches of LPIL.

I once took a quick stab at this and bumped into some kind of problem, but I can’t remember what that was…

Anyway, I hope you find this piece of code useful. Please – see it as display of how GIF support can be accomplished, not a production-ready package.

Thank you for listening.

This Post Has 6 Comments

  1. Hi~
    May I ask one question?
    I would like to bind a .png with Listbox
    and the properties set as
    Build Action=content
    Copy to Output Directory = copy always.

    But it was failure when loading the application.

    Would u please help? thanks very much

  2. Superb code… But one thing I’ve found from writing my twitter client is that, just because it ends in GIF, its not always a GIF image… (likewise PNG etc..). It’s a crazy world out there! :)

  3. Thanks Chris! That is very true! I haven’t had big problems with that luckily.. yet…

  4. Thanks, that was really helpful!

    One small improvement:
    You identify gif files by looking for “.gif” in the URL but that’s not always the case…

    One can replace the following if statement:
    if (pendingCompletion.Uri.AbsolutePath.ToLower().Contains(“.gif”))
    with this one:
    if (StreamHeaderMatch(pendingCompletion.Stream, new byte[] { 71, 73, 70 }))

    where StreamHeaderMatch is defined:

    private static bool StreamHeaderMatch(Stream stream, byte[] value)
    {
    var header = new byte[value.Length];

    var x = stream.Read(header, 0, header.Length);
    stream.Seek(0, SeekOrigin.Begin);

    return (x == value.Length) && header.SequenceEqual(value);
    }

    Gif files has these magic bytes at the beginning (actually, 71,73,70 is ‘G’,’I’,’F’…), so I used that to identify these files.

    Of course, this method could be used to identify any file type, as long as you know the type’s magic bytes…

  5. Thanks a lot!! Had same issues of Gifs not showing in my list of tweets.Your solution resolved this issue. Update 2012-01-10 seems to work as well

  6. Hi Rob! Thanks for sharing – great to know that the update tip worked.

Leave a Reply

Close Menu