Creating live bitmap
animations
A retained mode graphics
system is a wonderful thing. Those of us that struggled with GDI+ for many years
are a bit spoilt now that our UI can be dynamic and infinitely scalable. What
happens however if you actually want an immediate mode graphics system? Well,
thankfully, WPF doesn’t disappoint.
When we need the power of
WPF graphics with the familiarity of bitmaps we can use a
RenderTargetBitmap to create an
ImageSource that can be used to
generate real raster bitmaps.
For fun, in the following
example I’ve created an oscilloscope display that shows classic Lissajous
figures from the combination of two sinusoidal frequencies.
The image below shows the
application in action. The three sliders enable you to adjust the X and Y
frequencies and the length of time it takes for the green trace to fade away.
Just like the old oscilloscopes we played with in science lessons.

Figure 1: Lissajous figures on a
‘scope display.
The
RenderTargetBitmap I mentioned
earlier provides a bitmap rendering surface onto which we can draw any WPF
visual. To do the actual drawing, we need a
DrawingVisual.
The
DrawingVisual can render basic
graphical objects such as lines, rectangles and ellipses as well as images,
geometries and even video onto the bitmap surface.
To create the oscilloscope effect I drew a semi transparent rectangle onto the
background first. Over time, this has the effect of fading the background away. Then, I drew a simple line from the
last plotted point to the current one. All this, happening regularly from a
timer service routine provides the full bitmap animation.
Here’s the code for the timer routine:
//Timer service handler
void TimerCallback(object sender,
EventArgs a)
{
//Update the X and Y values
x += FX;
if (x >= 360)
x -= 360;
y += FY;
if (y >= 360)
y -= 360;
//Find the Cosine and Sine of the X and Y
values
double cx =
Math.Cos(x / 180 * Math.PI), sy =
Math.Sin(y / 180 *
Math.PI);
//Calculate the new point, with scaling
Point n =
new Point(cx * 150, sy * 150);
//Get the level of black transparent colour to
make a nice fade effect
scb.Color = Color.FromArgb((Byte)Fade, 0, 0, 0);
//Draw on the drawing context
using (DrawingContext
dc = dv.RenderOpen())
{
//Set up the drawing transform (sine and
cosine can be negative...
dc.PushTransform(new
TranslateTransform(150, 150));
//Draw a semi transparent rectangle over the bitmap to fade the
//background
dc.DrawRectangle(scb, null,
new Rect(-150,
-150, 300, 300));
//Draw a line from the last point to the
current point
dc.DrawLine(new
Pen(Brushes.Green,
2.0), last, n);
//Restore the original transform
dc.Pop();
//Close the context
dc.Close();
}
//last point becomes current point
last = n;
//Render the drawing to the bitmap
rti.Render(dv);
}
The entire application can be downloaded from
this link.
|