Home > database >  Save SVG in Memory Stream to input it into a PDF (C# OxyPlot and QuestPDF)
Save SVG in Memory Stream to input it into a PDF (C# OxyPlot and QuestPDF)

Time:04-22

I am currently using the OxyPlot and QuestPDF libraries to be able to generate a PDF with charts. I have designed a pie chart and a bar chart. I am currently saving the charts, exporting them to SVG, inside a folder, and then adding them to the PDF. I would like to change this and save them in memory and then yes, add them to the PDF. According to the documentation I read from the OxyPlot library, it has an option to save the plot to a PNG in memory, but then I don't know how to insert it into the PDF:

var stream = new MemoryStream();
var pngExporter = new PngExporter { Width = 600, Height = 400, Background = OxyColors.White };
pngExporter.Export(plotModel, stream);

I leave below the code that I am using to export the graph, in SVG format, and saving it in a folder. And then, I add it to the PDF. This is how I generate the SVG and export it:

using (var stremPieChart = File.Create("pieChart.svg"))
    {
           var exporter = new OxyPlot.SvgExporter { Width = 400, Height = 300, UseVerticalTextAlignmentWorkaround = true };
           exporter.Export(newPieModel, stremPieChart);
    }

And so I add it to the PDF:

.Element(element =>
{
    element
         .PaddingTop(-13)
         .PaddingLeft(4)
         .AlignCenter()
         .Canvas((canvas, size) =>
         {
              var pieChartSvg = new SKSvg();
              pieChartSvg.Load("pieChart.svg");
              canvas.Scale(0.65f);                         
              canvas.DrawPicture(pieChartSvg.Picture);
         });
});

I hope you can help me! Thank you!

CodePudding user response:

Since SVG is just text, you can probably save it in MemoryStream instead of FileStream, export it to array of bytes and then using encoding.GetString() to get the resulting text content of svg.

If this works, when loading your image you can pieChartSvg.FromSvg(svg) it.

like so:

string svgString;
using (var stremPieChart = new MemoryStream())
{
    var exporter = new OxyPlot.SvgExporter { 
        Width = 400, 
        Height = 300, 
        UseVerticalTextAlignmentWorkaround = true 
    };

    exporter.Export(newPieModel, stremPieChart);
    
    /// UTF8 or whatever the encoding may be, anyways...
    svgString = System.Text.Encoding.UTF8.GetString(stremPieChart)
}

and later

.Element(element =>
{
    element
         .PaddingTop(-13)
         .PaddingLeft(4)
         .AlignCenter()
         .Canvas((canvas, size) =>
         {
              var pieChartSvg = new SKSvg();
              pieChartSvg.FromSvg(svgString);
              canvas.Scale(0.65f);                         
              canvas.DrawPicture(pieChartSvg.Picture);
         });
});

CodePudding user response:

Unfortunately I couldn't save the svg in memory because the library doesn't allow in-memory export. So, I had to modify the logic to be able to save the svg to a temporary file and then consume and delete it. This is how I got the code:

.Element(element =>
{
     element
         .PaddingTop(-13)
         .PaddingLeft(4)
         .AlignCenter()
         .Canvas((canvas, size) =>
         {
              string pieChartTemp = Path.GetTempFileName();
              using (var stremPieChart = File.Create(pieChartTemp))
              {
                   var exporter = new OxyPlot.SvgExporter 
                   { 
                       Width = 400, 
                       Height = 300, 
                       UseVerticalTextAlignmentWorkaround = true 
                   };
                                                            
                   exporter.Export(newPieModel, stremPieChart);
              }

              var pieChartSvg = new SKSvg();                                         
              pieChartSvg.Load(pieChartTemp);
              canvas.Scale(0.65f);                          
              canvas.DrawPicture(pieChartSvg.Picture);  
                                                  
              File.Delete(pieChartTemp);
         });
});

As you can see, I first created a temporary path and then generated the .svg on that path. Then to load the SVG, I insert the temporary path.

  • Related