Make Bitmap from UIElement : Bitmap « 2D Graphics « C# / C Sharp






Make Bitmap from UIElement

       

using System;
using System.IO;
using System.IO.Packaging;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;

namespace StreamToMe.Flow.Windows.Utils
{
    public static class WebBrowserHelper
    {
        public static BitmapSource MakeBitmapSource(this UIElement control)
        {
            // The control we have been passed is quite possibly the child of
            // another element and we have no idea of what its left/top properties
            // may be. So the first thing we have to do is take a visual copy of it.
            // This will ensure we have a relative 0,0 origin.
            Rectangle rect = PaintControl(control);

            // Create an in memory xps package to write to            
            using (var stream = new MemoryStream())
            {
                Package package = Package.Open(stream,
                                               FileMode.CreateNew, FileAccess.ReadWrite);

                // A name (any name) is required when referencing the package.
                const string inMemoryPackageName = "memorystream://out.xps";
                var packageUri = new Uri(inMemoryPackageName);

                // A package, managing the memory stream, is held as a reference.
                PackageStore.AddPackage(packageUri, package);

                // We must keep the document open until we have finished with 
                // the resulting visual, otherwise it wont be able to access 
                // its resources.
                using (var doc = new XpsDocument(
                    package, CompressionOption.Maximum, inMemoryPackageName))
                {
                    // Print the control using Xps printing.
                    Visual capture = PrintToVisual(doc, rect);

                    // We want to render the resulting visual into a RenderTarget
                    // so that we can create an image from it.
                    RenderTargetBitmap renderTarget =
                        RenderVisual(capture, 700, 1024);

                    // Tidy up
                    PackageStore.RemovePackage(packageUri);

                    // Voila! The most complicated method of creating an image
                    // from a control you've ever seen!
                    return renderTarget;
                }
            }
        }

        /// <summary>
        /// Paints a control onto a rectangle. Gets around problems where
        /// the control maybe a child of another element or have a funny
        /// offset.
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        private static Rectangle PaintControl(UIElement control)
        {

            // Fill a rectangle with the illustration.
            var rect = new Rectangle
                           {
                               Fill = new VisualBrush(control) { TileMode = TileMode.None, Stretch = Stretch.Uniform },
                               Width = (control.RenderSize.Width),
                               Height = (control.RenderSize.Height)
                           };

            // Force the rectangle to re-size
            var szRect = new Size(rect.Width, rect.Height);
            rect.Measure(szRect);
            rect.Arrange(new Rect(szRect));
            rect.UpdateLayout();
            return rect;
        }

        /// <summary>
        /// Prints any UIElement to an xps document and gets the resulting Visual.
        /// This is the only fool proof way to copy the contents of a UIElement into
        /// a visual. Other methods may work well...but not with WindowsFormsHosts.
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="element"></param>
        /// <returns></returns>
        private static Visual PrintToVisual(XpsDocument doc, Visual element)
        {
            // Write the element to an XpsDocument
            XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
            writer.Write(element);

            // Get the visual that was 'printed'
            var Sequence = doc.GetFixedDocumentSequence();
            if (Sequence != null)
            {
                Visual capture = Sequence.DocumentPaginator.GetPage(0).Visual;
                doc.Close();
                return capture;
            }
            return null;
        }

        /// <summary>
        /// Render a Visual to a render target of a fixed size. The visual is
        /// scaled uniformly to fit inside the specified size.
        /// </summary>
        /// <param name="visual"></param>
        /// <param name="height"></param>
        /// <param name="width"></param>
        /// <returns></returns>
        private static RenderTargetBitmap RenderVisual(Visual visual,
                                                       double height, double width)
        {
            // Default dpi settings
            const double dpiX = 96;
            const double dpiY = 96;

            // We can only render UIElements...ContentPrensenter to 
            // the rescue!
            var presenter = new ContentPresenter { Content = visual };

            // Ensure the final visual is of the known size by creating a viewbox 
            // and adding the visual as its child.
            var viewbox = new Viewbox
                              {
                                  MaxWidth = width,
                                  MaxHeight = height,
                                  Stretch = Stretch.Uniform,
                                  Child = presenter
                              };

            // Force the viewbox to re-size otherwise we wont see anything.
            var sFinal = new Size(viewbox.MaxWidth, viewbox.MaxHeight);
            viewbox.Measure(sFinal);
            viewbox.Arrange(new Rect(sFinal));
            viewbox.UpdateLayout();

            // Render the final visual to a render target 
            var renderTarget = new RenderTargetBitmap(
                (int)width, (int)height, dpiX, dpiY, PixelFormats.Pbgra32);
            renderTarget.Render(viewbox);

            // Return the render taget with the visual rendered on it.
            return renderTarget;
        }
    }
}

   
    
    
    
    
    
    
  








Related examples in the same category

1.Draw on an Bitmap
2.Resize the Bitmap using the lowest quality interpolation mode
3.Resize the Bitmap using the highest quality interpolation mode
4.Create Graphics object From Image
5.Bitmap.SetResolution
6.Bitmap property: Height, Physical Dimension, width, raw format and sizeBitmap property: Height, Physical Dimension, width, raw format and size
7.Create your own BitMapCreate your own BitMap
8.Draw shapes to the bitmap in memoryDraw shapes to the bitmap in memory
9.new Bitmap(bitmap, size)
10.Read Bitmap Size by using BinaryReader
11.Bitmap.HorizontalResolution
12.Use a color matrix to change the color properties of the image
13.Create a Bitmap image in memory and set its CompositingMode
14.Create a red color with an alpha component then draw a red circle to the bitmap in memory
15.Create a green color with an alpha component then draw a green rectangle to the bitmap in memory
16.write the pixel information to the console window
17.Double buffer with Bitmap
18.Draw an array of imagesDraw an array of images
19.Bit operation with PixelFormat.Alpha
20.PixelFormat.DontCare
21.Scale Bitmap By Percent
22.Draws Bitmap in a cell within a DataGridView
23.Bitmap Image Utils
24.Bitmap Operations
25.Creates a new bitmap from a specific region of another bitmap
26.Allows drawing fonts with borders and auto centers the font on a bitmap.
27.Create New Bitmap From Image
28.Simple Resize Bmp
29.Create Thumbnail
30.Calculate the RBG projection
31.Make Thumb