Monday, August 30, 2010

Создание изображений из элементов управления WPF

Существует достаточно распространенная задача, когда окно приложения или его часть необходимо сохранить как изображение. В WPF есть класс, который очень упрощает ее решение – RenderTargetBitmap. Он позволяет получить изображение любого элемента управления WPF (включая его дочерние элементы) в растровом формате. Рассмотрим пример использования данного класса и некоторые особенности.
Сразу перейдем к коду примера. После я дам краткое его описание и расскажу про пару особенностей.
/// <summary>Renders the Visual object and store it to file.</summary>
/// <param name="baseElement">The Visual object to be used as a bitmap. </param>
/// <param name="imageWidth">The height of the bitmap.</param>
/// <param name="imageHeight">The width of the bitmap.</param>
/// <param name="pathToOutputFile">Full path to the output file.</param>
private void SaveControlImage(Visual baseElement,
       int imageWidth, int imageHeight, string pathToOutputFile)
{
   // 1) get current dpi
   PresentationSource pSource = PresentationSource.FromVisual(Application.Current.MainWindow);
   Matrix m = pSource.CompositionTarget.TransformToDevice;
   double dpiX = m.M11 * 96;
   double dpiY = m.M22 * 96;
   // 2) create RenderTargetBitmap
   RenderTargetBitmap elementBitmap =
               new RenderTargetBitmap(imageWidth, imageHeight, dpiX, dpiY, PixelFormats.Default);
   // 3) undo element transformation
   DrawingVisual drawingVisual = new DrawingVisual();
   using (DrawingContext drawingContext = drawingVisual.RenderOpen()) {
       VisualBrush visualBrush = new VisualBrush(baseElement);
       drawingContext.DrawRectangle(visualBrush, null,
           new Rect(new Point(0, 0), new Size(imageWidth, imageHeight)));
   }
   // 4) draw element
   elementBitmap.Render(drawingVisual);
   // 5) create PNG image
   BitmapEncoder encoder = new PngBitmapEncoder();
   encoder.Frames.Add(BitmapFrame.Create(elementBitmap));
   // 6) save image to file
   using (FileStream imageFile =
               new FileStream(pathToOutputFile, FileMode.Create, FileAccess.Write)) {
       encoder.Save(imageFile);
       imageFile.Flush();
       imageFile.Close();
   }
}
Read more: devblog.NET