📄 01_9_13_25.asp.html
字号:
</td></tr></table><table width=100% ><tr><td class=a14>
VC访问WMF文件</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
Windows API提供了访问WMF文件的函数,Visual C++的CDC类又封装了这些函数:</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
标准WMF文件(非活动式图元文件)可以用PloyMetafile播放。但是这个函数不支持活动式图元文件,对于活动式图元文件,必须先取出metafileheader中的信息,然后取出后面的记录信息,形成一个非活动式图元文件的样子,才能播放。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
前文指出,WMF文件有自己的逻辑坐标系,当播放活动式图元文件时,必须 使用metafileheader中的信息“矫正”到应用程序的逻辑坐标系。主要的信息由rect bbox成员提供。一般用如下格式:</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
SetWindowOrg(bbox.left,bbox.top);</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
SetWindowExt(abs(bbox.left)+ abs(bbox.right), abs(bbox.top) abs(bbox.bottom));</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
重要的是,一般WMF文件都是用MM_ANISOTROPIC 的映射模式。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
问题的难点</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
在视频行业(如字幕机)上的图片具有层次感,所以tga文件有一个描述色彩透明度的属性值a(一个字节),a=0x00时完全透明,显现底色;a=0xff时完全不透明。如果想把wmf文件的图像导入tga文件,关键有2点:</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
1.因为wmf文件是“播放”到DC上的,所以必须转换成矢量图,因为DC对于我们没有意义。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
2.必须分清那些像素点是实体,那些是背景,将背景部分置成透明,将实体部分的a值按照需要置成0x00~0xff之间的值。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
第一点比较容易实现,因为Windows API提供了PloyMetafile和EmnuMetafile函数,可以先在DC上画图,在将其转成bmp格式。但是第二点似乎很困难,不能试图指定某一个颜色是背景色,从而将这种颜色的点子的a值设成0。因为如果实体的某一部分也具有此种颜色,则形成“透光”图案。比如,白色为背景,画中人系了一条白围巾,如果统一指定白色为透明色,图片叠加之后,则此人的脖子部分就没了。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
一种看起来比较繁琐,但是肯定可以实现的方法是想办法仿真所有wmf文件支持的GDI函数,将播放过程对具体像素的操作模拟到目标图片上。也就是说,重新编写这些函数的源码。比如,如果有一个记录使用lineto函数,则首先计算该线上像素点子,然后按照当前的画笔的颜色将这些点子“染色”。 wmf文件一共支持72个GDI函数,这种方案的工作量相对于本任务来说是巨大的。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
一种简单的实现方法</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
利用Visual C++提供的强大的CDC类及其“区域”操作函数,本文提出了一种简便实用的方法。区域(Region)在CDC类中是一个重要的对象,区域可以合并、翻转,可以实现复杂的图形。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
观察wmf文件支持的GDI函数,除了少量的“实际”画图函数外,大部分是画笔画刷对象和一些设置函数。画图函数仅有LineTo,Arc, Chord, Ellipse, Pie, Rectangle, RoundRect, PolyPolygon,Polygon, Polyline这9个函数,绝大部分操作是由Polygon完成的。同时,CDC类提供了与完成同样图形绘制功能的“区域”绘制函数:CreateEllipticRgn, CreateRectRgn,Create RoundRectRgn,CreatePolygonRgn, CreatePolyPolygonRgn, 并提供了功能灵活的区域合并函数CombineRgn。所以可以用区域的集合体来表示实体。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
解决本文问题的“两步法”思路很简单:第一步,截取wmf文件记录的GDI函数,然后利用同功能“区域”绘制函数仿真它,例如CreateEllipticRgn仿真Ellipse,CreatePolygonRgn仿真Polygon,形成一个个的小区域代替实体的各个部分,最后组合成整个实体。第二步,为了区分背景和实体,使用了PtsInRegion函数,如果像素点子在实体区域内,则该点的a值为0xff,反之为0x00。实际上,这样形成的区域实体只是实体的“轮廓”,而不涉及每一个部分的填充颜色,所使用的样式,所使用的坐标系,以及其他的难以仿真的设置。因为这些都由CDC作了,只需使用GetPixel函数得到每个像素点的颜色值,再加上如前方法得到的透明度,就构成了tga文件的数据主体,于是可以导入tga文件中,本文利用这种方法将MS Office自带的近千个图元文件导入tga文件中。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
区域函数和一般GDI函数并不一一对应,LineTo,Arc, Chord, Ellipse, Pie,Polyline就没有对应函数,所以还要作以下处理, 形成这些形状的区域函数:</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
画线LineTo:看作高度为0的多边形,使用CreatePolyRgn函数仿真。 </td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
画弦形Chord :看作椭圆区域(E)和一多边形区域(P)的合并操作,先取交集(E.AND.P),再从椭圆中抠除这个交集。即Chord=(E.AND.P).DIFF. E,如图1所示。 </td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table>
<table width=100% >
<tr>
<td class=a14> 画弧Arc:先创建一个椭圆区域(E1),再创建一个椭圆区域(E2),E2比E1的半径减少一个当前画笔宽度。对E2和E1进行异或(XOR),得到圆的边。然后使用类似于画弦形的方法得到弧。
</td>
</tr>
<tr>
<td class=a14>
<div align="center"><img src="01_9_13_25a.gif" width="562" height="143"></div>
</td>
</tr>
</table>
<table width=100% ><tr>
<td class=a14>
<div align="center">图1 图2</div>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
饼图Pie:先创建弦形(C),然后创建一个三角形(T),圆心角为锐角则进行或(OR)操作,圆心角为钝角则进行除(DIFF)操作,如图3所示。 </td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
折线Polyline:多个LineTo的集合体。 </td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
结论</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
Wmf文件通过“播放”GDI记录的方式绘制图形。但是不包括透明度属性,使得向tga文件导入这些图片资源比较困难。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
本文提出先将wmf文件播放到DC,然后使用区域函数描绘wmf文件中实体的轮廓,为图片数据添加透明度,从而方便导入tga文件的两步方法,比仿真函数法更加简便使用。</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
</td></tr></table><table width=100% ><tr><td class=a14>
本文通过区域组合函数,为Windows没有提供对应的区域函数的5个GDI函数提出了解决方法。</td></tr></table>
<table width=100% ><tr><td class=a14>
</td></tr>
</table><br>
<style>.a1{font-size:1}</style>
<table width=100% ><tr><td align=right>(网页编辑:<a href='mailto:liu_yang@ccw.com.cn'>风之翼</a>)</td></tr></table>
</td><td class=a1 bgcolor=#f46240> </td>
<td valign=top width=138 align=right><table width=98% ><tr><td>
<form action='/app/gsearch1.asp' name=pdn><table width=100% ><tr><td>应用与方案
频道全文检索</td></tr>
<tr><td><input type="text" name="textfile" size=15 value=频道内检索 onfocus="this.value=''">
<input border=0 src="../../../../../images/jian.gif" name="I1" type="image" align=absmiddle>
</td></tr>
</table>
</form>
<form name=srch action="/search/which.asp" method=post onsubmit="JavaScript:return chk()">
<table width=100% >
<tr><td><select size="1" name="func">
<option selected value="2">主题检索</option>
<option value="1">周报全文检索</option>
<option value="3">模糊词检索</option>
</select></td></tr>
<tr><td><input type="text" name="SrchStr" size=15 value="输入待检索的词"
onfocus="this.value=''">
<input src="../../../../../images/jian.gif" name="I1" type="image" align="absMiddle" border=0>
</td></tr>
</table>
<script language="JavaScript">
function chk()
{if (!document.srch.SrchStr.value){
alert("请输入需检索的词!");
document.srch.SrchStr.focus();
return false;
}
else{if (document.srch.SrchStr.value.length>30){
alert("检索的词请不要超过30个字符!");
document.srch.SrchStr.focus();
return false;
}
}
}
</script></form>
<table width=100% ><tr><td class=f colspan=2><b>相关文章</b></td></tr>
<tr><td valign=top><IMG SRC=../../../../../img2/jiao.gif></td><td><a href='01_9_13_24.asp.html'>利用OpenGL实现三维绘图</a></td></tr>
<tr><td valign=top><IMG SRC=../../../../../img2/jiao.gif></td><td><a href='01_9_13_23.asp.html'>关于VC多文档应用中OpenGL的使用</a></td></tr>
<tr><td valign=top><IMG SRC=../../../../../img2/jiao.gif></td><td><a href='01_9_13_22.asp.html'>VC 6.0下自制媒体播放器</a></td></tr>
<tr><td valign=top><IMG SRC=../../../../../img2/jiao.gif></td><td><a href='01_9_13_21.asp.html'>用DirectDraw编写动画程序</a></td></tr>
<tr><td valign=top><IMG SRC=../../../../../img2/jiao.gif></td><td><a href='01_9_13_20.asp.html'>在对话框中动态显示位图</a></td></tr>
</table>
</td></tr></table></td></tr></table><br>
<table align=center width=680><tr><td align=right>
<form name=mail method=post action='/pub/subMail.asp' onsubmit='JavaScript: return chkField(this)'>
<INPUT type='hidden' name='rec' value='24121'>
您的姓名:<INPUT type="text" name=myName size=10>
您朋友的E-mail:<INPUT type="text" name=friendMail size=10>
<INPUT type="submit" value="推荐给好友">
</form>
</td></tr>
<tr><td align=right>
<b>[<a href="javascript:window.close()">关闭窗口</a>]</b>
</td></tr>
</table>
<script language="javascript">
function chkField(fmObj)
{if (!fmObj.friendMail.value){
alert("请输入您朋友的E-mail!");
fmObj.friendMail.focus();
return false;
}
return true;
}
</script>
<table align=center width=680>
<tr><td><hr size=1 width=660 color=#f46240></td></tr>
</table><br>
<p align=center>Copyright(C) ccw.com.cn,All rights reserved</p>
<p align=center><b>中国计算机世界出版服务公司版权所有</b></p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -