12-13-2012 03:33 AM
How to export WPF graph to vector or raster image?
Solved! Go to Solution.
12-13-2012 09:51 AM
You can use a RenderTargetBitmap to convert a WPF visual into a bitmap, and a BitmapEncoder to save an in-memory bitmap image to disk.
Here is an example adapted from How to: Encode a Visual to an Image File that saves a graph to a PNG file:
// Save control to bitmap.
Rect bounds = LayoutInformation.GetLayoutSlot( graph );
var bitmap = new RenderTargetBitmap( (int)bounds.Width, (int)bounds.Height, 96, 96, PixelFormats.Pbgra32 );
bitmap.Render( graph );
// Save bitmap to disk.
string path = ...;
var encoder = new PngBitmapEncoder { Frames = { BitmapFrame.Create( bitmap ) } };
using( Stream stream = File.Create( path ) )
encoder.Save( stream );
12-20-2012 04:03 AM
This works indeed, but image quality is low. How can I render high-resolution image from the graph? If I make it very big in XAML, then it's cut in resulting image as it doesn't fit to the screen.
12-20-2012 04:59 PM
The easiest way I know would be to manually layout the control and wait for it to update before saving it to a bitmap:
// Force graph to larger display size.
const int size = 1000;
Rect bounds = new Rect( 0, 0, size, size );
graph.Measure( bounds.Size );
graph.Arrange( bounds );
// Wait for WPF layout system to update graph.
Dispatcher.BeginInvoke( new Action( delegate {
// Save graph to bitmap.
RenderTargetBitmap rtb = new RenderTargetBitmap( size, size, 96, 96, PixelFormats.Pbgra32 );
rtb.Render( graph );
// Return graph to previous size.
((UIElement)graph.Parent).InvalidateMeasure( );
// Save bitmap to disk.
PngBitmapEncoder png = new PngBitmapEncoder { Frames = { BitmapFrame.Create( rtb ) } };
using( Stream stream = File.Create( path ) )
png.Save( stream );
} ), DispatcherPriority.Background );
12-24-2012 06:40 AM - edited 12-24-2012 06:42 AM
I even defined this size in XAML. Problem is that when graph is larger than application window, then bitmap is cut (only visible graph part is on image).
12-26-2012 05:14 PM
Hi EugeneM,
Can you attach a screenshot of the entire application window? I'm not sure what I'm looking at in your screenshot.
12-27-2012 01:36 AM
this wasn't screenshot but generated png
there is screenshot of application
12-28-2012 10:52 AM
Hi EugeneM,
Try scaling the image to render at a higher quality. You can use the BitmapCache.RenderAtScale Property to force a higher resolution. See the sample XAML snippet below. Let me know if this gets you headed in the right direction!
<Rectangle>
<Rectangle.Fill>
<VisualBrush x:Name="visual1" Visual="{Binding ElementName=graph1}"/>
</Rectangle.Fill>
<Rectangle.CacheMode>
<BitmapCache RenderAtScale="6"/>
</Rectangle.CacheMode>
</Rectangle>
Regards,
Alexandra
01-02-2013 12:52 PM
If you want to define the size of the control in XAML, then you will need put it in a panel that does not clip the size of its children, like a Canvas:
<Canvas>
<Graph x:Name="graph" Width="1000" Height="1000" />
</Canvas>
Using this XAML with the original bitmap save snippet should produce an unclipped image measuring a thousand pixels on each side.
01-02-2013 02:21 PM
Hi, Paul!
Much better indeed. The only problem that PNG from such graph is slightly cut on sides