`
wyf
  • 浏览: 426241 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

"Printing" in Silverlight 3 with WriteableBitmap

阅读更多

One of the high-profile missing features in Silverlight has been Printing support. If you have ever tried to print a web page containing Silverlight content, what you saw on the printed page may be skewed or even missing altogether!  So, what if you wanted to print a portion of your Silverlight screen, or take a “snapshot” image of the Silverlight UI to include in a report or other printable format?

Silverlight 3 can accomplish these scenarios using the WriteableBitmap API. WritableBitmap includes a Render method which can snag all of the pixels of a given UI Element and place them into a buffer for manipulation.
In this demo, I’ll show how to take a “snapshot” of a Silverlight UI screen, upload the image to a web server, and include it in a Report Viewer (RDLC) report. You could easily modify these steps to save the snapshot to an image file on the server, or otherwise manipulate the pixels.
The steps used in the demo are as follows:
1.       Render the Silverlight UI to a WriteableBitmap, passing in the UI Element and an arbitrary Transform. In the code below, the content of a Canvas named cnvSource is rendered to the WriteableBitmap. We pass in an empty TranslateTransform simply because one is required by the constructor:
WriteableBitmap bitmap = new WriteableBitmap(cnvSource, new TranslateTransform());
 2.Convert the WriteableBitmap pixels to a PNG using Joe Stegman's PNG encoder.
EditableImage imageData = new EditableImage(bitmap.PixelWidth, bitmap.PixelHeight);
 
 
for (int y = 0; y < bitmap.PixelHeight; ++y)
{
    for (int x = 0; x < bitmap.PixelWidth; ++x)
    {
 
        int pixel = bitmap.Pixels[bitmap.PixelWidth * y + x];
 
        imageData.SetPixel(x, y,
                    (byte)((pixel >> 16) & 0xFF),
                    (byte)((pixel >> 8) & 0xFF),
                    (byte)(pixel & 0xFF),
                    (byte)((pixel >> 24) & 0xFF)
                    );
 
    }
}
 
Stream pngStream = imageData.GetStream();
 NOTE that this PNG encoder does NOT include compression! This would be a good optimization to add, but also note that the GZipStream class is not present in Silverlight, so you would need to use an outside compression library such as SharpZipLib.

3.At this point, we have the PNG bytes in a stream, and you could take several approaches to get these bytes up to the server – such as using an Http Handler (ASHX). In this demo, we’ll place the bytes into a hidden field on the ASPX page and post the page back to the server  for inclusion in a report. To do this, we’ll translate the PNG bytes into a string using Base64 encoding:

byte[] binaryData = new Byte[pngStream.Length];
long bytesRead = pngStream.Read(binaryData, 0, (int)pngStream.Length);
 
string base64String =
        System.Convert.ToBase64String(binaryData,
                                      0,
                                      binaryData.Length);
 
// save the encoded PNG bytes to the page
HtmlDocument document = HtmlPage.Document;
HtmlElement txtPNGBytes = document.GetElementById("txtPNGBytes");
txtPNGBytes.SetProperty("value", base64String);
 
// this calls a js function "postBackPrint" which will cause a postback
HtmlPage.Window.CreateInstance("postBackPrint", new string[] { });

 4.Now that we have our bytes up on the server, we can decode them and feed them to a ReportViewer (RDLC) report. This will give us a nicely printed format and the ability to export to PDF:

string bytes64 = Request["txtPNGBytes"];
byte[] imageBytes = System.Convert.FromBase64String(bytes64);
 
 
DSReportPrintImage ds = new DSReportPrintImage();
DataRow drImage = ds.Tables[0].NewRow();
drImage["ImageBytes"] = imageBytes;
ds.Tables[0].Rows.Add(drImage);
 
ReportViewer1.LocalReport.ReportPath = "ReportPrintSilverlight.rdlc";
 
ReportDataSource src = new ReportDataSource("DSReportPrintImage_ImageData", ds.Tables[0]);
ReportViewer1.LocalReport.DataSources.Add(src);
ReportViewer1.LocalReport.Refresh();

 That’s it! I really think this use of WriteableBitmap as a snapshot/print function will be useful in some of my projects that need to capture the current view of the Silverlight application.

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics