ChatGPT解决这个技术问题 Extra ChatGPT

Converting SVG to PNG using C# [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers. Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it. Closed 8 years ago. Improve this question

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?

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 png
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/…

A
AxelEckenberger

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

I had to use the github version because it's more up-to-date and even that does not support the image element.
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?
@RasoolGhafari make sure your svgDocument is not null.
svgDocument is not null. This is some kind of internal problem in the library.
@JonathanAllen, I was answering Rasool's comment.
h
harriyott

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


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.
How embarrassing :) Good thing maybe the SVG rendering engine could help you out though.
I take it as a compliment. I've not been quoted to myself before!
have u tried the svg rendering engine? can u share ur solution plz. im trying to make it work but having troubles,see here
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.
U
Uwe Keim

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

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/…
s
stevenvh

I'm using Batik for this. The complete Delphi code:

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 - Please explain why you downvote. A downvote without an explanation has zero value.
i guess downvotes come from the question text which contain "c#" in it. and your proposal is delphi
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)
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.
M
Michal Kieloch

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.


parent is not defined in SetFont, should be element or rename the element variable to parent at the function signature
Also Font seems to be a string now. However this was a lifesaver, thanks!
佚名

you can use altsoft xml2pdf lib for this