Some Silverlight 3 Goodness : Using WriteableBitmap

While working on a demo for the upcoming NAB conference, one of the Silverlight product developers showed me a really cool API in SL3:  the WriteableBitmap API.  It’s really easy to use… you can point it at a UIElement and render an ImageSource to be used with another image.  To demonstrate, here’s a simple bit of XAML with a media player.

 <UserControl
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="NABMediaPlayer.MainPage" 
    Width="395" Height="530" mc:Ignorable="d">
    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
      <RowDefinition Height="240"/>
      <RowDefinition Height="240"/>
        </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="320" />
      <ColumnDefinition Width="75" />
    </Grid.ColumnDefinitions>
        <Button x:Name="CopyImage" Click="CopyImage_Button_Click" Content="Grab Video Snapshot"   Grid.Row="0" Grid.Column="0"/>
        <Button x:Name="Play" Click="Play_Button_Click" Content="Play"  Grid.Row="0" Grid.Column="1" />
    
    <MediaElement Grid.Row="1"
      x:Name="myPlayer"
      Source="https://mschnlnine.vo.llnwd.net/d1/ch9/6/7/8/0/6/4/SharePointDevPart1_ch9.wmv"
      AutoPlay="False" Width="320" Height="240"  />
    
        <Image x:Name="outputImage"  Grid.Row="2" Source="BentleySm.jpg" Stretch="None" Height="240" Width="320"/>
        <Button Height="22" HorizontalAlignment="Right" VerticalAlignment="Top" Width="26" Grid.Row="1" Click="Pause_Button_Click" />
    
    </Grid>  
</UserControl>

There isn’t really much going on in the XAML, there’s a MediaElement, 2 buttons, and an image.  When the video loads, press the play button.  When you click the “Grab Video Snapshot” button, the Image is populated with the frame from the video.  Here’s the code to do make it happen.

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using System.ComponentModel;


namespace NABMediaPlayer
{
    public partial class MainPage : UserControl
    {
        TransformGroup mytransform;

        public MainPage()
        {            
            InitializeComponent();
            CreateTransform();
        }

        private void Play_Button_Click(object sender, RoutedEventArgs e)
        {
            myPlayer.Play();
        }
        private void CopyImage_Button_Click(object sender, RoutedEventArgs e)
        {
            WriteableBitmap wb = new WriteableBitmap(320, 240, PixelFormats.Pbgra32);
            wb.Render(myPlayer, mytransform);            
            outputImage.Source = wb;
        }

        private void CreateTransform()
        {
            mytransform = new TransformGroup();          
            TranslateTransform tt = new TranslateTransform();            
            //Adjust downward to accomodate for button controls at top
            tt.Y = -50;
            mytransform.Children.Add(tt);
        } 
    }
}

The transform here is used to accommodate for the first row in the table being 50 pixels high. 

So, why is this cool?  Well… because you could use this to create a reflection of your video or even a wet floor effect for your videos and other controls in Silverlight 3!  The link I just gave shows how to do this in WPF because this wasn’t possible previously in Silverlight without playing the video stream twice on the same page.  Now, you could simply set a timer to update the image once every couple hundred millseconds, and you can simulate a reflection.