Saving the captured Silverlight 4 screenshot to database or send it as an email attachment


Capture the Silverlight 4 screen through C# code and Save it to a database or send it as an email attachment by passing byte array to the WCF Service method.

Saving the captured Silverlight 4 screenshot to database or send it as an email attachment

In this article we will see how best we can compress and transfer WritableBitmap object to WCF services by encoding it to JPEG format.

In my previous article “Capture the screenshot of Silverlight application in Silverlight 4”, we have seen how to capture a Silverlight screen using WritableBitmap class.

In order to save the captured bitmap image onto the server or to send the snapshot as an attachment in email, we first need to convert the WritableBitmap object to byte array or binary stream and pass it to the WCF services.

Most importantly, we need to do compression as direct conversion of WritableBitmap object to byte array results in a very huge (more than 5mb for any decent graphics on the screen) object, which may cause “Maximum request length exceeded” issue with WCF services.

Here I am making use of FjCore library available on codeplex which provides option to encode the JPEG and to a Memory Stream.

Here is the function that to convert WritableBitmap object to JPEG and get the stream after compression.

/// 
/// Encodes the JPG.
/// 
/// "bitmap">The bitmap.
/// "destinationStream">The destination stream.
public static void EncodeJpeg(WriteableBitmap bitmap, Stream destinationStream)
{
    int width = bitmap.PixelWidth;
    int height = bitmap.PixelHeight;
    int bands = 3; // RGB
    byte[][,] raster = new byte[bands][,];
 
    // initialise the bands
    for (int i = 0; i < bands; i )
    {
        raster[i] = new byte[width, height];
    }
 
    // copy over the pixel data from the bitmap
    for (int row = 0; row < height; row )
    {
        for (int column = 0; column < width; column )
        {
            int pixel = bitmap.Pixels[width * row   column];
            raster[0][column, row] = (byte)(pixel >> 16);
            raster[1][column, row] = (byte)(pixel >> 8);
            raster[2][column, row] = (byte)pixel;
        }
    }
 
    // Use the Flux library to encode the JPG
    ColorModel model = new ColorModel { colorspace = ColorSpace.RGB };
    FluxJpeg.Core.Image img = new FluxJpeg.Core.Image(model, raster);
 
    // encode it to the destination stream
    JpegEncoder encoder = new JpegEncoder(img, 90, destinationStream);
    encoder.Encode();
}

 Here is how we can use this function to capture the Silverlight screen and encode to JPG and then call the WCF service method to save the image to database.

/// 
/// Handles the Click event of the btnCapture control.
/// 
/// "sender">The source of the event.
/// "e">The "System.Windows.RoutedEventArgs"/> instance containing the event data.
private void btnCapture_Click(object sender, RoutedEventArgs e)
{
    // Create Bitmap image by passing UIElement to WriteableBitmap constructor 
    WriteableBitmap bmp = new WriteableBitmap(LayoutRoot, null);
 
    // Display captured snapshot or can save to database
    System.Windows.Controls.Image img = new System.Windows.Controls.Image();
    img.Margin = new Thickness(10);
    img.Source = bmp;
    capturedImages.Children.Add(img);
 
    // Encode to JPEG format
    byte[] screenshot;
    using (Stream pngStream = new MemoryStream())
    {
        EncodeJpeg(bmp, pngStream);
        pngStream.Flush();
        pngStream.Seek(0, SeekOrigin.Begin);
        screenshot = ConvertToByteArray(pngStream);
 
        pngStream.Close();
    }
 
    // Call service method by passing binary array as input parameter
    ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
    client.SaveImageAsync(screenshot);
}
 
/// 
/// Converts to byte array.
/// 
/// "fileStream">The file stream.
/// 
public byte[] ConvertToByteArray(Stream fileStream)
{
    if (fileStream != null)
    {
        int fileStreamLength = (int)fileStream.Length;
        byte[] bytes = new byte[fileStreamLength];
        fileStream.Read(bytes, 0, fileStreamLength);
 
        return bytes;
    }
 
    return null;
}

You can download the sample application here.

 


Related tags

Silverlight 4, Screenshot