C#生成EMF矢量图形文件示例详解

目录
  • 前言
  • 原因
  • 实现
  • 绘制位置错误
  • 结论

前言

公众号上有网友询问我如何生成 EMF 文件的问题:

本以为非常简单,我快速给出了解决方案:

var bitmap = new Bitmap(640, 480);
var g = Graphics.FromImage(bitmap);
g.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 100, 100);
bitmap.Save("MyIO.emf",ImageFormat.Emf);

结果,网友告诉我,这是错误的:

用编辑器查看文件内容,发现实际生成的是PNG格式文件:

这是怎么回事呢?

原因

在官方文档上找到这样一段话:

当使用Save此方法将图形图像另存为Windows元文件格式 (WMF) 或增强的图元文件格式 (EMF) 文件时,生成的文件将改为保存为可移植网络图形 (PNG) 文件。发生此行为是因为.NET Framework的GDI+组件没有可用于将文件另存为 .wmf 或 .emf 文件的编码器。

不理解这样设计的原因,不支持应该抛出异常吧?!

实现

不过还好,从文档上我们也找到了解决方案,那就是使用Metafile类。

可是在实现时,又踩了不少坑。

创建实例失败

按照示例代码,使用文件名创建实例:

var metafile = new Metafile("MyIO.emf");

结果报了个通用异常,完全没有指导意义:

只好反编译代码查错。

发现,底层实现使用的GdipCreateMetafileFromFileAPI:

public Metafile(string filename)
{
 Path.GetFullPath(filename);
 SafeNativeMethods.Gdip.CheckStatus(SafeNativeMethods.Gdip.GdipCreateMetafileFromFile(filename, out IntPtr metafile));
 SetNativeImage(metafile);
}

也就是说,参数必须是一个已存在的 EMF 文件名。

查看其他构造函数的实现,发现传递referenceHdc的构造函数使用的是GdipRecordMetafileFileNameAPI:

public Metafile(string fileName, IntPtr referenceHdc, EmfType type, string? description)
{
 Path.GetFullPath(fileName);
 SafeNativeMethods.Gdip.CheckStatus(SafeNativeMethods.Gdip.GdipRecordMetafileFileName(fileName, referenceHdc, type, IntPtr.Zero, MetafileFrameUnit.GdiCompatible, description, out IntPtr metafile));
 SetNativeImage(metafile);
}

也就是说,这个 API 可以创建 EMF 文件。看来可以用。

而referenceHdc可以使用Graphics.GetHdc()得到。

于是,实现代码如下:

using (Graphics g1 = Graphics.FromHwnd(IntPtr.Zero))
{
    using (var metafile = new Metafile("MyIO.emf", g1.GetHdc()))
    {
        using (Graphics g2 = Graphics.FromImage(metafile))
        {
            g2.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 100, 100);
            g2.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 200, 200);
        }
    }
}

生成的确实是矢量图形文件:

绘制位置错误

可以明显看到,第一个My IO绘制的位置是错误的,绘制到了左上角,而不是(100, 100)。

再次查找构造函数,发现可以传递Rectangle参数:

修改实现代码如下:

using (Graphics g1 = Graphics.FromHwnd(IntPtr.Zero))
{
    using (var metafile = new Metafile("MyIO.emf", g1.GetHdc(), new Rectangle(0, 0, 300, 300), MetafileFrameUnit.Pixel))
    {
        using (Graphics g2 = Graphics.FromImage(metafile))
        {
            g2.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 100, 100);
            g2.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 200, 200);
        }
    }
}

这次总算成功了:

结论

后来发现,生成的图片实际是375 x 375像素,这应该是因为我的显示属性设置了缩放的原因(375 / 300 = 1.25):

以上就是C#生成EMF矢量图形文件示例详解的详细内容,更多关于C#生成EMF矢量图形文件的资料请关注我们其它相关文章!

(0)

