New block - ciAnimatedGif


#1

Hey amigos. Here is a quick block for a more advanced playback of animated gifs. It takes into account that framerates can be different between every single frame, and also exposes global palettes often included in gifs. While I don’t recommend using a lot of gifs in your project, it’s something that gets requested enough from clients that I finally made this so I could stop worrying about it. Use is super simple.

ciAnimatedGifRef    mGif = ciAnimatedGif::create( loadAsset("someGif.gif") );
mGif->draw();

Find the block here: https://github.com/cwhitney/ciAnimatedGif
It’s based on the information in this article: http://giflib.sourceforge.net/whatsinagif/bits_and_bytes.html

Now - a question! When I load the gif frames, I am storing them as a vector of Surfaces. When they get displayed, I convert it to a texture right before it displays, which means an upload to the gpu. The alternative is to upload every frame to the gpu at the beginning, and just leave them there with gl::TextureRefs. I did it this way because if you’re displaying gifs, then you might be displaying a lot of them, and I didn’t want to clog the gpu, especially if you’re not displaying them. How would you handle this?

-c


#2

@sharkbox –– Thanks! Works on iOS too.

–8


#3

Amazing, thanks for checking!


#4

Definitely handy when it comes up, thanks for sharing it.

Now - a question! When I load the gif frames, I am storing them as a vector of Surfaces. When they get displayed, I convert it to a texture right before it displays, which means an upload to the gpu. The alternative is to upload every frame to the gpu at the beginning, and just leave them there with gl::TextureRefs. I did it this way because if you’re displaying gifs, then you might be displaying a lot of them, and I didn’t want to clog the gpu, especially if you’re not displaying them. How would you handle this?

What about making most of that a virtual AnimatedGifBase, then you can make two more concrete subclasses: AnimatedGif that stores the data as Surface's and another AnimatedGifGl that stores them as gl::Textures all on the gpu. I know that at least for me, I’d almost always use the gl version, especially if I’m using a card with like 4+ gigs of VRAM. Also, I think it would be nice if you could return the current frame to be drawn, and let the user draw it however they like. Could be in addition to the draw() methods if you find that more convenient.

cheers,
Rich


#5

Good advice Rich. I might just make ciAnimatedGif use textures as a default and provide ciAnimatedGifSurf as well.


#6

For the gl version, using a GL_TEXTURE_2D_ARRAY over a vector of gl::Texture2d would be significantly more optimal in the scenario where you want +1000 gifs all scrubbing at a different frame, which we may want :slight_smile: Though it implies a custom playback shader, and not sure it would work on mobile platforms? You could argue for or against it.

I did so with image sequences, but had to fix an issue with mimaps. You might have the same problem.
https://github.com/cinder/Cinder/pull/1432