Conversión de SVG a PNG usando C # [cerrado]

102

He intentado convertir imágenes SVG a PNG usando C #, sin tener que escribir demasiado código. ¿Alguien puede recomendar una biblioteca o un código de ejemplo para hacer esto?

harriyott
fuente
Encontré una biblioteca buena y simple que puede usar en c # github.com/ElinamLLC/SharpVectors , puede convertir muchos tipos de svg a bmp, jpeg o png
Mahdi
2
Puedo decir: esas soluciones son malas, incluyendo wkhtml2pdf / wkhtml2image, etc. La especificación SVG es compleja y evoluciona, al igual que los estilos CSS, y además de eso, debería verse igual que en el navegador. wkhtml2X, por ejemplo, tiene grandes problemas con las fuentes, y el motor webkit interno es demasiado antiguo. Afortunadamente, hay una solución: Chrome tiene modo sin cabeza, y con su API de depuración, puede obtener imágenes PNG y PDF de los propios Headless-Chrome, con MasterDevs / ChromeDevTools en C #: Ejemplo: github.com/ststeiger/ChromeDevTools / blob / master / source /…
Stefan Steiger

Respuestas:

68

Puede llamar a la versión de línea de comandos de inkscape para hacer esto:

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

También hay un motor de renderizado C # SVG, diseñado principalmente para permitir que los archivos SVG se utilicen en la web en un codeplex que podría satisfacer sus necesidades si ese es su problema:

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

Bifurcación con correcciones y más actividad: (agregado 7/2013)
https://github.com/vvvv/SVG

Espo
fuente
39
Gracias Espo. De hecho, escribí esa publicación de blog de Inkscape. Aunque "funciona", no es una solución particularmente sólida. Sin embargo, me gusta el proyecto del codeplex, lo echaré un vistazo. Gracias.
harriyott
9
Qué vergüenza :) Lo bueno es que quizás el motor de renderizado SVG podría ayudarte.
Espo
20
Lo tomo como un cumplido. ¡No me han citado antes!
harriyott
¿Has probado el motor de renderizado svg? ¿Puedes compartir tu solución por favor? Estoy tratando de hacerlo funcionar pero tengo problemas, mira aquí
Armance
1
He tratado github.com/vvvv/SVG y funciona pero con ciertas limitaciones. El imageelemento no se ha implementado; verifiqué el código fuente. @FrankHale Tuve que eliminar un xmlns del svg porque raphael lo agregó dos veces.
fireydude
74

Hay una manera mucho más fácil de usar la biblioteca http://svg.codeplex.com/ (versión más reciente @ GIT , @ NuGet ). Aqui esta mi codigo

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
fuente
1
Tuve que usar la versión de github porque está más actualizada e incluso eso no es compatible con el imageelemento.
fireydude
Estoy acostumbrado a este código, lanza object not set to an instance of an objectcuando quiero ejecutar var bitmap = svgDocument.Draw();. ¿Cuál es el problema?
Rasool Ghafari
@RasoolGhafari asegúrese de que su svgDocument no sea nulo.
Anish
svgDocument no es nulo. Este es algún tipo de problema interno en la biblioteca.
Jonathan Allen
@JonathanAllen, estaba respondiendo al comentario de Rasool.
Anish
12

Cuando tuve que rasterizar svgs en el servidor, terminé usando P / Invoke para llamar a las funciones librsvg (puede obtener los dlls desde una versión de Windows del programa de edición de imágenes 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());
    }
}
noroeste.
fuente
1
librSVG no está mal, pero las fuentes / texto no las maneja correctamente. En su lugar, eche un vistazo a la API de depuración de chrome sin cabeza, y una API de C # para la API de depuración de Chrome
Stefan Steiger
8

Estoy usando Batik para esto. El código completo de 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;
stevenvh
fuente
@downvoters: explique por qué votó en contra. Un voto negativo sin explicación tiene valor cero.
stevenvh
4
Supongo que los votos negativos provienen del texto de la pregunta que contiene "c #". y tu propuesta es Delphi
Denis
no votó negativamente, pero puede editar su respuesta y dejar en claro que Batikes una biblioteca de Java a la que puede llamar desde C # o cualquier idioma (en este caso, mostró cómo llamarlo en Delphi)
ErrCode
Iniciar un nuevo proceso es lento. Además, ¿qué tan correctamente se rasteriza batik? Los últimos binarios son difíciles de obtener. En lugar de aguantar esa mierda, eche un vistazo a la API de depuración de chrome sin cabeza, y una API de C # para la API de depuración de Chrome : github.com/ststeiger/ChromeDevTools/blob/master/source/… - Para todos Usuarios de Java, estoy seguro de que también hay API de Java en torno a la API de depuración de Chrome.
Stefan Steiger
4

Para agregar a la respuesta de @Anish, si tiene problemas para no ver el texto al exportar el SVG a una imagen, puede crear una función recursiva para recorrer los elementos secundarios del SVGDocument, intente convertirlo en un SvgText si posible (agregue su propia comprobación de errores) y configure la familia de fuentes y el estilo.

    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
        {

        }
    }

Avíseme si hay preguntas.

Michal Kieloch
fuente
padre no está definido en SetFont, debe ser elemento o cambiar el nombre de la variable del elemento a padre en la firma de la función
Norbert Kardos
También Font parece ser una cadena ahora. Sin embargo, esto fue un salvavidas, ¡gracias!
Norbert Kardos
-3

puedes usar altsoft xml2pdf lib para esto


fuente