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

Posted

技术标签:

【中文标题】如何在 C# 中将 SVG 文件转换为 EMF 文件【英文标题】:How to convert an SVG file to an EMF file in C# 【发布时间】:2014-11-26 22:03:29 【问题描述】:

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


更新:

我尝试使用 SVG.NET 读取 SVG 文件并将其绘制到 Graphics 对象,然后尝试将 Image 导出为 .emf 扩展名中的元文件(我按照此处的说明操作: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();

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,但搜索没有结果。 最后我在下面得到了我自己的简单解决方案。我用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);
    

首先我创建了一个临时文件。然后我使用Draw(Graphics) 方法将 emf 保存在其中。最后我从临时文件中读取字节。 不要尝试将MemoryStream 用于Metafile。不幸的是,它不起作用。

【讨论】:

已经过去一年了,终于 :) 我会尝试您的解决方案并尽快回复您 :) 知道如何做反向吗?从 .emf 到 .svg?【参考方案2】:

这是我发现目前最好的解决方案。这几乎就像接受的答案并使用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 之类的替代方案可能更适合您的情况。

【讨论】:

以上是关于如何在 C# 中将 SVG 文件转换为 EMF 文件的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Python 将 EMF 插入 Word

如何在ghostscript中将svg、eps和ai转换为png

emf格式需要装啥软件

如何通过api将文本文档(ODT或DOCX)中的表格导出为EMF格式

如何将emf文件转换成png格式

在 Inkscape 中将 SVG 批量转换为 PNG 不起作用