Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

wpf graph export to image

Solved!
Go to solution

The graph has a default Margin, which is added to the Width and Height of the control (this is why the original code snippet used LayoutInformation.GetLayoutSlot, which returns the full display size of the control).


If you explicitly assign a value of 0 to the margin of the graph, or include the margin in the size of the bitmap, this should avoid the new clipping issue.

~ Paul H
0 Kudos
Message 11 of 20
(5,775 Views)

Thanks, this solved the problem.

0 Kudos
Message 12 of 20
(5,771 Views)

Hi, Paul!

 

Another issue: is it possible to copy data from invisible graph? I use it for reporting and don't want to show these temporary graphs. But currently the only way I found to copy graph image is to make it visible.

0 Kudos
Message 13 of 20
(5,754 Views)

Hi Eugenem,

 

How do you want to use this data in a report? Do you insert the image into a text file? I found some examples of other users rendering off-screen, like this one (http://stackoverflow.com/questions/1877115/create-wpf-element-offscreen-and-render-to-bitmap), or rendering a not-visible image to disk (http://stackoverflow.com/questions/5868631/render-a-not-visible-wpf-controls-to-an-bitmap-image)

 

Regards,

 

Alexandra

 

 

National Instruments
Applications Engineer
0 Kudos
Message 14 of 20
(5,729 Views)

Using the technique from the Create WPF element offscreen and render to bitmap question Alex+ra mentioned, you can create a graph outside the visual tree and render it to a bitmap:


    // Create graph and populate with data.
    var graph = new Graph { Margin = new Thickness( ) };
    graph.DataSource = ...;

    // Perform layout on graph at desired size.
    Rect bounds = new Rect( 0, 0, width, height );
    graph.Measure( bounds.Size );
    graph.Arrange( bounds );
    graph.UpdateLayout( );


After layout has been performed, you can use the original bitmap save snippet to generate the image.

~ Paul H
0 Kudos
Message 15 of 20
(5,720 Views)

strange, I do it like follows: 

 

var graph2 = new Graph();
graph2.Margin = new Thickness(0);
Rect bounds = new Rect(0, 0, 950, 450);
graph2.Measure(bounds.Size);
graph2.Arrange(bounds);
graph2.UpdateLayout();

 

var renderTarget = new RenderTargetBitmap((int)graph2.ActualWidth, (int)graph2.ActualHeight, 96, 96, PixelFormats.Pbgra32);
renderTarget.Render(graph2);

 

and graph size is 300x200 instead of 950x450

0 Kudos
Message 16 of 20
(5,708 Views)

The main difference I see is that I used the width and height of the bounds, rather than ActualWidth and ActualHeight. 300 by 200 is the default size of the graph, so it may be an artifact of measuring outside of the visual tree that ActualWidth and ActualHeight report default values.

~ Paul H
0 Kudos
Message 17 of 20
(5,700 Views)

var renderTarget = new RenderTargetBitmap((int)bounds.Width, (int)bounds.Height, 96, 96, PixelFormats.Pbgra32);

 

this shows the same graph 300x200

0 Kudos
Message 18 of 20
(5,697 Views)

Just to ensure we're on the same page, here is the complete image test code I am using:


    string path = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.Desktop ), "new.png" );
    var g = new Graph { Margin = new Thickness( ) };
    GenerateData( g, 11 );

    // Render graph at desired display size.
    Rect bounds = new Rect( 0, 0, 950, 450 );
    g.Measure( bounds.Size );
    g.Arrange( bounds );
    g.UpdateLayout( );

    // Save graph to bitmap.
    var rtb = new RenderTargetBitmap( (int)bounds.Width, (int)bounds.Height, 96, 96, PixelFormats.Pbgra32 );
    rtb.Render( g );

    // Delete existing test file.
    if( File.Exists( path ) )
        File.Delete( path );

    // Save bitmap to disk.
    PngBitmapEncoder png = new PngBitmapEncoder { Frames = { BitmapFrame.Create( rtb ) } };
    using( Stream stream = File.Create( path ) )
        png.Save( stream );

    // Show image and close program.
    System.Diagnostics.Process.Start( path );
    this.Close( );


On my machine, this correctly generates a 950 by 450 pixel image of a graph with 11 plots of random data using this GenerateData helper method:


    private void GenerateData( Graph g, int plotCount ) {
        Random r = new Random( );
        for( int i = 0; i < plotCount; ++i )
            g.Data[i] = Enumerable.Repeat( r, 11 ).Select( _ => i + r.NextDouble( ) ).ToArray( );
    }

~ Paul H
0 Kudos
Message 19 of 20
(5,693 Views)

Very strange, it suddenly started to work. Probably some bug at our side, or maybe it wasn't compiling somehow.

 

Thanks for help!

0 Kudos
Message 20 of 20
(5,689 Views)