将 SVG 保存在内存流中以将其输入到 PDF 中(C# OxyPlot 和 QuestPDF)

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

我目前正在使用 OxyPlot 和 QuestPDF 库来生成带有图表的 PDF。我设计了饼图和条形图。我目前正在保存图表,将它们导出到 SVG,放在一个文件夹中,然后将它们添加到 PDF 中。我想更改此设置并将它们保存在内存中,然后将它们添加到 PDF 中。 根据我从 OxyPlot 库中读取的文档,它有一个选项可以将绘图保存到内存中的 PNG,但是我不知道如何将它插入到 PDF 中:

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

我在下面留下了我用来以 SVG 格式导出图形并将其保存在文件夹中的代码。然后,我将它添加到 PDF 中。这就是我生成 SVG 并将其导出的方式:

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

所以我将其添加到 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);
         });
});

希望你能帮帮我!谢谢!

由于 SVG 只是文本,您可以将其保存在 MemoryStream 而不是 FileStream 中,将其导出到字节数组,然后使用 encoding.GetString() 获取结果文本内容svg.

如果这可行,加载图像时您可以pieChartSvg.FromSvg(svg)它。

像这样:

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)
}

以后

.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);
         });
});

更新

根据 OxyPlot 的 github 存储库,即使没有记录,SvgExporter 似乎有一个名为 ExportToString 的方法,它更适合我的示例并且不'创建有关流类型的问题。

相关代码:here (line 115 - 123)

也就是说,我的例子可能是这样的:

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

以后

.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);
         });
});

不幸的是,我无法将 svg 保存在内存中,因为该库不允许 in-memory 导出。因此,我必须修改逻辑才能将 svg 保存到临时文件,然后使用并删除它。这就是我获得代码的方式:

.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);
         });
});

如您所见,我首先创建了一个临时路径,然后在该路径上生成了 .svg。 然后加载 SVG,我插入临时路径。