I would like to present some of the functionality that Windows Presentation Foundation (WPF) provides to viewers of my website, and I don’t want to require them to have the .NET 3.0 Framework installed. In particular I want to capture animations, both in 2D and 3D, and play them back as little filmstrips.
I’m not an expert in the field of animation and video, so my tool needs to be fairly easy to use.
With that in mind I did some looking around (the web) for appropriate tools. Unfortunately, I didn’t find anything that seemed simple enough to use. If anyone knows of a good tool please let me know.
Now, as a stubborn, old fashioned programmer, I couldn’t give up yet. I know that WPF has great imaging support, and sure enough, it also supports creating animated GIFs. After studying the MSDN documentation (I couldn’t find any external articles on the subject), I had a functional "FilmStrip" prototype.
Here’s a quick example of how it can be used. Assume that you have a window with a Viewport3D that you somehow can perform transformations/animations on. In addition you have three buttons named "Start Film Strip", "Add Frame", and "Save Film Strip".
First you declare your FilmStrip object:
private FilmStrip Film = new FilmStrip();
In the code behind you have the following click event handlers:
void StartFilmButton_Click(object sender, RoutedEventArgs e)
{
Film.Start();
}
void AddFrameToFilmStripButton_Click(object sender, RoutedEventArgs e)
{
Film.AddFrame(fViewport);
}
void SaveFilmStripButton_Click(object sender, RoutedEventArgs e)
{
Film.SaveToFile(@"C:\Temp\FilmStrip.gif");
}
What you can do with this in place, is to click the Start button, followed by multiple clicks on the Add Frame button at appropriate times, finalized by a click on the save button.
That seems to be fairly straight forward. With this basic functionality operational, the next logical step would be to tie into the WPF animation framework to automate adding frames to the filmstrip. Unfortunately, the GIF file that this code creates doesn’t seem to behave quite right, at least not when I display it in IE7. What happens is that the prior frame is not cleared before the next frame is displayed. I will have to look into that at some other time. Maybe somebody already knows how to do this?
Here’s the source for the FilmStrip class:
namespace Koda.WPF
{
using System;
using System.Windows.Media.Imaging;
using System.Windows;
using System.Windows.Media;
using System.IO;
public class FilmStrip
{
private BitmapEncoder fEncoder;
protected BitmapEncoder Encoder
{
get { return fEncoder; }
}
public void AddFrame(BitmapFrame frame)
{
Encoder.Frames.Add(frame);
}
public void AddFrame(BitmapSource source)
{
AddFrame(BitmapFrame.Create(source));
}
public void AddFrame(FrameworkElement element)
{
RenderTargetBitmap bmp = new RenderTargetBitmap((int)element.ActualWidth,
(int)element.ActualHeight, 1 / 96, 1 / 96, PixelFormats.Pbgra32);
bmp.Render(element);
AddFrame(bmp);
}
protected virtual BitmapEncoder CreateEncoder()
{
return new GifBitmapEncoder();
}
public void SaveToFile(String fileName)
{
using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
Encoder.Save(fs);
}
}
public void Start()
{
fEncoder = CreateEncoder();
}
}
}