如何在 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 文件的主要内容,如果未能解决你的问题,请参考以下文章
如何在ghostscript中将svg、eps和ai转换为png