Преобразование SVG в PNG с помощью C # [закрыто]

103

Я пытался преобразовать изображения SVG в PNG с помощью C # без необходимости писать слишком много кода. Может ли кто-нибудь порекомендовать библиотеку или пример кода для этого?

Харриотт
источник
1
Я нашел хорошую и простую библиотеку, которую вы можете использовать в C # github.com/ElinamLLC/SharpVectors , она может конвертировать многие типы svg в bmp, jpeg или png
Махди
2
Могу я сказать: эти решения плохие, в том числе wkhtml2pdf / wkhtml2image и т. Д. Спецификация SVG сложна и развивается, как и стили CSS, и, кроме того, они должны выглядеть так же, как в браузере. wkhtml2X, например, имеет огромные проблемы со шрифтами, а движок webkit внутри слишком стар. К счастью, есть решение: в Chrome есть безголовый режим, а с его Debugging-API вы можете получать PNG-изображения и PDF-файлы из самого Headless-Chrome с помощью MasterDevs / ChromeDevTools на C #: Пример: github.com/ststeiger/ChromeDevTools / blob / master / source /…
Стефан Штайгер

Ответы:

69

Для этого вы можете вызвать версию inkscape для командной строки:

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

Также существует механизм рендеринга SVG C #, который в первую очередь предназначен для использования файлов SVG в Интернете в кодовом комплексе, который может удовлетворить ваши потребности, если это ваша проблема:

Исходный проект
http://www.codeplex.com/svg

Форк с исправлениями и дополнительной активностью: (добавлено 07/2013)
https://github.com/vvvv/SVG

Espo
источник
39
Спасибо, Эспо. Я действительно написал это сообщение в блоге inkscape! Хотя это "работает", это не особо надежное решение. Хотя мне нравится проект codeplex - я его посмотрю. Спасибо.
harriyott,
9
Как обидно :) Хорошо, что движок рендеринга SVG может вам помочь.
Espo,
20
Я воспринимаю это как комплимент. Я не цитировал себя раньше!
harriyott,
Вы пробовали движок рендеринга svg? Вы можете поделиться своим решением, пожалуйста. Я пытаюсь заставить его работать, но у меня проблемы, см. здесь
Armance
1
Я пробовал github.com/vvvv/SVG, и он работает, но с некоторыми ограничениями. imageЭлемент не был реализован - я проверил исходный код. @FrankHale Мне пришлось удалить xmlns из svg, потому что Рафаэль добавил его дважды.
fireydude
75

Есть гораздо более простой способ использовать библиотеку http://svg.codeplex.com/ (более новая версия @ GIT , @ NuGet ). Вот мой код

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
Мне пришлось использовать версию на github, потому что она более актуальна и даже не поддерживает imageэлемент.
fireydude
Я использую этот код, он выдает, object not set to an instance of an objectкогда хочу выполнить var bitmap = svgDocument.Draw();. в чем проблема?
Расул Гафари
@RasoolGhafari убедитесь, что ваш svgDocument не нулевой.
Аниш
svgDocument не равен нулю. Это какая-то внутренняя проблема в библиотеке.
Джонатан Аллен
@JonathanAllen, я отвечал на комментарий Расула.
Аниш
12

Когда мне пришлось растрировать svgs на сервере, я в конечном итоге использовал P / Invoke для вызова функций librsvg (вы можете получить библиотеки DLL из версии программы редактирования изображений GIMP для Windows).

[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.
источник
1
librSVG неплох, но шрифты / текст не обрабатывает их правильно. Вместо этого взгляните на headless-chrome, chrome-debugging API и C # API для chrome-debugging API: github.com/ststeiger/ChromeDevTools/blob/master/source/…
Stefan Steiger
8

Я использую для этого батик . Полный код 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;
Стивенвх
источник
@downvoters - Объясните, почему вы проголосовали против. Голос против без объяснения причин имеет нулевую ценность.
stevenvh
4
Я предполагаю, что отрицательные голоса исходят из текста вопроса, который содержит в нем «c #». и ваше предложение - delphi
Денис
не голосовал против, но вы можете отредактировать свой ответ и пояснить, что Batikэто библиотека Java, которую вы можете вызывать из C # или любого
другого
Запуск нового процесса идет медленно. И как правильно растрировать батик? Последние бинарные файлы получить сложно. Вместо того, чтобы мириться с этой чушью, взгляните на headless-chrome, chrome-debugging API и C # API для chrome-debugging API: github.com/ststeiger/ChromeDevTools/blob/master/source/… - Для всех Пользователи Java, я уверен, что есть также Java-API вокруг API отладки Chrome.
Стефан Штайгер
4

Чтобы добавить к ответу от @Anish, если у вас возникают проблемы с отсутствием текста при экспорте SVG в изображение, вы можете создать рекурсивную функцию для циклического перебора дочерних элементов SVGDocument, попробуйте преобразовать ее в SvgText, если возможно (добавьте свою собственную проверку ошибок) и установите семейство шрифтов и стиль.

    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
        {

        }
    }

Сообщите мне, если возникнут вопросы.

Михал Килох
источник
parent не определен в SetFont, должен быть element или переименовать переменную element в parent в сигнатуре функции
Норберт Кардос
Также шрифт теперь кажется строкой. Однако это была палочка-выручалочка, спасибо!
Норберт Кардос
-3

вы можете использовать altsoft xml2pdf lib для этого


источник