Converter SVG em PNG usando C # [fechado]

102

Tenho tentado converter imagens SVG para PNG usando C #, sem ter que escrever muito código. Alguém pode recomendar uma biblioteca ou código de exemplo para fazer isso?

Harriyott
fonte
Eu encontrei uma biblioteca boa e simples que você pode usar em c # github.com/ElinamLLC/SharpVectors , ela pode converter muitos tipos de svg para bmp, jpeg ou png
Mahdi
2
Posso dizer: essas soluções são ruins, incluindo wkhtml2pdf / wkhtml2image etc. A especificação SVG é complexa e está em evolução, assim como os estilos CSS e, além disso, deve ser igual ao do navegador. wkhtml2X, por exemplo, tem enormes problemas com fontes, e o motor do webkit interno é muito antigo. Felizmente, há uma solução: o Chrome tem o modo headless, e com sua Debugging-API, você pode obter imagens PNG e PDFs do próprio Headless-Chrome, com MasterDevs / ChromeDevTools em C #: Exemplo: github.com/ststeiger/ChromeDevTools / blob / master / source /…
Stefan Steiger,

Respostas:

68

Você pode chamar a versão de linha de comando do inkscape para fazer isso:

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

Também há um mecanismo de renderização C # SVG, projetado principalmente para permitir que arquivos SVG sejam usados ​​na web em codeplex que pode atender às suas necessidades, se esse for o seu problema:

Projeto Original
http://www.codeplex.com/svg

Fork com correções e mais atividades: (adicionado em 7/2013)
https://github.com/vvvv/SVG

Espo
fonte
39
Obrigado Espo. Na verdade, eu escrevi aquele post no blog do inkscape! Embora "funcione", não é uma solução particularmente robusta. Eu gosto do projeto codeplex - vou dar uma olhada. Obrigado.
harriyott de
9
Que vergonha :) Ainda bem que o motor de renderização SVG pode ajudá-lo.
Espo
20
Eu tomo isso como um elogio. Eu não fui citado antes!
harriyott de
Você já experimentou o mecanismo de renderização SVG? u pode compartilhar ur solução plz. estou tentando fazer funcionar, mas estou tendo problemas, veja aqui
Armance
1
Tentei github.com/vvvv/SVG e funciona, mas com certas limitações. O imageelemento não foi implementado - verifiquei o código-fonte. @FrankHale Tive que remover um xmlns do svg porque raphael o adicionou duas vezes.
fireydude
74

Há uma maneira muito mais fácil de usar a biblioteca http://svg.codeplex.com/ (versão mais recente @ GIT , @ NuGet ). Aqui está meu código

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
fonte
1
Tive que usar a versão github porque está mais atualizada e mesmo que não suporte o imageelemento.
fireydude
eu sou usado a partir deste código, ele lança object not set to an instance of an objectquando deseja executar var bitmap = svgDocument.Draw();. qual é o problema?
Rasool Ghafari
@RasoolGhafari certifique-se de que seu svgDocument não seja nulo.
Anish
svgDocument não é nulo. Este é algum tipo de problema interno na biblioteca.
Jonathan Allen
@JonathanAllen, estava respondendo ao comentário do Rasool.
Anish
12

Quando tive que rasterizar svgs no servidor, acabei usando P / Invoke para chamar funções librsvg (você pode obter as dlls de uma versão do Windows do programa de edição de imagem 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.
fonte
1
librSVG não é ruim, mas fontes / texto, ele não os manipula corretamente. Em vez disso, dê uma olhada na API headless-chrome, chrome-debugging e uma API C # para a API chrome-debugging: github.com/ststeiger/ChromeDevTools/blob/master/source/…
Stefan Steiger
8

Estou usando o Batik para isso. O código 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;
Stevenvh
fonte
@downvoters - Explique porque você votou negativamente. Um voto negativo sem explicação tem valor zero.
stevenvh
4
Eu acho que os votos negativos vêm do texto da pergunta que contém "c #" nele. e sua proposta é delphi
Denis
não downvote, mas você pode editar sua resposta e deixar claro que Batiké uma biblioteca Java que você pode chamar de C # ou qualquer linguagem (neste caso, você mostrou como chamá-la em Delphi)
ErrCode
Iniciar um novo processo é lento. Além disso, o quão corretamente o batik rasteriza? Os binários mais recentes são difíceis de obter. Em vez de tolerar essa porcaria, dê uma olhada em headless-chrome, chrome-debugging API e uma API C # para a API chrome-debugging: github.com/ststeiger/ChromeDevTools/blob/master/source/… - Para todos Usuários de Java, tenho certeza de que também há APIs de Java em torno da API de depuração do Chrome.
Stefan Steiger
4

Para adicionar à resposta de @Anish, se você estiver tendo problemas para não ver o texto ao exportar o SVG para uma imagem, você pode criar uma função recursiva para percorrer os filhos do SVGDocument, tentar lançá-lo em um SvgText se possível (adicione sua própria verificação de erros) e defina a família e o estilo da fonte.

    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
        {

        }
    }

Deixe-me saber se houver dúvidas.

Michal Kieloch
fonte
pai não está definido em SetFont, deve ser elemento ou renomear a variável do elemento para pai na assinatura da função
Norbert Kardos
Além disso, a fonte parece ser uma string agora. No entanto, este foi um salva-vidas, obrigado!
Norbert Kardos
-3

você pode usar altsoft xml2pdf lib para isso


fonte