Conversione da SVG a PNG utilizzando C # [chiuso]


102

Ho provato a convertire immagini SVG in PNG usando C #, senza dover scrivere troppo codice. Qualcuno può consigliare una libreria o un codice di esempio per farlo?


ho trovato una libreria buona e semplice che puoi usare in c # github.com/ElinamLLC/SharpVectors , può convertire molti tipi di svg in bmp, jpeg o png
— Mahdi

2
Posso dire: quelle soluzioni sono pessime, incluse wkhtml2pdf / wkhtml2image ecc. La specifica SVG è complessa e in evoluzione, così come lo sono gli stili CSS e, soprattutto, dovrebbe avere lo stesso aspetto del browser. wkhtml2X, ad esempio, ha enormi problemi con i caratteri e il motore webkit al suo interno è troppo vecchio. Fortunatamente, c'è una soluzione: Chrome ha la modalità headless e con la sua API di debug, puoi ottenere immagini PNG e PDF dallo stesso Headless-Chrome, con MasterDevs / ChromeDevTools in C #: Esempio: github.com/ststeiger/ChromeDevTools / blob / master / source /…
— Stefan Steiger,

Risposte:


68

Puoi chiamare la versione a riga di comando di inkscape per fare questo:

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

Inoltre è disponibile un motore di rendering SVG C #, progettato principalmente per consentire l'utilizzo di file SVG sul Web su codeplex che potrebbe soddisfare le tue esigenze se questo è il tuo problema:

Progetto originale
http://www.codeplex.com/svg

Fork con correzioni e più attività: (aggiunto 7/2013)
https://github.com/vvvv/SVG


39
Grazie Espo. In realtà ho scritto quel post sul blog di Inkscape! Sebbene "funzioni", non è una soluzione particolarmente robusta. Però mi piace il progetto codeplex - lo darò un'occhiata. Grazie.
— harriyott

9
Che imbarazzo :) Meno male che forse il motore di rendering SVG potrebbe aiutarti.
— Espo

20
Lo prendo come un complimento. Non sono mai stato citato da me stesso prima!
— harriyott

hai provato il motore di rendering SVG? puoi condividere la tua soluzione per favore. Sto cercando di farlo funzionare ma ho problemi, vedi qui
— Armance

1
Ho provato github.com/vvvv/SVG e funziona ma con alcune limitazioni. L' imageelemento non è stato implementato: ho controllato il codice sorgente. @FrankHale ho dovuto rimuovere un xmlns dal svg perché Raphael lo ha aggiunto due volte.
— fireydude

74

Esiste un modo molto più semplice utilizzando la libreria http://svg.codeplex.com/ (versione più recente @ GIT , @ NuGet ). Ecco il mio codice

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
Ho dovuto usare la versione GitHub perché è più aggiornata e anche quella non supporta l' imageelemento.
— fireydude

sono usato da questo codice, viene lanciato object not set to an instance of an objectquando si desidera eseguire var bitmap = svgDocument.Draw();. qual è il problema?
— Rasool Ghafari

@RasoolGhafari assicurati che il tuo svgDocument non sia nullo.
— Anish

svgDocument non è nullo. Questo è un qualche tipo di problema interno nella libreria.
— Jonathan Allen

@ JonathanAllen, stavo rispondendo al commento di Rasool.
— Anish

12

Quando ho dovuto rasterizzare svgs sul server, ho finito per usare P / Invoke per chiamare le funzioni librsvg (puoi ottenere le dll da una versione Windows del programma di modifica delle immagini GIMP).

[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 non è male, ma caratteri / testo non li gestisce correttamente. Invece, dai un'occhiata a headless-chrome, API di debug di chrome e un'API C # per l'API di debug di chrome: github.com/ststeiger/ChromeDevTools/blob/master/source/…
— Stefan Steiger

8

Sto usando Batik per questo. Il codice Delphi completo:

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 - Spiega perché hai un voto negativo. Un voto negativo senza una spiegazione ha valore zero.
— Stevenvh

4
Immagino che i voti negativi provengano dal testo della domanda che contiene "c #". e la tua proposta è delphi
— Denis

non hai votato in basso, ma potresti modificare la tua risposta e chiarire che Batikè una libreria Java che potresti chiamare da C # o qualsiasi linguaggio (in questo caso hai mostrato come chiamarlo in Delphi)
— ErrCode

L'avvio di un nuovo processo è lento. Inoltre, quanto correttamente rasterizza il batik? Gli ultimi binari sono difficili da ottenere. Invece di sopportare quella merda, dai un'occhiata a headless-chrome, API di debug di chrome e un'API C # per l'API di debug di chrome: github.com/ststeiger/ChromeDevTools/blob/master/source/… - Per tutti Utenti Java, sono sicuro che ci siano anche API Java attorno all'API di debug di Chrome.
— Stefan Steiger

4

Per aggiungere alla risposta di @Anish, se hai problemi con la mancata visualizzazione del testo durante l'esportazione dell'SVG in un'immagine, puoi creare una funzione ricorsiva per scorrere i figli dell'SVGDocument, provare a trasmetterlo a un SvgText se possibile (aggiungi il tuo controllo degli errori) e imposta la famiglia e lo stile dei caratteri.

    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
        {

        }
    }

Fammi sapere se ci sono domande.


parent non è definito in SetFont, dovrebbe essere elemento o rinominare la variabile dell'elemento in parent nella firma della funzione
— Norbert Kardos

Anche il carattere ora sembra essere una stringa. Comunque questo è stato un vero toccasana, grazie!
— Norbert Kardos

-3

puoi usare altsoft xml2pdf lib per questo

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.