Conversion de SVG en PNG en utilisant C # [fermé]

102

J'ai essayé de convertir des images SVG en PNG en utilisant C #, sans avoir à écrire trop de code. Quelqu'un peut-il recommander une bibliothèque ou un exemple de code pour ce faire?

harriyott
la source
J'ai trouvé une bonne et simple bibliothèque que vous pouvez utiliser dans c # github.com/ElinamLLC/SharpVectors , elle peut convertir de nombreux types de svg en bmp, jpeg ou png
Mahdi
2
Puis-je dire: ces solutions sont mauvaises, y compris wkhtml2pdf / wkhtml2image etc. La spécification SVG est complexe et évolutive, tout comme les styles CSS, et en plus de cela, il devrait avoir la même apparence que dans le navigateur. wkhtml2X, par exemple, a d'énormes problèmes avec les polices et le moteur Webkit à l'intérieur est tout simplement trop ancien. Heureusement, il existe une solution: Chrome a le mode sans tête, et avec son API de débogage, vous pouvez obtenir des images PNG et des PDF à partir de Headless-Chrome lui-même, avec MasterDevs / ChromeDevTools en C #: Exemple: github.com/ststeiger/ChromeDevTools / blob / master / source /…
Stefan Steiger

Réponses:

68

Vous pouvez appeler la version en ligne de commande d'Inkscape pour ce faire:

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

Il existe également un moteur de rendu C # SVG, principalement conçu pour permettre l'utilisation de fichiers SVG sur le Web sur un codeplex qui pourrait répondre à vos besoins si tel est votre problème:

Projet original
http://www.codeplex.com/svg

Fork avec des correctifs et plus d'activité: (ajouté 7/2013)
https://github.com/vvvv/SVG

Espo
la source
39
Merci Espo. J'ai en fait écrit ce billet de blog inkscape! Bien que cela «fonctionne», ce n'est pas une solution particulièrement robuste. J'aime bien le projet codeplex - je vais y jeter un coup d'œil. Merci.
harriyott
9
Comment embarrassant :) Heureusement, peut-être que le moteur de rendu SVG pourrait vous aider.
Espo le
20
Je le prends comme un compliment. Je ne me suis jamais cité auparavant!
harriyott
avez-vous essayé le moteur de rendu svg? pouvez-vous partager votre solution plz. Im essayant de le faire fonctionner mais ayant des problèmes, voir ici
Armance
1
J'ai essayé github.com/vvvv/SVG et cela fonctionne mais avec certaines limitations. L' imageélément n'a pas été implémenté - j'ai vérifié le code source. @FrankHale J'ai dû supprimer un xmlns du svg parce que Raphael l'a ajouté deux fois.
fireydude
74

Il existe un moyen beaucoup plus simple d'utiliser la bibliothèque http://svg.codeplex.com/ (version plus récente @ GIT , @ NuGet ). Voici mon 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);
}
Anish
la source
1
J'ai dû utiliser la version github car elle est plus à jour et même cela ne prend pas en charge l' imageélément.
fireydude
je suis utilisé à partir de ce code, il jette object not set to an instance of an objectquand je veux exécuter var bitmap = svgDocument.Draw();. quel est le problème?
Rasool Ghafari
@RasoolGhafari assurez-vous que votre svgDocument n'est pas nul.
Anish
svgDocument n'est pas nul. C'est une sorte de problème interne à la bibliothèque.
Jonathan Allen
@JonathanAllen, je répondais au commentaire de Rasool.
Anish
12

Quand j'ai dû rastériser des svgs sur le serveur, j'ai fini par utiliser P / Invoke pour appeler les fonctions librsvg (vous pouvez obtenir les dll à partir d'une version Windows du programme d'édition d'images 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());
    }
}
nw.
la source
1
librSVG n'est pas mauvais, mais polices / texte, il ne les gère pas correctement. Jetez plutôt un œil à l'API headless-chrome, chrome-debugging et à une API C # pour l'API chrome-debugging: github.com/ststeiger/ChromeDevTools/blob/master/source
Stefan Steiger
8

J'utilise Batik pour cela. Le code Delphi complet:

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;
Stevenvh
la source
@downvoters - Veuillez expliquer pourquoi vous votez contre. Un vote défavorable sans explication a une valeur nulle.
stevenvh
4
Je suppose que les votes négatifs proviennent du texte de la question qui contient "c #". et votre proposition est delphi
Denis
n'a pas voté contre, mais vous pouvez modifier votre réponse et préciser qu'il Batiks'agit d'une bibliothèque Java que vous pouvez appeler à partir de C # ou de n'importe quel langage (dans ce cas, vous avez montré comment l'appeler en Delphi)
ErrCode
Le démarrage d'un nouveau processus est lent. Aussi, comment le batik est-il correctement pixellisé? Les derniers binaires sont difficiles à obtenir. Au lieu de supporter cette merde, jetez un œil à l'API headless-chrome, chrome-debugging et une API C # pour l'API chrome-debugging: github.com/ststeiger/ChromeDevTools/blob/master/source/… - Pour tous Utilisateurs Java, je suis sûr qu'il existe également des API Java autour de l'API de débogage de Chrome.
Stefan Steiger
4

Pour ajouter à la réponse de @Anish, si vous rencontrez des problèmes pour ne pas voir le texte lors de l'exportation du SVG vers une image, vous pouvez créer une fonction récursive pour parcourir les enfants du SVGDocument, essayez de le convertir en SvgText si possible (ajoutez votre propre vérification d'erreur) et définissez la famille et le style de police.

    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
        {

        }
    }

Faites-moi savoir s'il y a des questions.

Michal Kieloch
la source
parent n'est pas défini dans SetFont, devrait être un élément ou renommer la variable d'élément en parent à la signature de la fonction
Norbert Kardos
La police semble également être une chaîne maintenant. Cependant, c'était une bouée de sauvetage, merci!
Norbert Kardos
-3

vous pouvez utiliser altsoft xml2pdf lib pour cela


la source