使用 C# 将 SVG 转换为 PNG [关闭]

Posted

技术标签:

【中文标题】使用 C# 将 SVG 转换为 PNG [关闭]【英文标题】:Converting SVG to PNG using C# [closed] 【发布时间】:2010-09-08 16:54:09 【问题描述】:

我一直在尝试使用 C# 将 SVG 图像转换为 PNG,而无需编写太多代码。任何人都可以推荐一个库或示例代码来执行此操作吗?

【问题讨论】:

我找到了一个不错的简单库,可以在c#中使用github.com/ElinamLLC/SharpVectors,它可以将多种svg转换为bmp、jpeg或png 我可以说:那些解决方案很糟糕,包括 wkhtml2pdf/wkhtml2image 等。SVG 规范复杂且不断发展,CSS 样式也是如此,最重要的是,它应该看起来与浏览器。例如,wkhtml2X 在字体方面存在大量问题,而且里面的 webkit 引擎太旧了。幸运的是,有一个解决方案:Chrome 有 headless-mode,并且通过它的 Debugging-API,您可以从 Headless-Chrome 本身获取 PNG 图像和 PDF,使用 C# 中的 MasterDevs/ChromeDevTools:示例:github.com/ststeiger/ChromeDevTools/blob/master/source/… 【参考方案1】:

使用库http://svg.codeplex.com/(较新版本@GIT、@NuGet)有一种更简单的方法。这是我的代码

var byteArray = Encoding.ASCII.GetBytes(svgFileContents);
using (var stream = new MemoryStream(byteArray))

    var svgDocument = SvgDocument.Open(stream);
    var bitmap = svgDocument.Draw();
    bitmap.Save(path, ImageFormat.Png);

【讨论】:

我不得不使用 github 版本,因为它是最新的,甚至不支持 image 元素。 我是从这段代码中使用的,当想要执行var bitmap = svgDocument.Draw();时它会抛出object not set to an instance of an object。有什么问题? @RasoolGhafari 确保您的 svgDocument 不为空。 svgDocument 不为空。这是图书馆的某种内部问题。 @JonathanAllen,我在回答 Rasool 的评论。【参考方案2】:

您可以调用命令行版本的 inkscape 来执行此操作:

http://harriyott.com/2008/05/converting-svg-images-to-png-in-c.aspx

还有一个 C# SVG 渲染引擎,主要设计用于允许 SVG 文件在 web 上的 codeplex 上使用,如果这是您的问题,可能会满足您的需求:

原创项目http://www.codeplex.com/svg

带有修复和更多活动的分叉:(2013 年 7 月添加)https://github.com/vvvv/SVG

【讨论】:

感谢埃斯波。我实际上写了那篇inkscape博客文章!尽管它“有效”,但它并不是一个特别强大的解决方案。不过,我喜欢 codeplex 项目——我来看看。谢谢。 多么尴尬 :) 好在也许 SVG 渲染引擎可以帮到你。 我认为这是一种恭维。我以前没有被自己引用过! 你试过svg渲染引擎吗?你能分享你的解决方案吗?我试图让它工作但遇到麻烦,see here 我已经尝试过github.com/vvvv/SVG,它可以工作,但有一定的限制。 image 元素尚未实现 - 我检查了源代码。 @FrankHale 我不得不从 svg 中删除一个 xmlns,因为 raphael 添加了两次。【参考方案3】:

当我不得不在服务器上光栅化 svgs 时,我最终使用 P/Invoke 来调用 librsvg 函数(您可以从 Windows 版本的 GIMP 图像编辑程序中获取 dll)。

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetDllDirectory(string pathname);

[DllImport("libgobject-2.0-0.dll", SetLastError = true)]
static extern void g_type_init(); 

[DllImport("librsvg-2-2.dll", SetLastError = true)]
static extern IntPtr rsvg_pixbuf_from_file_at_size(string file_name, int width, int height, out IntPtr error);

