长沙物流职院:转换WMF工具

来源:百度文库 编辑:神马品牌网 时间:2024/04/25 16:42:01

一种将WMF文件转换为TGA文件的简便方法
文章发表:kehui 发表日期:2002-01-21 阅读次数:222
(北京昌平石油大学智能工程研究室 102249)

摘要:windows图元文件(*.WMF)提供了大量的、丰富多彩的剪贴画,它的文件格式与一般的图像文件不同,它只是记录绘制图画的GDI函数,显示图画的过程就是执行这些函数的过程,由于占用空间小、设备无关,所以适合那些反复播放的场合。TGA文件格式是目前广泛使用的视频文件格式,将丰富的剪贴画资源应用于TGA文件,作视频字幕播出是一个很有意义的工作,但是WMF 文件和TGA文件格式不同,尤其是WMF 文件以(r,g,b)表示图像颜色,TGA文件中以(r,g,b,a)表示图像颜色, a表示图像的透明度。所以如何给WMF文件数据加上a属性是一个难题。一种解决方法是试图全部仿真WMF文件中的GDI函数,但是成本太高,本文利用Virtual C++提供的强大的CDC类“区域”操作函数,成功地区分开WMF文件中的图像和背景,提出将WMF图像资源引入到TGA文件中的“两步法”。本文还为Windows没有提供对应的区域函数的5个GDI函数提出了形成区域函数的解决方法

关键词:WMF文件 图像处理 文件格式 区域函数

引言

如果使用过微软的MS Office软件,一定会对微软提供的成千的、丰富多彩的剪贴画文件深感惊奇。微软称这种文件为Windows metafile,由于比bitmap文件占用空间更小、更设备无关,所以适合那些在应用程序中反复播放的场合。为了产生一个WMF文件,首先创建一个特殊的设备上下文(DC),然后将绘制图像的GDI (graphics device interface)函数发送到DC中存起来。在显示这个文件时,应用程序将该文件在分成一条一条的GDI函数记录,一步一步地“回放”这些记录,从而形成图像。Windows图元文件分为两种,一种为标准格式,即通常的WMF文件,另一种称为Windows增强图元文件(emf文件),后者支持更多的GDI函数,但是不常见。

TGA文件格式是Truevision公司在1984年定义的视频文件格式,目前广泛应用于视频行业,TGA文件格式很复杂,本文不论述。常见的图像文件一般用RGB三原色表示像素,因为TGA文件要处理图像的叠合,为了保持层次感,增加了一个a属性,表示图像的透明程度。TGA文件适合于作丰富多彩的字幕制作、电视节目包装系统。

如果能把丰富的剪贴画资源应用于TGA文件,作视频字幕播出是一个很有意义的工作,但是WMF 文件和TGA文件格式不同,尤其是WMF 文件没有表示图像透明度的a属性,所以如何给WMF文件数据加上a属性是一个难题。

WMF文件类型及其格式

一个windows metafile包括两个部分,第一部分是文件头信息,使用一个metaheader结构保存;

struct {

word mttype;表示图元文件是存在内存里还是磁盘上

word mtheadersize; 表示图元文件头大小

word mtversion;使用的windows版本号

dword mtsize; 图元文件大小

word mtnoobjects;同时存在于文件中的最大对象数目

dword mtmaxrecord;最大尺寸的GDI记录

word mtnoparameters;保留域

} metaheader;

第二部分是GDI函数记录表,使用一个metarecord结构保存。

struct {

dword rdsize;记录大小

word rdfunction;该记录的GDI函数名

word rdparm[];该GDI函数的参数

} metarecord;

实际上,还有一种图元文件类型,称为活动式图元文件(placeable windows metafile ),它虽然属于标准图元文件,但是它同时包含了该图像的原始大小及缩放有关的信息,允许应用程序以指定的尺寸自由地显示该图像,这些信息存在了一个称为metafileheader 的结构中,这个结构在文件的第一部分,后面才是前文所述的两个结构。

struct {

dword key; 该值一定为0x9ac6cdd7l,表示这是一个活动式图元文件

handle hmf;未用,置0

rect bbox; 该图像的原始大小

word inch;1英寸于图元文件逻辑单位之比

dword reserved; 保留域

word checksum;文件头检验和

} metafileheader;

需要指出的是,微软的MS Office软件自带的图元文件,绝大部分是这种活动式图元文件,所以一定要按照这种格式访问,才可以正确使用。

VC访问WMF文件

Windows API提供了访问WMF文件的函数,Visual C++的CDC类又封装了这些函数:

标准WMF文件(非活动式图元文件)可以用PloyMetafile播放。但是这个函数不支持活动式图元文件,对于活动式图元文件,必须先取出metafileheader中的信息,然后取出后面的记录信息,形成一个非活动式图元文件的样子,才能播放。

前文指出,WMF文件有自己的逻辑坐标系,当播放活动式图元文件时,必须 使用metafileheader中的信息“矫正”到应用程序的逻辑坐标系。主要的信息由rect bbox成员提供。一般用如下格式:

