`
陈砚羲君
  • 浏览: 1835 次
  • 性别: Icon_minigender_1
  • 来自: 天津
最近访客 更多访客>>
社区版块
存档分类
最新评论

java解析WMF文件

    博客分类:
  • java
阅读更多
2012-03-11

        最近实习单位布置了一个任务,就是要用java解析微软图元文件wmf图像文件的参数信息,懵懵懂懂做了一个礼拜,任务基本上完成了,在此过程中有很多误区,故在此跟大家分享一下自己的感受,希望能给有同样需求的IT人员一点点灵感,不至于陷入到程序中去。

   首先简单介绍一下关于微软的wmf文件:微软的wmf文件分为两种一种是标准的图元文件,一种是活动式图元文件,活动式图元文件与标准的图元文件的主要区别是,活动式图元文件包含了图像的原始大小和缩放信息,本文主要介绍活动式图元文件,关于两种文件的具体定义可在百度百科中找到,本文主要讲解用程序如何解析活动式图元文件的坐标信息和颜色信息。

  以下是活动式图元文件的文件结构信息:

WMF 文件格式:
文件缩放信息:0x16字节
typedef struct _PlaceableMetaHeader
{
  DWORD Key;           /* 固定大小以相反顺序出现 9AC6CDD7h */
  WORD  Handle;        /* Metafile HANDLE number (always 0) */
  SHORT Left;          /* Left coordinate in metafile units */
  SHORT Top;           /* Top coordinate in metafile units */
  SHORT Right;         /* Right coordinate in metafile units */
  SHORT Bottom;        /* Bottom coordinate in metafile units */
  WORD  Inch;          /* Number of metafile units per inch */
  DWORD Reserved;      /* Reserved (always 0) */
  WORD  Checksum;      /* Checksum value for previous 10 WORDs */
} PLACEABLEMETAHEADER;

紧接文件缩放信息的是 WMFHEAD, 0x12字节
typedef struct _WindowsMetaHeader
{
  WORD  FileType;       /* Type of metafile (0=memory, 1=disk) */
  WORD  HeaderSize;     /* Size of header in WORDS (always 9) */
  WORD  Version;        /* Version of Microsoft Windows used */
  DWORD FileSize;       /* Total size of the metafile in WORDs */
  WORD  NumOfObjects;   /* Number of objects in the file */
  DWORD MaxRecordSize;  /* The size of largest record in WORDs */
  WORD  NumOfParams;    /* Not Used (always 0) */
} WMFHEAD;

紧接WMFHEAD的是WMFRECORD
typedef struct _StandardMetaRecord
{
    DWORD Size;          /* Total size of the record in WORDs */
    WORD  Function;      /* Function number (defined in WINDOWS.H) */
    WORD  Parameters[];  /* Parameter values passed to function */
} WMFRECORD;

每一个record中储存的是Windows GDI绘图函数的代码及每个函数对应的参数.这样的
话整个wmf文件就由这样的函数编码与参数组成。就像下面这样:
Record Name        Function Number
AbortDoc        0x0052
Arc        0x0817
Chord        0x0830
DeleteObject        0x01f0
Ellipse        0x0418

以上是wmf文件的结构信息,下面以一个例子说明:



字节图

以上前20个字节记录了文件的原始大小与一些规定的信息,

typedef struct _PlaceableMetaHeader
{
  DWORD Key;           /* Magic number (always 9AC6CDD7h) */
  WORD  Handle;        /* Metafile HANDLE number (always 0) */
  SHORT Left;          /* Left coordinate in metafile units */
  SHORT Top;           /* Top coordinate in metafile units */
  SHORT Right;         /* Right coordinate in metafile units */
  SHORT Bottom;        /* Bottom coordinate in metafile units */
  WORD  Inch;          /* Number of metafile units per inch */
  DWORD Reserved;      /* Reserved (always 0) */
  WORD  Checksum;      /* Checksum value for previous 10 WORDs */
} PLACEABLEMETAHEADER;

根据上面wmf文件的格式可知为:

d7 cd c6 9a(这是规定的信息)

00 00(这是保留信息) 

91 00 bf f3 c8 02 a7 f5(这是图元文件的最左端与最右端坐标信息)

20 01(记录了每英寸的逻辑单位数)

00 00 00 00 (保留字段)

70 52(文件校验位) ,校验代码如下:

/**
  * 判断此文件是否为活动式wmf文件
  *
  * @param path
  * @throws IOException
  */
private byte[] opinionHead(String path) throws IOException {
  FileInputStream fs = new FileInputStream(path);
  // 对头22个字节进行判断
  byte bf[] = new byte[22];
  fs.close();// 关闭文件流
  System.out.println((bf[0] & 0xff) + "\t" + (bf[1] & 0xff) + "\t"
    + (bf[2] & 0xff) + "\t" + (bf[3] & 0xff));
  // 对开始的四个字节进行校验
  if (((bf[0] & 0xff) != 215) || ((bf[1] & 0xff) != 205)
    || ((bf[2] & 0xff) != 198) || ((bf[3] & 0xff) != 154)) {
   bf = null;
   throw new IOException("此文件不为活动式wmf文件.....");
  }
  // 验证文件校验位
  int index = 0;
  for (int i = 0; i < 20; i += 2) {
   if (i == 0) {
    index = (((int) bf[i + 1] & 0xff) << | ((int) bf[i] & 0xff);
   } else if (i < 19) {
    index ^= (((int) bf[i + 1] & 0xff) << | ((int) bf[i] & 0xff);
   }
  }
  if (index != ((((int) bf[21] & 0xff) << | ((int) bf[20] & 0xff))) {
   bf = null;
   throw new IOException("此wmf文件已损坏!");
  }
  return bf;
}



接下来的信息为文件头信息:

typedef struct _WindowsMetaHeader
{
  WORD  FileType;       /* Type of metafile (0=memory, 1=disk) */
  WORD  HeaderSize;     /* Size of header in WORDS (always 9) */
  WORD  Version;        /* Version of Microsoft Windows used */
  DWORD FileSize;       /* Total size of the metafile in WORDs */
  WORD  NumOfObjects;   /* Number of objects in the file */
  DWORD MaxRecordSize;  /* The size of largest record in WORDs */
  WORD  NumOfParams;    /* Not Used (always 0) */
} WMFHEAD;


01 00(当为0的时候表示此文件只存在于内存,当为1的时候表示此文件是以文件形式存在的)

09 00(是一个固定值,表示文件头的大小总是9个字大小,即18个字节)

00 03(使用的windows版本号一般是windows 3系列)

4d 00 00 00 (文件大小以字为单位不包含 文件缩放信息的22字节)

02 00(Number of objects in the file )

0f 00 00 00(此文件的最大记录数)
00 00(保留位)



接下来是记录信息:

typedef struct _StandardMetaRecord
{
    DWORD Size;          /* Total size of the record in WORDs */
    WORD  Function;      /* Function number (defined in WINDOWS.H) */
    WORD  Parameters[];  /* Parameter values passed to function */
} WMFRECORD;

根据上面给出的文件二进制信息,

可知第一个记录的大小为: 04 00 00 00(即8字节大小)

对应函数的十六进制为01 03

函数参数为 00 08



第二个记录的大小为:05 00 00 00

对应函数的十六进制为:02 0b

函数参数为:f3 bf,00 91

...........................

依此类推,关于windows gdi函数与十六进制的对应关系,由于一些原因,本人只收集了一部分,希望有这方面资料的高手能贴上来,供大家分享。

AbortDoc 0x0052
Arc 0x0817
Chord 0x0830
DeleteObject 0x01f0
Ellipse 0x0418
EndDoc 0x005E
EndPage 0x0050
ExcludeClipRect 0x0415
ExtFloodFill 0x0548
FillRegion 0x0228
FloodFill 0x0419
FrameRegion 0x0429
IntersectClipRect 0x0416
InvertRegion 0x012A
LineTo 0x0213
MoveTo 0x0214
OffsetClipRgn 0x0220
OffsetViewportOrg 0x0211
OffsetWindowOrg 0x020F
PaintRegion 0x012B
PatBlt 0x061D
Pie 0x081A
RealizePalette 0x0035
Rectangle 0x041B
ResetDc 0x014C
ResizePalette 0x0139
RestoreDC 0x0127
RoundRect 0x061C
SaveDC 0x001E
ScaleViewportExt 0x0412
ScaleWindowExt 0x0410
SelectClipRegion 0x012C
SelectObject 0x012D
SelectPalette 0x0234
SetTextAlign 0x012E
SetBkColor 0x0201
SetBkMode 0x0102
SetDibToDev 0x0d33
SetMapMode 0x0103
SetMapperFlags 0x0231
SetPalEntries 0x0037
SetPixel 0x041F
SetPolyFillMode 0x0106
SetRelabs 0x0105
SetROP2 0x0104
SetStretchBltMode 0x0107
SetTextAlign 0x012E
SetTextCharExtra 0x0108
SetTextColor 0x0209
SetTextJustification 0x020A
SetViewportExt 0x020E
SetViewportOrg 0x020D
SetWindowExt 0x020C
SetWindowOrg 0x020B
StartDoc 0x014D
StartPage 0x004F

关于各个函数的功能大家也可在百度百科中找到。

  然而事情并没有就这么完,光是知道上面的那些并不能解析出我们需要的信息,因为上面得到的坐标信息是文件的逻辑坐标信息,关于逻辑坐标转换为设备坐标需要用到一些数学知识,公式如下:

下面的公式是将窗口(逻辑)坐标转化为视口(设备)坐标: 
 
xViewport   =   (xWindow   -   xWinOrg)*xViewExt/xWinExt   +   xViewOrg
yViewport   =   (yWindow   -   yWinOrg)*yViewExt/yWinExt   +   yViewOrg
(xWindow,yWindow)是待转换的逻辑点,(xViewport,yViewport)是转换后的设备坐标。 
设备坐标的视口原点(xViewOrg,yViewOrg)和逻辑坐标的窗口原点(xWinOrg,yWinOrg)默认情况下均被设置成(0,0),但具体情况下可以改变;
(xWinExt,yWinExt)是逻辑坐标的窗口范围;(xViewExt,yViewExt)是设备坐标的窗口范围,在多数映射方式下,范围是映射方式所隐含的,


下面给出具体的说明:

根据以上给出的字节信息:

此文件的逻辑坐标为(在windows gdi函数中设置逻辑坐标的函数十六进制为020b):(0091,f3bf);对应上面公式的(xWindow   ,yWindow   )

此文件的逻辑横纵轴的长度为(在windows gdi函数中设置逻辑坐标系横纵轴的函数十六进制为020c):(0237,01e8); 对应上面公式的(xWinOrg,yWinOrg)

现在对活动式wmf文件的解析基本上已经差不多了,关于上面公式的(xViewExt,yViewExt)可以自己设置。



初次发表技术博文,希望指正出有错误的地方,谢谢!

图详见本人51博客地址:
http://chenyanxi.blog.51cto.com
分享到:
评论

相关推荐

    JAVA WMF 转换SVG,PNG

    wmf2svg-0.9.5.jar文件正是这个工具的Java实现,它能够解析WMF和EMF文件,并将其转化为SVG格式。该工具通常通过命令行接口调用,允许开发者将其集成到自动化流程或Java应用程序中。 接着,有了SVG图像,我们就可以...

    poi解析word文档 及 试卷数学公式导入wmf图片转成png图片

    这可能是通过读取WMF文件的元数据,解析图形指令,然后重新绘制为PNG像素流来完成的。 从文件名称列表来看: - "试卷导入模板.doc":这可能是一个包含示例试题的Word文档,可能包含数学公式和图形,用于测试或演示...

    在网页上浏览并缩放wmf、emf等图元文件

    1. **图元文件解析**:理解WMF和EMF文件结构,编写代码来读取和解释文件内容。 2. **矢量图形渲染**:创建一个能在Web环境中绘制矢量图形的机制,可能通过JavaScript和Canvas,或者使用WebGL进行3D渲染。 3. **...

    emf文件和wmf的转换

    WMF文件通常用于简单的剪贴画和图形,或者作为其他应用程序之间的图形交换格式。 在实际应用中,你可能需要将EMF文件转换为WMF,反之亦然,这通常是出于兼容性考虑或是因为特定软件只接受其中一种格式。提供的源码...

    doc/docx转html,以及wmf与emf转jpg,png图片

    1. 解析图形: Batik提供了`VectorGraphics2D`类来解析WMF或EMF文件。 2. 转换:通过`Rasterizer`或者`ImageWriter`接口,可以将矢量图形渲染成指定的位图格式,例如JPEG或PNG。 3. 输出图片:将生成的位图数据写入...

    将WMF图片格式转换成PNG

    这个过程涉及到读取WMF文件,将其解析为内部的SVG表示,然后生成SVG的XML源代码。 **SVG到PNG转换** 完成WMF到SVG的转换后,我们可以通过 Batik 的`SVGGraphics2D` 和 `PNGTranscoder` 类将SVG文件转换为PNG。`...

    wmf转svgz、png

    然而,WMF文件不跨平台兼容,且文件大小相对较大,不适合网络传输。 2. EMF格式:EMF(Enhanced Metafile)是WMF的增强版,同样为矢量格式,它包含了更多的图形功能和色彩管理,支持透明度和更高的分辨率。EMF通常...

    Java读取word文档内容并输出成网页(含图片,公式)

    Java POI库是Apache软件基金会开发的一个开源项目,专门用于处理Microsoft Office格式的文件,包括Word、Excel和PowerPoint等。在这个场景中,我们将重点讨论如何使用Java POI读取Word文档并将其内容转换为HTML网页...

    WMFTOPNG.zip

    `WMFTOPNG.zip`压缩包内的文件可能包括一个简单的Java程序,用于调用Batik库进行转换操作,以及一个或多个示例WMF文件。要运行这个项目,你需要将压缩包解压,确保你的Java环境配置正确,并且已添加Batik库到你的...

    java将word转换为html,包含JAVA实现代码与需要jar文件

    在本文中,我们将深入探讨如何使用Java来实现这个功能,包括所需的jar文件和处理Word中的矢量图(WMF和EMF图片)。 首先,我们需要引入一个关键的库,Apache POI,它是一个用于读写Microsoft Office格式文件的Java ...

    文件切割,生成XML文件

    在Windows中,元文件可以用来存储图形数据,如Windows Metafile (WMF) 或 Enhanced Metafile (EMF) 格式,这些格式可以存储矢量图形。在本项目中,`metafile.exe`可能是用于处理或展示切割过程中的元数据或图形信息...

    RTF文本转图片 - WMF图片转BMP、JPG

    WMF文件可以无损地缩放,而BMP和JPG则是像素化的格式。BMP是无压缩的图像格式,保留了原始图像的所有细节,但文件大小较大;JPG则采用有损压缩,适合于照片或色彩丰富的图像,文件大小相对较小。转换通常可以通过...

    利用POI将word转换成html实现在线阅读

    Apache POI是一个强大的开源Java库,它允许开发者读取、写入以及创建Microsoft Office格式的文件,包括Word(.doc)文档。 首先,让我们深入了解Apache POI库。POI项目始于2001年,其目标是提供一个API,让开发者...

    StarUML是一款非常好的UML建模工具 汉化版 自带JAVA,C++插件

    StarUML 支持多种格式的影像文件,可导出JPG、JPEG、BMP、EMF和WMF等格式的影像文件。 StarUML 可以依据类图的内容生成Java、C++、C#代码,也能够读取Java、C++、C#代码反向生成类图。反向工程有两个主要用途,其一...

    Java用freemarker导出word文档

    这个类可能是专门处理图片的,比如将图片从网络或文件系统读取,转换为Word支持的格式(如EMF或WMF),并插入到文档中。 7. **springbootdemo.zip**: 这是一个Spring Boot应用的示例项目,可能包含了上述所有类的...

    Java中使用正则表达式获取网页中所有图片的路径

    ([^'/\"\\n\\r\\f&gt;]+(\\.jpg|\\.bmp|\\.eps|\\.gif|\\.mif|\\.miff|\\.png|\\.tif|\\.tiff|\\.svg|\\.wmf|\\.jpe|\\.jpeg|\\.dib|\\.ico|\\.tga|\\.cut|\\.pic)\\b)[^&gt;]*&gt;" ``` 这个正则表达式的工作原理是: 1. `...

    JPedal JBIG2 Image Decoder:在 BSD 许可下为 Java 编写的 JBIG2 解码器-开源

    JPedal JBIG2 图像解码器是 JBIG2 文件格式的 100% 纯 Java 图像解码器。 该解码器采用了 2007 年为 JPedal PDF 渲染器开发的 JBIG2 图像处理技术,并将其作为通用库提供给更广泛的使用。 JDeli 图像库 ...

Global site tag (gtag.js) - Google Analytics