Konvertieren von SVG in PNG mit C # [geschlossen]


102

Ich habe versucht, SVG-Bilder mit C # in PNG zu konvertieren, ohne zu viel Code schreiben zu müssen. Kann jemand eine Bibliothek oder einen Beispielcode dafür empfehlen?


Ich habe eine gute und einfache Bibliothek gefunden, die Sie in c # github.com/ElinamLLC/SharpVectors verwenden können. Sie kann viele Arten von SVG in BMP, JPEG oder PNG konvertieren
Mahdi

2
Darf ich sagen: Diese Lösungen sind schlecht, einschließlich wkhtml2pdf / wkhtml2image usw. Die SVG-Spezifikation ist komplex und entwickelt sich weiter, ebenso wie CSS-Stile. Außerdem sollte sie genauso aussehen wie im Browser. wkhtml2X hat zum Beispiel massive Probleme mit Schriftarten, und die Webkit-Engine im Inneren ist einfach zu alt. Glücklicherweise gibt es eine Lösung: Chrome hat den Headless-Modus und mit seiner Debugging-API können Sie PNG-Bilder und PDFs von Headless-Chrome selbst mit MasterDevs / ChromeDevTools in C # abrufen: Beispiel: github.com/ststeiger/ChromeDevTools / blob / master / source /…
Stefan Steiger

Antworten:


68

Sie können dazu die Befehlszeilenversion von inkscape aufrufen:

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

Außerdem gibt es eine C # SVG-Rendering-Engine, die in erster Linie dafür ausgelegt ist, SVG-Dateien im Web auf Codeplex zu verwenden, die Ihren Anforderungen entsprechen könnten, wenn dies Ihr Problem ist:

Originalprojekt
http://www.codeplex.com/svg

Gabel mit Korrekturen und mehr Aktivität: (hinzugefügt 7/2013)
https://github.com/vvvv/SVG


39
Danke Espo. Ich habe diesen Inkscape-Blog-Beitrag tatsächlich geschrieben! Obwohl es "funktioniert", ist es keine besonders robuste Lösung. Ich mag das Codeplex-Projekt - ich werde es mir ansehen. Vielen Dank.
Harriyott

9
Wie peinlich :) Gut, dass die SVG-Rendering-Engine Ihnen vielleicht helfen könnte.
Espo

20
Ich nehme es als Kompliment. Ich bin noch nie für mich selbst zitiert worden!
Harriyott

Hast du die SVG-Rendering-Engine ausprobiert? Kannst du deine Lösung teilen? Ich versuche es zum Laufen zu bringen, habe aber Probleme, siehe hier
Armance

1
Ich habe github.com/vvvv/SVG ausprobiert und es funktioniert aber mit gewissen Einschränkungen. Das imageElement wurde nicht implementiert - ich habe den Quellcode überprüft. @FrankHale Ich musste eine XML-Datei aus dem SVG entfernen, da Raphael sie zweimal hinzugefügt hat.
Fireydude

74

Es gibt eine viel einfachere Möglichkeit, die Bibliothek http://svg.codeplex.com/ (neuere Version @ GIT , @ NuGet ) zu verwenden. Hier ist mein 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);
}

1
Ich musste die Github-Version verwenden, weil sie aktueller ist und selbst das das imageElement nicht unterstützt .
Fireydude

Ich werde von diesem Code verwendet, er wirft, object not set to an instance of an objectwenn er ausgeführt werden soll var bitmap = svgDocument.Draw();. was ist das Problem?
Rasool Ghafari

@RasoolGhafari stellen Sie sicher, dass Ihr svgDocument nicht null ist.
Anish

svgDocument ist nicht null. Dies ist eine Art internes Problem in der Bibliothek.
Jonathan Allen

@ JonathanAllen, ich habe Rasools Kommentar beantwortet.
Anish

12

Als ich svgs auf dem Server rastern musste, habe ich P / Invoke verwendet, um librsvg-Funktionen aufzurufen (Sie können die DLLs von einer Windows-Version des GIMP-Bildbearbeitungsprogramms erhalten).

[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 ist nicht schlecht, aber Schriftarten / Text werden nicht richtig behandelt. Schauen Sie sich stattdessen Headless-Chrome, Chrome-Debugging-API und eine C # -API für die Chrome-Debugging-API an: github.com/ststeiger/ChromeDevTools/blob/master/source/…
Stefan Steiger

8

Ich benutze Batik dafür. Der vollständige 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 - Bitte erklären Sie, warum Sie abstimmen. Ein Downvote ohne Erklärung hat den Wert Null.
Stevenvh

4
Ich denke, Downvotes kommen aus dem Fragentext, der "c #" enthält. und Ihr Vorschlag ist delphi
Denis

hat nicht abgelehnt, aber Sie können Ihre Antwort bearbeiten und klarstellen, dass Batikes sich um eine Java-Bibliothek handelt, die Sie aus C # oder einer anderen Sprache aufrufen können (in diesem Fall haben Sie gezeigt, wie man sie in Delphi
aufruft

Das Starten eines neuen Prozesses ist langsam. Wie richtig rastert Batik? Neueste Binärdateien sind schwer zu bekommen. Werfen Sie einen Blick auf Headless-Chrome, Chrome-Debugging-API und eine C # -API für die Chrome-Debugging-API, anstatt sich mit diesem Mist abzufinden : github.com/ststeiger/ChromeDevTools/blob/master/source/… - Für alle Java-Benutzer, ich bin sicher, es gibt auch Java-APIs rund um die Debugging-API von Chrome.
Stefan Steiger

4

Um der Antwort von @Anish hinzuzufügen, können Sie eine rekursive Funktion erstellen, um die untergeordneten Elemente des SVGDocument zu durchlaufen, und versuchen, sie in einen SvgText umzuwandeln, wenn Sie Probleme haben, den Text beim Exportieren des SVG in ein Bild nicht zu sehen möglich (fügen Sie Ihre eigene Fehlerprüfung hinzu) und legen Sie die Schriftfamilie und den Schriftstil fest.

    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
        {

        }
    }

Lassen Sie mich wissen, wenn es Fragen gibt.


Eltern ist nicht in SetFont definiert, sollte Element sein oder die Elementvariable bei der Funktionssignatur in Eltern umbenennen
Norbert Kardos

Auch Font scheint jetzt eine Zeichenfolge zu sein. Dies war jedoch ein Lebensretter, danke!
Norbert Kardos

-3

Sie können hierfür die altsoft xml2pdf lib verwenden

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.