SetWindowOrg(bbox.left,bbox.top);

SetWindowExt(abs(bbox.left)+ abs(bbox.right), abs(bbox.top) abs(bbox.bottom));

重要的是,一般WMF文件都是用MM_ANISOTROPIC 的映射模式。

问题的难点

在视频行业(如字幕机)上的图片具有层次感,所以tga文件有一个描述色彩透明度的属性值a(一个字节),a=0x00时完全透明,显现底色;a=0xff时完全不透明。如果想把wmf文件的图像导入tga文件,关键有2点:

1.因为wmf文件是“播放”到DC上的,所以必须转换成矢量图,因为DC对于我们没有意义。

2.必须分清那些像素点是实体,那些是背景,将背景部分置成透明,将实体部分的a值按照需要置成0x00~0xff之间的值。

第一点比较容易实现,因为Windows API提供了PloyMetafile和EmnuMetafile函数,可以先在DC上画图,在将其转成bmp格式。但是第二点似乎很困难,不能试图指定某一个颜色是背景色,从而将这种颜色的点子的a值设成0。因为如果实体的某一部分也具有此种颜色,则形成“透光”图案。比如,白色为背景,画中人系了一条白围巾,如果统一指定白色为透明色,图片叠加之后,则此人的脖子部分就没了。

一种看起来比较繁琐,但是肯定可以实现的方法是想办法仿真所有wmf文件支持的GDI函数,将播放过程对具体像素的操作模拟到目标图片上。也就是说,重新编写这些函数的源码。比如,如果有一个记录使用lineto函数,则首先计算该线上像素点子,然后按照当前的画笔的颜色将这些点子“染色”。 wmf文件一共支持72个GDI函数,这种方案的工作量相对于本任务来说是巨大的。

一种简单的实现方法

利用Visual C++提供的强大的CDC类及其“区域”操作函数,本文提出了一种简便实用的方法。区域(Region)在CDC类中是一个重要的对象,区域可以合并、翻转,可以实现复杂的图形。

观察wmf文件支持的GDI函数,除了少量的“实际”画图函数外,大部分是画笔画刷对象和一些设置函数。画图函数仅有LineTo,Arc, Chord, Ellipse, Pie, Rectangle, RoundRect, PolyPolygon,Polygon, Polyline这9个函数,绝大部分操作是由Polygon完成的。同时,CDC类提供了与完成同样图形绘制功能的“区域”绘制函数:CreateEllipticRgn, CreateRectRgn,Create RoundRectRgn,CreatePolygonRgn, CreatePolyPolygonRgn, 并提供了功能灵活的区域合并函数CombineRgn。所以可以用区域的集合体来表示实体。

解决本文问题的“两步法”思路很简单:第一步,截取wmf文件记录的GDI函数,然后利用同功能“区域”绘制函数仿真它,例如CreateEllipticRgn仿真Ellipse,CreatePolygonRgn仿真Polygon,形成一个个的小区域代替实体的各个部分,最后组合成整个实体。第二步,为了区分背景和实体,使用了PtsInRegion函数,如果像素点子在实体区域内,则该点的a值为0xff,反之为0x00。实际上,这样形成的区域实体只是实体的“轮廓”,而不涉及每一个部分的填充颜色,所使用的样式,所使用的坐标系,以及其他的难以仿真的设置。因为这些都由CDC作了,只需使用GetPixel函数得到每个像素点的颜色值,再加上如前方法得到的透明度,就构成了tga文件的数据主体,于是可以导入tga文件中,本文利用这种方法将MS Office自带的近千个图元文件导入tga文件中。

区域函数和一般GDI函数并不一一对应,LineTo,Arc, Chord, Ellipse, Pie,Polyline就没有对应函数,所以还要作以下处理, 形成这些形状的区域函数:

画线LineTo:看作高度为0的多边形,使用CreatePolyRgn函数仿真。

画弦形Chord :看作椭圆区域(E)和一多边形区域(P)的合并操作,先取交集(E.AND.P),再从椭圆中抠除这个交集。即Chord=(E.AND.P).DIFF. E,如图1所示。

画弧Arc:先创建一个椭圆区域(E1),再创建一个椭圆区域(E2),E2比E1的半径减少一个当前画笔宽度。对E2和E1进行异或(XOR),得到圆的边。然后使用类似于画弦形的方法得到弧。

<br>图1 图2

饼图Pie:先创建弦形(C),然后创建一个三角形(T),圆心角为锐角则进行或(OR)操作,圆心角为钝角则进行除(DIFF)操作,如图3所示。

折线Polyline:多个LineTo的集合体。

结论

Wmf文件通过“播放”GDI记录的方式绘制图形。但是不包括透明度属性,使得向tga文件导入这些图片资源比较困难。

本文提出先将wmf文件播放到DC,然后使用区域函数描绘wmf文件中实体的轮廓,为图片数据添加透明度,从而方便导入tga文件的两步方法,比仿真函数法更加简便使用。

本文通过区域组合函数,为Windows没有提供对应的区域函数的5个GDI函数提出了解决方法。