[DllImport("libgdk_pixbuf-2.0-0.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern bool gdk_pixbuf_save(IntPtr pixbuf, string filename, string type, out IntPtr error, __arglist);

public static void RasterizeSvg(string inputFileName, string outputFileName)

    bool callSuccessful = SetDllDirectory("C:\\Program Files\\GIMP-2.0\\bin");
    if (!callSuccessful)
    
        throw new Exception("Could not set DLL directory");
    
    g_type_init();
    IntPtr error;
    IntPtr result = rsvg_pixbuf_from_file_at_size(inputFileName, -1, -1, out error);
    if (error != IntPtr.Zero)
    
        throw new Exception(Marshal.ReadInt32(error).ToString());
    
    callSuccessful = gdk_pixbuf_save(result, outputFileName, "png", out error, __arglist(null));
    if (!callSuccessful)
    
        throw new Exception(error.ToInt32().ToString());
    

【讨论】:

librSVG 还不错,但是字体/文本,它不能正确处理它们。相反,请查看 headless-chrome、chrome-debugging API 和用于 chrome-debugging API 的 C# API:github.com/ststeiger/ChromeDevTools/blob/master/source/…【参考方案4】:

我为此使用Batik。完整的 Delphi 代码:

procedure ExecNewProcess(ProgramName : String; Wait: Boolean);
var
  StartInfo : TStartupInfo;
  ProcInfo : TProcessInformation;
  CreateOK : Boolean;
begin
  FillChar(StartInfo, SizeOf(TStartupInfo), #0);
  FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
  StartInfo.cb := SizeOf(TStartupInfo);
  CreateOK := CreateProcess(nil, PChar(ProgramName), nil, nil, False,
              CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS,
              nil, nil, StartInfo, ProcInfo);
  if CreateOK then begin
    //may or may not be needed. Usually wait for child processes
    if Wait then
      WaitForSingleObject(ProcInfo.hProcess, INFINITE);
  end else
    ShowMessage('Unable to run ' + ProgramName);

  CloseHandle(ProcInfo.hProcess);
  CloseHandle(ProcInfo.hThread);
end;

procedure ConvertSVGtoPNG(aFilename: String);
const
  ExecLine = 'c:\windows\system32\java.exe -jar C:\Apps\batik-1.7\batik-rasterizer.jar ';
begin
  ExecNewProcess(ExecLine + aFilename, True);
end;

【讨论】:

@downvoters - 请解释你为什么投反对票。没有解释的反对票的价值为零。 我猜反对票来自其中包含“c#”的问题文本。你的建议是delphi 没有投反对票,但您可以编辑您的答案并明确指出 Batik 是一个 Java 库,您可以从 C# 或任何语言调用它(在这种情况下,您展示了如何调用它在德尔福) 启动新进程很慢。另外,蜡染光栅化的正确程度如何?最新的二进制文件很难获得。与其忍受这些废话,不如看看 headless-chrome、chrome-debugging API 和用于 chrome-debugging API 的 C# API:github.com/ststeiger/ChromeDevTools/blob/master/source/… - 对于所有 Java 用户,我相信还有 Java- API 围绕着 chrome 的调试 API。【参考方案5】:

要添加到来自@Anish 的响应,如果您在将 SVG 导出到图像时遇到看不到文本的问题,您可以创建一个递归函数来循环遍历 SVGDocument 的子项,尝试将其转换为如果可能的话,一个 SvgText(添加您自己的错误检查)并设置字体系列和样式。

    foreach(var child in svgDocument.Children)
    
        SetFont(child);
    

    public void SetFont(SvgElement element)
    
        foreach(var child in element.Children)
        
            SetFont(child); //Call this function again with the child, this will loop
                            //until the element has no more children
        

        try
        
            var svgText = (SvgText)parent; //try to cast the element as a SvgText
                                           //if it succeeds you can modify the font

            svgText.Font = new Font("Arial", 12.0f);
            svgText.FontSize = new SvgUnit(12.0f);
        
        catch
        

        
    

如果有问题请告诉我。

【讨论】:

父在SetFont中没有定义,应该是元素或在函数签名处将元素变量重命名为父 现在也字体似乎是一个字符串。不过,这是救命稻草,谢谢!【参考方案6】:

您可以为此使用 altsoft xml2pdf lib

【讨论】:

以上是关于使用 C# 将 SVG 转换为 PNG [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

php下svg格式如何转换为png

将svg转换为png时如何包含CSS样式

svg格式的图片怎么转换成PNG的?

将png图片转换为字体图标

将 SVG 转换为 PNG,并将应用的图像作为 svg 元素的背景

使用 PHP 将 SVG 图像转换为 PNG