Converting SVG to PNG using C# [closed]
Asked Answered
S

6

119

I've been trying to convert SVG images to PNG using C#, without having to write too much code. Can anyone recommend a library or example code for doing this?

Semivitreous answered 12/9, 2008 at 13:9 Comment(2)
i found a good and simple library that you can use in c# github.com/ElinamLLC/SharpVectors , it can convert many type of svg to bmp, jpeg or pngRestraint
May I say: those solutions are bad, including wkhtml2pdf/wkhtml2image etc. The SVG specification is complex and evolving, so is CSS-styles, and on top of that, it should look the same as in the browser. wkhtml2X, for example, has massive problems with fonts, and the webkit engine inside is just too old. Fortunately, there is a solution: Chrome has headless-mode, and with its Debugging-API, you can get PNG-images and PDFs from Headless-Chrome itselfs, with MasterDevs/ChromeDevTools in C#: Example: github.com/ststeiger/ChromeDevTools/blob/master/source/…Mayoralty
A
72

You can call the command-line version of inkscape to do this:

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

Also there is a C# SVG rendering engine, primarily designed to allow SVG files to be used on the web on codeplex that might suit your needs if that is your problem:

Original Project
http://www.codeplex.com/svg

Fork with fixes and more activity: (added 7/2013)
https://github.com/vvvv/SVG

Abbotson answered 12/9, 2008 at 13:11 Comment(11)
Thanks Espo. I actually wrote that inkscape blog post! Although it "works", it's not a particularly robust solution. I like the codeplex project though - I'll give it a look. Thanks.Semivitreous
How embarrassing :) Good thing maybe the SVG rendering engine could help you out though.Abbotson
I take it as a compliment. I've not been quoted to myself before!Semivitreous
have u tried the svg rendering engine? can u share ur solution plz. im trying to make it work but having troubles,see hereGray
astrocybernaute, Svg Rendering Engine is a no go for me to. I get the same error as you.Swen
@astrocybernaute Please, try to keep a minimum of proper grammar.Lactescent
I have tried github.com/vvvv/SVG and it works but with certain limitations. The image element has not been implemented - I checked the source code. @FrankHale I had to remove an xmlns from the svg because raphael added it twice.Ervinervine
Some feedback: 1. inkscape works well with my 30 test images, result is correct. But very slow, on Core i7-3520M takes 248 secs. 2. github.com/vvvv/SVG ver 1.7, produces incorrect result, have not try codeplex.com/svg. Plus, I also tried SharpVectorGraphics.0.3, test one file, cannot handle font correctly.Eryn
+ I've just tried CoolUtils's "Total CAD converter" ver 3.1.56 with one svg file, produce incorrect result.Eryn
Inkscape is unreliable, slow, not multi-threading conformant, and doesn't necessarely handle CSS-styles correctly. Instead, take a look at headless-chrome, chrome-debugging API, and a C# API for the chrome-debugging API: github.com/ststeiger/ChromeDevTools/blob/master/source/…Mayoralty
It doesnt work on linuxTillery
S
91

There is a much easier way using the library http://svg.codeplex.com/ (Newer version @GIT, @NuGet). Here is my code

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);
}
Scandal answered 14/10, 2012 at 16:54 Comment(9)
I had to use the github version because it's more up-to-date and even that does not support the image element.Ervinervine
i'm used from this code, it throws object not set to an instance of an object when want to execute var bitmap = svgDocument.Draw();. what's the problem?Barbel
@RasoolGhafari make sure your svgDocument is not null.Scandal
svgDocument is not null. This is some kind of internal problem in the library.Bowse
@JonathanAllen, I was answering Rasool's comment.Scandal
Yea, but the exact same thing is happening to me. Seems to be a flaw in how it handles SVG files that it can't fully render.Bowse
vvvv/SVG doesn't handle CSS-styles correctly. Fonts are incorrect, too. Instead, take a look at headless-chrome, chrome-debugging API, and a C# API for the chrome-debugging API: github.com/ststeiger/ChromeDevTools/blob/master/source/…Mayoralty
It doesnt work on linuxTillery
It worked perfectly for me on a Win64 .Net Core app hosted in Azure.Electroacoustics
A
72

