如何在C#中将SVG文件转换为EMF文件

时间:2014-10-01 22:52:05

标签: c# .net svg .emf

将SVG转换为EMF绝对是可能的,例如this website。我想知道是否有可能在C#中实现这种转换?


更新

我尝试使用SVG.NET读取SVG文件并将其绘制到Graphics对象,然后尝试将Image导出为.emf扩展名中的MetaFile(我按照此处的说明操作) :GDI+ / C#: How to save an image as EMF?)。读取成功完成,图像输出为.emf。但是,当我在PowerPoint中打开.emf时,它无法取消分组,这表明该文件的绘图信息实际上没有正确转储。

更新2:

现在它确实导出了一个无组合的.emf,但是取消组合显示效果非常糟糕。我使用以下代码生成.emf:

private void OpenPictureButtonClick(object sender, EventArgs e)
{
    var openFileDialog = new OpenFileDialog();
    openFileDialog.ShowDialog();

    _svgDoc = SvgDocument.Open(openFileDialog.FileName);

    RenderSvg(_svgDoc);
}

private void SavePictureClick(object sender, EventArgs e)
{
    var saveFileDialog = new SaveFileDialog {Filter = "Enhanced Meta File | *.Emf"};
    saveFileDialog.ShowDialog();

    var path = saveFileDialog.FileName;
    var graphics = CreateGraphics();
    var img = new Metafile(path, graphics.GetHdc());
    var ig = Graphics.FromImage(img);

    _svgDoc.Draw(ig);

    ig.Dispose(); img.Dispose(); graphics.ReleaseHdc(); graphics.Dispose();
}

private void RenderSvg(SvgDocument svgDoc)
{
    svgImageBox.Image = svgDoc.Draw();
}

2 个答案:

答案 0 :(得分:7)

I had the same issue but searching had no results.
Finally I ended up with my own simple solution below. I used SVG.NET.

public static byte[] ConvertToEmf(string svgImage)
{
    string emfTempPath = Path.GetTempFileName();
    try
    {
        var svg = SvgDocument.FromSvg<SvgDocument>(svgImage);
        using (Graphics bufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero))
        {
            using (var metafile = new Metafile(emfTempPath, bufferGraphics.GetHdc()))
            {
                using (Graphics graphics = Graphics.FromImage(metafile))
                {
                    svg.Draw(graphics);
                }
            }
        }

        return File.ReadAllBytes(emfTempPath);
    }
    finally
    {
        File.Delete(emfTempPath);
    }
}

At first I create a temp file. Then I use Draw(Graphics) method to save emf in it. And at last I read bytes from temp file.
Don't try to use MemoryStream for Metafile. Unfortunately, it's not working.

答案 1 :(得分:0)

这是我发现目前最好的解决方案。这几乎类似于已接受的答案并使用 SVG.NET,但能够在内存中执行此操作。

重要的变化是释放手柄和重置位置记忆流。

public static Stream ConvertSvgToEmf(string svgImage)
{
    using var writeStream = new MemoryStream();

    var svg = SvgDocument.FromSvg<SvgDocument>(svgImage);
    var stream = new MemoryStream();
    var sizedImage = new Bitmap((int)svg.Width.Value, (int)svg.Height.Value);
    using (var graphicsFromSizedImage = Graphics.FromImage(Image.FromHbitmap(sizedImage.GetHbitmap())))
    using (var metafile = new Metafile(stream, graphicsFromSizedImage.GetHdc(), EmfType.EmfPlusOnly)) // Specify EmfType for lesser file size
    using (var graphics = Graphics.FromImage(metafile))
    {
        svg.Draw(graphics);
        graphicsFromSizedImage.ReleaseHdc();
    }

    stream.Position = 0;

    return stream;
}

请注意,底层实现依赖于 System.Drawing,因此 gdi 必须是可访问的。在基于 linux 的操作系统(或 Docker 映像)上,必须安装 libgdiplus

由于 System.Drawing 被认为是 deprecated,因此 Magick.NET 之类的替代方案可能更适合您的情况。

相关问题