WPF FAQ
Get Microsoft Silverlight
Skip Navigation Links

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.

Lissajous figures

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.