相关推荐

  • c#生成自定义图片方法代码实例

    本篇文章给大家带来的内容是关于c# 如何生成自定义图片?c# 生成自定义图片方法,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. using System.Drawing;using System.IO;using System.Drawing.Imaging;using System;namespace treads { /// <summary> /// 生成略缩图 /// </summary> public class Class2 { private Ima

  • C#图片切割、图片压缩、缩略图生成代码汇总

    本文为大家整理了C#图片切割.图片压缩.缩略图生成的实现代码,大家可以收藏,方便以后使用,具体内容如下 /// 图片切割函数 /// </summary> /// <param name="sourceFile">原始图片文件</param> /// <param name="xNum">在X轴上的切割数量</param> /// <param name="yNum">在Y轴

  • C#生成饼形图及添加文字说明实例代码

    本文以实例形式说明了C#生成饼形图,圆饼图,并为图表添加文字注释的方法.可实现文字显示在图表周围,直观形象的展示各个数据分量的走抛情况的效果.通常在编写系统报表过程中,使用图表显示数据是很多人认可的方式.本文所述的就是一个用Visual C#生成圆饼型图表,并且在图表外围添加数据分量报表说明的一个例子. 具体功能代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using Syst

  • C#将PDF转为多种图像文件格式的方法(Png/Bmp/Emf/Tiff)

    PDF是一种在我们日常工作学习中最常用到的文档格式之一,但常常也会因为文档的不易编辑的特点,在遇到需要编辑PDF文档内容或者转换文件格式的情况时让人苦恼.通常对于开发者而言,可选择通过使用组件的方式来实现PDF文档的编辑或者格式转换,因此本文将介绍如何通过使用免费版的组件Free Spire.PDF for .NET来转换PDF文档.这里介绍将PDF转换多种不同格式的图像文件格式,如PNG,BMP,EMF,TIFF等,同时,转换文档也分为转换全部文档和转换部分文档为图片两种情况,本文也将作进一步

  • C#生成PDF的方法

    之前项目中是通过wkhtmltopdf渲染web页面生成的pdf文件,这个方案一直不是很稳定,并且在不同的场景样式也常不一样,老需要调整. 今天研究了一下C#直接生成PDF的方案,还是比较简单的,整体方案如下: 通过WPF库生成XPS文件 通过PdfSharp将XPS文件转成PDF文件 首先看一下生成xps文件的代码.,代码如下: var fixedDoc = new FixedDocument(); var pageContent = new PageContent(); var fixedP

  • C#生成EMF矢量图形文件示例详解

    目录 前言 原因 实现 绘制位置错误 结论 前言 公众号上有网友询问我如何生成 EMF 文件的问题: 本以为非常简单,我快速给出了解决方案: var bitmap = new Bitmap(640, 480); var g = Graphics.FromImage(bitmap); g.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 100, 100); bitmap.Save("

  • C++ OpenCV生成蒙太奇图像的示例详解

    目录 前言 一.输入模板图像 二.读取素材图像 三.生成蒙太奇模板 四.生成蒙太奇图像 五.源码 总结 前言 本文将使用OpenCV C++ 生成蒙太奇图像. 一.输入模板图像 原图如图所示.我们将对此图生成蒙太奇图像. Mat src = imread("Taylor.jpg"); if (src.empty()) { cout << "No image!" << endl; system("pause"); retur

  • 详解Python中生成随机数据的示例详解

    目录 随机性有多随机 加密安全性 PRNG random 模块 数组 numpy.random 相关数据的生成 random模块与NumPy对照表 CSPRNG 尽可能随机 os.urandom() secrets 最佳保存方式 UUID 工程随机性的比较 在日常工作编程中存在着各种随机事件,同样在编程中生成随机数字的时候也是一样,随机有多随机呢?在涉及信息安全的情况下,它是最重要的问题之一.每当在 Python 中生成随机数据.字符串或数字时,最好至少大致了解这些数据是如何生成的. 用于在 P

  • 对python 生成拼接xml报文的示例详解

    最近临时工作要生成xml报名,通过MQ接口发送.简单小程序. 自增长拼成xml报文 Test_001.py # encoding=utf-8 import time orderId = '' s1= "\n" # for ID in range(1,5): item1 = "<item>" + \ "<orderID>" + str(ID) + "</orderID>" + \ "

  • PHP基于phpqrcode类生成二维码的方法示例详解

    HP QR Code是一个PHP二维码生成类库,利用它可以轻松生成二维码,官网提供了下载和多个演示demo,查看地址: http://phpqrcode.sourceforge.net/ 下载官网提供的类库后,只需要使用phpqrcode.php就可以生成二维码了,当然您的PHP环境必须开启支持GD2. phpqrcode.php提供了一个关键的png()方法,其中 参数$text表示生成二位的的信息文本: 参数$outfile表示是否输出二维码图片 文件,默认否: 参数$level表示容错率,

  • C语言编程gcc如何生成静态库.a和动态库.so示例详解

    目录 一.什么是静态库和动态库 二.gcc生成.a静态库和.so动态库 1.生成静态库(.a) 1.1编辑生成例子程序hello.h.hello.c和main.c 1.2将hello.c编译成.o文件 1.3由.o文件创建静态库 1.4在程序中使用静态库 1.5验证静态库的特点 2.生成动态库(.so) 2.1由.o文件创建动态库文件 2.2在程序中使用动态库 三.实例 1.实例1 1.1代码 1.2 静态库.a文件的生成与使用 1.3 动态库.so文件的生成与使用 2.实例2 2.1代码 2.

  • C语言实现生成新春福字的示例详解

    目录 主要代码 字面量以及数据结构 定义一个回调函数,刷新福字 应用初始化程序 主程序 效果展示 快新年了,支付宝扫福活动又开始了,每次都要百度找福,这次不想找了,自己写一个程序生成各种字体的福字. 主要代码 字面量以及数据结构 #define FONT_DISPLAY "福" // g_fu_label中的每一个控件都是一个福字 static GtkWidget *g_fu_label[3][3]; // 记录所有的字体family typedef struct { int n_fa

  • 利用Python自动生成PPT的示例详解

    在日常工作中,PPT制作是常见的工作,如果制作创意类PPT,则无法通过自动化的形式生成,因为创意本身具有随机性,而自动化解决的是重复性工作,两者有所冲突. python-pptx是python处理PPT的一个库,注重的是读和写,无法导出,没有渲染功能. 废话不多说,第一步,安装python-pptx库: pip3 install -i https://pypi.doubanio.com/simple/ python-pptx ppt里面处理的主要对象一般为文本框,表格,图片. 每一页的ppt为一

  • Blender Python编程实现程序化建模生成超形示例详解

    目录 正文 什么是超形(Supershapes, Superformula) 二维超形 n1 = n2 = n3 = 1 n1 = n2 = n3 = 0.3 其他特别情况 例子 1 例子 2 例子 3 例子 4 例子 5 奇异的形状 三维超形 Blender 生成超形 详细代码和注释如下 正文 Blender 并不是唯一一款允许你为场景编程和自动化任务的3D软件; 随着每一个新版本的推出,Blender 正逐渐成为一个可靠的 CG 制作一体化解决方案,从使用油脂铅笔的故事板到基于节点的合成.

  • Go java 算法之括号生成示例详解

    目录 括号生成 方法一:深度优先遍历(java) 方法一:深度优先遍历(go) 括号生成 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合. 示例 1: 输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"] 示例 2: 输入:n = 1 输出:["()"] 提示: 1 <=

随机推荐