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


102

我一直在尝试使用C#将SVG图像转换为PNG,而不必编写太多代码。谁能推荐这样做的库或示例代码?


我找到了一个很好的简单库,可以在c#github.com/ElinamLLC/SharpVectors中使用,它可以将许多类型的svg转换为bmp,jpeg或png
Mahdi,

2
我可以说:这些解决方案是不好的,包括wkhtml2pdf / wkhtml2image等。SVG规范复杂且不断发展,CSS样式也是如此,最重要的是,它应与浏览器中的外观相同。例如,wkhtml2X的字体存在大量问题,并且内部的Webkit引擎太旧了。幸运的是,有一个解决方案:Chrome具有无头模式,并且通过其Debugging-API,您可以使用C#中的MasterDevs / ChromeDevTools从Headless-Chrome本身获取PNG图像和PDF:示例:github.com/ststeiger/ChromeDevTools / blob / master / source / ...
Stefan Steiger

Answers:


68

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

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

还有一个C#SVG呈现引擎,主要设计为允许SVG文件在网络上在Codeplex上使用,如果这是您的问题,它可能会满足您的需求:

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

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


39
谢谢埃斯波。我实际上写了那篇inkscape博客文章!尽管它“有效”,但它并不是一个特别强大的解决方案。不过,我喜欢Codeplex项目-我来看一下。谢谢。
harriyott

9
真令人尴尬:)也许SVG渲染引擎可以帮助您。
Espo

20
我认为这是一种赞美。我以前没有被自己引用过!
harriyott

您是否尝试过svg渲染引擎?您能分享您的解决方案吗?我正在尝试使其正常运行,但遇到了麻烦,请参阅此处
-Armance

1
我尝试了github.com/vvvv/SVG,它可以工作,但有一定的限制。该image元素尚未实现-我检查了源代码。@FrankHale我不得不从svg中删除xmlns,因为raphael两次添加了它。
fireydude

74

使用库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);
}

1
我必须使用github版本,因为它是最新的,甚至不支持该image元素。
fireydude

我从这段代码中使用过,它object not set to an instance of an object在要执行时抛出var bitmap = svgDocument.Draw();。有什么问题?
Rasool Ghafari 2015年

@RasoolGhafari确保您的svgDocument不为null。
阿尼什(Anish)2015年

svgDocument不为null。这是库中的某种内部问题。
乔纳森·艾伦

@JonathanAllen,我正在回答Rasool的评论。
阿尼什(Anish)2015年

12

当不得不在服务器上光栅化svg时,我最终使用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());
    }
}

1
librSVG不错,但是字体/文本不能正确处理它们。相反,看看无头,镀铬,镀铬调试API,以及用于铬调试API一个C#API: github.com/ststeiger/ChromeDevTools/blob/master/source/...
斯特凡·斯泰格尔

8

我为此使用蜡染。完整的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-请说明为什么要投票。没有解释的下降投票的值为零。
stevenvh 16/09/19

4
我猜否决票来自其中包含“ c#”的问题文本。而您的建议是delphi
Denis

并没有投票,但是您可以编辑答案,并明确说明Batik可以使用C#或任何语言(在这种情况下,您演示了如何在Delphi中调用它)调用的Java库
ErrCode

启动新进程很慢。此外,蜡染栅格化的正确程度如何?最新的二进制文件很难获得。与其忍受这种废话,不如看看无头铬,铬调试API和用于铬调试API的C#API: github.com/ststeiger/ChromeDevTools/blob/master/source/…-全部Java用户,我确定chrome的debugging-API周围也有Java-API。
Stefan Steiger

4

要添加到@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中定义,应为元素或在函数签名处将元素变量重命名为父元素
Norbert Kardos,

而且Font现在似乎是一个字符串。但是,这是一个救命稻草,谢谢!
诺伯特·卡多斯

-3

您可以为此使用altsoft xml2pdf lib

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.