การแปลง SVG เป็น PNG โดยใช้ C # [ปิด]


104

ฉันพยายามแปลงภาพ SVG เป็น PNG โดยใช้ C # โดยไม่ต้องเขียนโค้ดมากเกินไป ใครช่วยแนะนำไลบรารีหรือโค้ดตัวอย่างสำหรับการทำสิ่งนี้ได้บ้าง


1
ฉันพบไลบรารีที่ดีและเรียบง่ายที่คุณสามารถใช้ใน c # github.com/ElinamLLC/SharpVectorsมันสามารถแปลง svg หลายประเภทเป็น bmp, jpeg หรือ png
Mahdi

2
ฉันขอบอกว่าโซลูชันเหล่านั้นไม่ดีรวมถึง wkhtml2pdf / wkhtml2image เป็นต้นข้อกำหนด SVG มีความซับซ้อนและมีการพัฒนารูปแบบ CSS ก็เช่นกันและยิ่งไปกว่านั้นควรมีลักษณะเช่นเดียวกับในเบราว์เซอร์ ตัวอย่างเช่น wkhtml2X มีปัญหาใหญ่เกี่ยวกับแบบอักษรและโปรแกรม webkit ภายในเก่าเกินไป โชคดีที่มีวิธีแก้ไข: Chrome มีโหมด headless และด้วย Debugging-API คุณจะได้รับ PNG-images และ PDF จาก Headless-Chrome ด้วย MasterDevs / ChromeDevTools ใน C #: ตัวอย่าง: github.com/ststeiger/ChromeDevTools / blob / master / source / …
Stefan Steiger

คำตอบ:


69

คุณสามารถเรียกใช้ inkscape เวอร์ชันบรรทัดคำสั่งเพื่อทำสิ่งนี้:

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

นอกจากนี้ยังมีเอ็นจิ้นการเรนเดอร์ C # SVG ซึ่งออกแบบมาเพื่ออนุญาตให้ใช้ไฟล์ SVG บนเว็บบน codeplex ซึ่งอาจเหมาะกับความต้องการของคุณหากนั่นคือปัญหา

โครงการเดิม
http://www.codeplex.com/svg

ส้อมพร้อมการแก้ไขและกิจกรรมอื่น ๆ : (เพิ่ม 7/2013)
https://github.com/vvvv/SVG


39
ขอบคุณ Espo ฉันเขียนบล็อกโพสต์ของ inkscape จริงๆ! แม้ว่าจะ "ใช้ได้ผล" แต่ก็ไม่ใช่วิธีแก้ปัญหาที่มีประสิทธิภาพเป็นพิเศษ ฉันชอบโครงการ codeplex - ฉันจะให้ดู ขอบคุณ.
harriyott

9
น่าอายแค่ไหน :) สิ่งที่ดีบางทีเอ็นจิ้นการเรนเดอร์ SVG อาจช่วยคุณได้
Espo

21
ฉันถือเป็นคำชม ฉันไม่เคยถูกยกมาก่อน!
harriyott

คุณได้ลองใช้เอ็นจิ้นการเรนเดอร์ svg หรือยัง คุณสามารถแบ่งปันวิธีแก้ปัญหาของคุณได้ไหมกรุณา ฉันพยายามทำให้มันใช้งานได้ แต่มีปัญหาโปรดดูที่นี่
Armance

1
ฉันได้ลองgithub.com/vvvv/SVGแล้วและใช้งานได้ แต่มีข้อ จำกัด บางประการ imageองค์ประกอบยังไม่ได้รับการดำเนินการ - ฉันจะตรวจสอบรหัสที่มา @ FrankHale ฉันต้องลบ xmlns ออกจาก svg เพราะ raphael เพิ่มสองครั้ง
fireydude

76

มีวิธีที่ง่ายกว่ามากในการใช้ไลบรารี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();มีปัญหาอะไร?
Rasool Ghafari

@RasoolGhafari ตรวจสอบให้แน่ใจว่า svgDocument ของคุณไม่เป็นโมฆะ
Anish

svgDocument ไม่เป็นโมฆะ นี่เป็นปัญหาภายในห้องสมุด
Jonathan Allen

@JonathanAllen ฉันกำลังตอบความคิดเห็นของ Rasool
Anish

12

เมื่อฉันต้องแรสเตอร์ขนาด svgs บนเซิร์ฟเวอร์ฉันลงเอยด้วยการใช้ P / Invoke เพื่อเรียกใช้ฟังก์ชัน librsvg (คุณสามารถรับ dlls จากโปรแกรมแก้ไขภาพ 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());
    }
}

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 #" อยู่ในนั้น และข้อเสนอของคุณคือเดลฟี
เดนิส

ไม่ได้ลงคะแนน แต่คุณสามารถแก้ไขคำตอบของคุณและทำให้ชัดเจนว่าBatikเป็นไลบรารี Java ที่คุณสามารถเรียกใช้จาก C # หรือภาษาอะไรก็ได้ (ในกรณีนี้คุณแสดงวิธีเรียกมันใน Delphi)
ErrCode

การเริ่มกระบวนการใหม่ทำได้ช้า นอกจากนี้ผ้าบาติกแรสเตอร์ถูกต้องอย่างไร? ไบนารีล่าสุดหายาก แทนที่จะทนกับเรื่องไร้สาระให้ดูที่ headless-chrome, chrome-debugging API และ C # API สำหรับ chrome-debugging API: github.com/ststeiger/ChromeDevTools/blob/master/source/… - สำหรับทุกคน ผู้ใช้ Java ฉันแน่ใจว่ามี Java-API ที่อยู่รอบ ๆ debugging-API ของ Chrome ด้วย
Stefan Steiger

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 ควรเป็นองค์ประกอบหรือเปลี่ยนชื่อตัวแปรองค์ประกอบเป็นพาเรนต์ที่ลายเซ็นของฟังก์ชัน
Norbert Kardos

นอกจากนี้ Font ก็ดูเหมือนจะเป็นสตริงแล้ว อย่างไรก็ตามนี่เป็นการช่วยชีวิตขอบคุณ!
Norbert Kardos

-4

คุณสามารถใช้ altsoft xml2pdf lib สำหรับสิ่งนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.