You can call the command-line version of inkscape to do this:

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

Also there is a C# SVG rendering engine, primarily designed to allow SVG files to be used on the web on codeplex that might suit your needs if that is your problem:

Original Project
http://www.codeplex.com/svg

Fork with fixes and more activity: (added 7/2013)
https://github.com/vvvv/SVG

Abbotson answered 12/9, 2008 at 13:11 Comment(11)
Thanks Espo. I actually wrote that inkscape blog post! Although it "works", it's not a particularly robust solution. I like the codeplex project though - I'll give it a look. Thanks.Semivitreous
How embarrassing :) Good thing maybe the SVG rendering engine could help you out though.Abbotson
I take it as a compliment. I've not been quoted to myself before!Semivitreous
have u tried the svg rendering engine? can u share ur solution plz. im trying to make it work but having troubles,see hereGray
astrocybernaute, Svg Rendering Engine is a no go for me to. I get the same error as you.Swen
@astrocybernaute Please, try to keep a minimum of proper grammar.Lactescent
I have tried github.com/vvvv/SVG and it works but with certain limitations. The image element has not been implemented - I checked the source code. @FrankHale I had to remove an xmlns from the svg because raphael added it twice.Ervinervine
Some feedback: 1. inkscape works well with my 30 test images, result is correct. But very slow, on Core i7-3520M takes 248 secs. 2. github.com/vvvv/SVG ver 1.7, produces incorrect result, have not try codeplex.com/svg. Plus, I also tried SharpVectorGraphics.0.3, test one file, cannot handle font correctly.Eryn
+ I've just tried CoolUtils's "Total CAD converter" ver 3.1.56 with one svg file, produce incorrect result.Eryn
Inkscape is unreliable, slow, not multi-threading conformant, and doesn't necessarely handle CSS-styles correctly. Instead, take a look at headless-chrome, chrome-debugging API, and a C# API for the chrome-debugging API: github.com/ststeiger/ChromeDevTools/blob/master/source/…Mayoralty
It doesnt work on linuxTillery
L
12

When I had to rasterize svgs on the server, I ended up using P/Invoke to call librsvg functions (you can get the dlls from a windows version of the GIMP image editing program).

[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());
    }
}
Lamebrain answered 9/8, 2011 at 22:25 Comment(1)
librSVG is not bad, but fonts/text, it doesn't handle them correctly. Instead, take a look at headless-chrome, chrome-debugging API, and a C# API for the chrome-debugging API: github.com/ststeiger/ChromeDevTools/blob/master/source/…Mayoralty
O
8

I'm using Batik for this. Batik is a graphics library written in Java, with a command line interface. This makes that you can Batik from C#, same as the following example in 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;
Oakman answered 14/2, 2009 at 5:34 Comment(4)
@downvoters - Please explain why you downvote. A downvote without an explanation has zero value.Oakman
i guess downvotes come from the question text which contain "c#" in it. and your proposal is delphiKnighton
didn't downvote, but you could edit your answer and make it clear that Batik is a Java library that you could call from C# or whatever language (in this case you showed how to call it in Delphi)Cardiff
Starting a new process is slow. Also, how correctly does batik rasterize ? Latest binaries are hard to get. Instead of putting up with that crap, take a look at headless-chrome, chrome-debugging API, and a C# API for the chrome-debugging API: github.com/ststeiger/ChromeDevTools/blob/master/source/… - For all Java-users, I'm sure there's also Java-API's around chrome's debugging-API.Mayoralty
D
4

To add to the response from @Anish, if you are having issues with not seeing the text when exporting the SVG to an image, you can create a recursive function to loop through the children of the SVGDocument, try to cast it to a SvgText if possible (add your own error checking) and set the font family and style.

    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
        {

        }
    }

Let me know if there are questions.

Deadbeat answered 14/2, 2013 at 16:4 Comment(2)
parent is not defined in SetFont, should be element or rename the element variable to parent at the function signatureDoughboy
Also Font seems to be a string now. However this was a lifesaver, thanks!Doughboy
A
-4

you can use altsoft xml2pdf lib for this

Andrej answered 24/2, 2009 at 21:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.