了解采用 Office 二进制文件格式的图形

**摘要:**本文讨论 MS-ODRAW 二进制文件格式(也称为 OfficeArt),它用于存储当前和以前的 Microsoft Office 产品中的图形对象。

上次修改时间: 2015年3月9日

适用范围: Excel 2010 | Office 2007 | Office 2010 | Open XML | PowerPoint 2010 | SharePoint Server 2010 | VBA | Word 2010

本文内容
什么是 MS-ODRAW 文件格式?
MS-ODRAW 文件格式中的结构
从二进制文件提取艺术内容
结论
其他资源

**供稿人:**Microsoft Corporation

目录

  • 什么是 MS-ODRAW 文件格式?

  • MS-ODRAW 文件格式中的结构

    • 绘图组

    • 绘图

    • 形状

      • 形状类型

      • 坐标和分组

    • 规则

    • 位图

    • 属性

  • 从二进制文件提取艺术内容

    • 形状和形状组

    • 属性

    • 位图

  • 结论

  • 其他资源

本文介绍 MS-ODRAW 二进制文件格式的元素,并提供如何从二进制文件提取艺术内容的示例。本文旨在说明可对二进制文件执行的某些实际任务,并使您能够基本了解将帮助您进行更深入探索的格式。紧跟在本文后面的一系列文章介绍 Microsoft Office 产品使用的二进制文件格式。应将这些文章与 Microsoft MSDN 上提供的open file format specifications结合起来阅读:

什么是 MS-ODRAW 文件格式?

[MS-ODRAW]: Office Drawing Binary File Format也称为 OfficeArt,是 Microsoft Office 应用程序使用的一种二进制文件格式,用于存储绘图元素,例如图片、形状和艺术字及其关联的格式。这些元素可包含在其他绘图中,或包含在图表、关系图、表和控件中,或者可能显示为文件中的独立组件。

MS-ODRAW 格式将图形对象存储在由主机程序(如 Microsoft Word)创建的文件中。可以在由 MS-OGRAPH 格式(也存储在主机文件内)定义的图表、图形或表的上下文中找到这些图形对象。没有 MS-ODRAW 文件。

此格式以及由 Microsoft Word、Microsoft PowerPoint、Microsoft Excel 和 Microsoft Outlook 使用的文件格式全部完整记录在 MSDN 库中的以下位置:Open Specifications/Data Portability/Microsoft Office File Formats/Microsoft Office File Format Documents。您可以从此位置打开文件格式的完整规范(直接在 MSDN 网站上打开或作为 .pdf 文件打开)。

备注

在 Microsoft Office 中执行大多数编程任务的推荐方法是使用 Office 主互操作程序集。这些程序集是一组提供可用于 Microsoft Office 的完整对象模型的 .NET 类。本系列文章只涉及高级方案,如未安装 Microsoft Office 的情形。

MS-ODRAW 文件格式中的结构

图形对象由一系列记录(可能包含其他记录)组成。包含其他记录的记录称为容器,而存储数据的记录称为 Atom。所有记录都共享一个通用Record Header,后者指定记录类型和长度。记录标头还具有 Atom 记录用于指定版本和实例的字段,以便与同一容器中的其他 Atom 区分开。

由于这些记录共享一个公共标头,因此您可以通过只读取每个标头的 recType 和 recLen 字段来有选择地分析记录,直至找到所需记录为止。另外,您可以通过创建唯一的 recType 值来定义仅应用于应用程序的自定义记录类型,主机应用程序将通过这种方式定位文档中的绘图元素并呈现关联的文本。

以下各节说明主机文档内对象容器层次结构的组织,并介绍一些应用于不同种类的图形元素的关键结构。若要查看对象容器层次结构的图示和其他说明,请参阅 MS-ODRAW 规范中的 1.3 Structure Overview (Synopsis)一节。

绘图组

包含图形元素的每个主机文件都包含一个图形组,其中承载文件中的所有图形。这些图形存储在各个图形对象中,而不存储在图形组本身中,但在逻辑上与其关联。图形组包含一个属性表(其中存储新形状的默认值),以及一个 BLIP 存储(其中包含文件中使用的所有静态图像)。各个绘图从中心位置引用这些图像来减少重复的图片数据。

图形组在 OfficeArtDggContainer 记录中指定。

绘图

图形对象表示主机文档内的一个完整图形元素,例如一张剪贴画、艺术字或维恩图中形状的分组。图形对象将包含一个或多个形状对象以及一组应用于图形中所有形状的规则。

图形对象由 OfficeArtDgContainer 记录表示。它包含一个通用记录标头,以及 OfficeArtFDG 记录中 16 个字节的图形数据,用于指定图形中的形状数以及图形中最后一个形状的标识符。

图形对象还包含一组应用于图形中的连接器、弧形和标注的规则,以及四组不同的形状,这些形状根据形状分组和删除状态进行排序,如下表所示。

绘图记录中的形状集合

字段

记录类型

说明

deletedShapes

OfficeArtSpgrContainerFileBlock 的数组

定义删除的形状和形状组。

groupShape

OfficeArtSpgrContainer

定义组合形状的形状属性,并以数组形式包含组中的所有形状。

regroupItems

OfficeArtFRITContainer

保留未分组的形状的组标识符。

shape

OfficeArtSpContainer

定义当前绘图的默认形状属性。

形状

Microsoft Office 应用程序中创建的大多数绘图都由形状组成。各个形状都具有属性,用于确定形状类型(例如圆角矩形或双箭头)、它与其他形状的关系、大小、位置以及有关其呈现方式的各种详细信息(例如线型和填充)。单个形状在 OfficeArtSpContainer 记录中定义。

形状类型

所有 OfficeArt 形状类型都列在 MSOSPT 枚举中。在定义形状的 OfficeArtSpContainer 记录内,有一个 shapeProp 属性,该属性是一个 OfficeArtFSP 记录。OfficeArtFSP 记录标头的 recInstance 字段存储用于设置形状类型的 MSOSPT 枚举值。下图演示了在容器层次结构中定义四角星的方式。

容器层次结构中的形状类型示意图

坐标和分组

坐标和分组是紧密相连的,因为如何设定形状的位置和大小取决于其分组状态。绘图中的所有形状都是顶级形状组的一部分,该组在 OfficeArtSpgrContainer 记录中定义。在形状组中,有一个其他形状定位到的核心形状,称为组合形状。该形状不会显示。顶级形状组由定义组合形状的 OfficeArtSpContainer 记录的 clientAnchor 属性定位在客户端 UI 界面上。clientAnchor 是一个由客户端应用程序定义的 OfficeArtClientAnchor 记录。

相对于客户端定位的位置和大小由分组决定。一个简单的形状定义为顶级形状组的直接子级,而已分组到 UI 中其他形状的形状成为下属形状组。与顶级组一样,下属形状组在 OfficeArtSpgrContainer 记录中定义,该记录将定义形状的 OfficeArtSpContainer 记录封装在 OfficeArtSpgrContainerFileBlock 记录中。组合形状的大小和位置由 OfficeArtSpContainer.shapeGroup 属性定义,该属性是一个 OfficeArtFSPGR 记录。每个子形状的坐标由其 OfficeArtSpContainer.childAnchor 属性定义,该属性是一个 OfficeArtChildAnchor 记录。

以下示例演示了两个类似的形状。

罗盘

罗盘

四角星

四角星

罗盘由两个组合在一起的菱形形状 垂直菱形水平菱形组成,而四角星是一个简单的形状,并非下属组的一部分。

在罗盘中,用户首先创建了垂直菱形,然后将水平菱形放在其上,并将它们组合在一起。这样就使其包含在下属组形状中,两个菱形作为其子形状。下图演示了两个菱形在绘图容器层次结构中的显示位置,及其各自坐标的查找位置。

绘图容器示意图

组合形状的坐标位于 .shapeGroup 属性中。数组中的第二和第三个形状是子形状,将其坐标保留在其各自的 .childAnchor 属性中。添加到该组中的任何其他形状也会将其坐标存储在 .childAnchor 属性中。

上图中的四角星是作为单个形状创建的,并存储为顶级组合形状的直接子级,如下图所示:

简单形状的容器层次结构

规则

在单个图形中,规则定义连接器、弧形和标注。文件中的每个 OfficeArtDgContainer 图形对象都包含一个 OfficeArtSolverContainer 实例,用于存储 OfficeArtSolverContainerFileBlock 记录的数组,其中每个记录可能为 OfficeArtFConnectorRuleOfficeArtFArcRuleOfficeArtFCalloutRule

OfficeArtFConnectorRule 记录根据连接器连接到的形状(例如流程图)定义连接器,以及它定位到形状上的哪个点。连接器规则是相关的主要规则。标注规则和弧形规则只提供应用它们的标注或弧形的 ID,而不提供任何其他信息。

若要查看使用连接器规则的 OfficeArtSolverContainer 的示例,请参阅 MS-ODRAW 文档中的 3.1.5 OfficeArtSolverContainer

位图

MS-ODRAW 格式将位图图像称为二进制大型图像或图片 (BLIP)。Microsoft Office 文档中的位图集中存储在 BLIP 存储 中,后者为顶级绘图组中的 OfficeArtBStoreContainer 记录。BLIP 存储包含 OfficeArtBStoreContainerFileBlock 记录的数组。在 BLIP 存储的记录标头中,recInstance 和 recLen 字段指定 OfficeArtBStoreContainerFileBlock 记录数及其总大小(以字节为单位)。

每个 OfficeArtBStoreContainerFileBlock 记录都包含一个 OfficeArtFBSE 记录或空 OfficeArtBlip 记录,由其记录标头的 type 字段指定。OfficeArtFBSE 记录将 OfficeArtBlip 记录封装在名称、大小、类型和偏移信息中。OfficeArtBlip 记录包含记录标头以及图像的实际位流。

下图演示了容器层次结构中二进制图像数据的位置。

显示图像数据位置的示意图

属性

属性定义形状和位图。MS-ODRAW 格式将属性存储在属性表中。每个形状都具有存储仅应用于该形状的属性的属性表,其中包括 OfficeArtFOPT 记录、OfficeArtSecondaryFOPT 记录和 OfficeArtTertiaryFOPT 记录。在记录名称中,"PT"表示"属性表"。另外,顶级绘图组包含一个存储应用于整个文件的属性的属性表,该属性表仅包括 OfficeArtFOPT 记录和 OfficeArtTertiaryFOPT 记录。属性在顶级绘图组中定义并用作未由单个形状定义的属性的默认值,但在设置了单个形状属性的情况下,它们会覆盖默认值。在任一位置未设置的属性会还原为系统或应用程序默认值。每个属性表的记录标头指定属性数和记录的长度(以字节为单位)。

在 OfficeArtFOPT 中,OfficeArtSecondaryFOPT 或 OfficeArtTertiaryFOPT 记录是分类的 OfficeArtRGFOPTE 记录的数组,其中每个记录表示一组相关属性。在记录名称中,"RG"表示"相关组","PTE"表示"属性表条目"。各个属性都存储为 OfficeArtFOPTE 记录。这些记录不具有记录标头,但以 opid 字段开头,该字段指定属性的标头信息。Opid 存储为 OfficeArtFOPTEOPID 记录。如果 OfficeArtFOPTEOPID 记录的最后一位(即 fComplex 字段)等于 0x1,则该属性为复杂属性。在本例中,超出 OfficeArtFOPTE 记录的 4 个字节限制的信息将移至父 OfficeArtRGFOPTE 表的 complexData 部分。

从二进制文件提取艺术内容

从 Microsoft Office 二进制文件提取艺术内容的过程部分取决于要提取的艺术内容的类型,部分取决于主机应用程序。下表显示了哪些结构以不同的 Microsoft Office 二进制文件格式承载绘图和绘图组。

按主机应用程序划分的绘图组位置

主机应用程序

包含绘图的结构

包含绘图组的结构

Microsoft Excel

HFPictureMsoDrawing

HFPictureMsoDrawingGroup

Microsoft PowerPoint

DrawingContainer

DrawingGroupContainer

Microsoft Word

OfficeArtWordDrawing

OfficeArtContent

以下过程说明通常如何从主机应用程序提取 MS-ODRAW 内容,而不包括特定于该应用程序的任何内容。

记录标头

MS-ODRAW 格式中所有记录标头的长度都为 8 个字节,并且从零开始编制索引。例如,第三个字节是字节 2,最后一个字节是字节 7。字节 2-3 指定记录类型,最后 4 个字节指定记录长度(以字节为单位)。在知道记录类型和长度后,即可决定是读取记录长度中指定的字节数,还是跳过相同数目的字节并转到下一条记录。

形状和形状组

以下过程说明如何在 Microsoft Office 文档中重新构造简单的形状和形状组。这不包括连接器或标注,它们在规划求解容器或者图表和图形(使用 MS-OGRAPH 格式)中已指定。这些过程也不指定客户端文档中形状或形状组的具体位置,并且不包括撤消历史记录或修订历史记录选项。

采用 MS-ODRAW 格式重新构造形状组或唯一形状

  1. 在文件中查找 OfficeArtDgContainer 记录,以获得包含相关形状组的绘图,或循环访问所有绘图,直至找到符合您的条件的绘图为止。

    读取记录标头以获取绘图末尾的字节数。

  2. 检查容器中的每个记录标头,直至找到记录类型为 OfficeArtSpgrContainer (0xf003) 的记录为止。如果没有 OfficeArtSpgrContainer 记录,表明绘图中没有任何形状。

  3. OfficeArtSpgrContainer 记录表示 .groupShape 字段。该记录以 OfficeArtSpgrContainerFileBlock 记录数组的形式包含绘图中的所有活动形状。

    读取记录标头以获取容器长度,然后开始读取第一个 OfficeArtSpgrContainerFileBlock 记录。因为这是数组中的第一个 OfficeArtSpgrContainerFileBlock 记录,所以它必须包含 OfficeArtSpContainer 记录,该记录必须对应于当前组的组合形状。

  4. 如下一过程"采用 MS-ODRAW 格式重新构造单个形状"中所述,读取 OfficeArtSpContainer 记录。

  5. 开始读取下一个 OfficeArtSpgrContainerFileBlock 记录,从记录标头开始。

  6. 如果 .recType 为 0xF004,则当前文件块的其余部分为 OfficeArtSpContainer 记录。如下一过程"采用 MS-ODRAW 格式重新构造单个形状"中所述,读取该记录。

    如果 .recType 为 0xF003,则当前文件块的其余部分为 OfficeArtSpgrContainer 记录,这表示下属形状组。如前三步中所述读取该记录。

  7. 以同一方式读取其余的 OfficeArtSpgrContainerFileBlock 记录。

  8. 查找表示文件的绘图组的 OfficeArtDggContainer。

  9. 在 OfficeArtDggContainer 内,通过检查每个记录标头来查找属性表,读取 OfficeArtFOPT 和 OfficeArtTertiaryFOPT 类型的记录,并跳过其余记录。

  10. 这些属性表表示整个文件中的默认属性。像以前一样分析这些属性表,但仅将这些表中的属性应用于尚未指定相关属性的形状。

  11. 在应用程序中根据收集的信息呈现形状组。

在形状组中重新构造单个形状

  • 从 OfficeArtSPContainer 记录开始,读取容器中每个记录的记录标头,并按如下所示继续操作:

    1. 如果记录类型为 OfficeArtFSPGR (0xF009),且这是绘图中的第一个形状(因此是组合形状),则该记录表示 .shapeGroup 字段。跳过记录标头,将其余 16 个字节作为四个 4 字节的带符号整数读取到内存中,这些整数指定顶级组合形状的左、上、右和下坐标。

    2. 如果记录类型为 OfficeArtChildAnchor (0xF00F) 且当前形状不是组合形状,则该记录表示 .childAnchor 字段。跳过记录标头并将其余 16 个字节作为四个带符号整数读取到内存中,这些整数指定当前形状相对于其父组合形状的左、上、右和下坐标。

    3. 如果记录类型为 OfficeArtFSP (0xF00A),则该记录表示 .shapeProp 字段,其长度为 16 字节。将该记录读取到内存中。位 4-15 指定一个用于定义形状类型的 MSOSPT 枚举值。位 101 和 102 指定形状相对于其默认方向是水平翻转还是垂直翻转。

    4. 如果记录类型为 OfficeArtFOPT (0xF00B)、OfficeArtSecondaryFOPT (0xF121) 或 OfficeArtTertiaryFOPT (0xF122),则该记录为属性表。如下一过程"采用 MS-ODRAW 格式分析属性"中所述,分析其中的属性。

    5. 跳过其他所有记录。

属性

采用 MS-ODRAW 格式分析属性

  1. 从属性表(如 OfficeArtFOPT 记录)开始读取 .fopt 数组(包括 OfficeArtRGFOPTE 属性组)的第一个成员。每个组表示属性表中某个类别的属性。

  2. 开始读取第一个 OfficeArtRGFOPTE 组。OfficeArtRGFOPTE 记录没有记录标头,但以 .rgfopte 数组(包括 OfficeArtFOPTE 记录)的第一个成员开头。

  3. 每个 OfficeArtFOPTE 记录表示一个属性。将 2 字节的 .opid 字段(是一个 OfficeArtFOPTEOPID 记录)读取到内存中。

    以无符号整数的形式读取该属性的第一个 14 位标识符。若要查找哪些整数值对应于哪些属性,请查看 ODRAW 规范的section 2.3中的属性列表。

    如果最后一位设置为 1,则表示这是一个复杂属性。

  4. 以带符号整数(用于指定该属性的值)的形式读取当前 OfficeArtFOPTE 记录的其余 4 字节 .op 字段,或者,如果该属性为复杂属性,则为存储该值的复杂数据的字节数。

  5. 以同一方式读取 .rgfopte 数组中的其余条目。

  6. 在最后一条 OfficeArtFOPTE 记录后,读取复杂数据。复杂数据与数组中的属性的显示顺序相同,并采用其 .op 字段中指定的大小。

  7. 按照与上述步骤中相同的方式读取其余 OfficeArtRGFOPTE 属性组,直至完成属性表为止。

位图

采用 MS-ODRAW 格式提取位图图像

  1. 在文件中找到 OfficeArtDggContainer 记录。

  2. 读取记录标头以获取容器长度。

  3. 检查容器内每个记录的记录标头,直至找到 OfficeArtBStoreContainer (0xF001) 记录(表示 .blipStore 字段),或到达 OfficeArtDggContainer 末尾为止。如果没有 OfficeArtBStoreContainer 记录,表明没有要提取的位图。

  4. OfficeArtBStoreContainer 记录将文件的所有位图存储在 OfficeArtBStoreContainerFileBlock 记录数组中。读取记录标头。

    位 4-15 是无符号整数,用于指定数组的长度。

  5. 对于数组中的每个 OfficeArtBStoreContainerFileBlock 记录,执行以下操作。

    1. 读取记录标头的字节 2-3 以获取记录类型。

    2. 如果记录类型为 0xF018-0xF117,则该记录是 OfficeArtBlip。继续执行此过程的下一步。

      如果记录类型为 0xF007,则该记录为 OfficeArtFBSE。执行以下操作:

      1. 跳过前 20 个字节。

      2. 读取接下来的 4 个字节,这些字节将位图大小指定为无符号整数。

      3. 跳过接下来的 12 个字节。

      4. 读取 .name 字段,这是一个长度可变的以 空 结尾的 Unicode 字符串,用于指定位图名称。

        下一个字段是 .embeddedBlip,它是一个 OfficeArtBlip 记录。

    3. 读取 OfficeArtBlip 记录的记录标头。字节 2-3 指定图像在未单独保存时的文件类型。记录标头的最后 4 个字节指定记录的其余部分的长度。有关哪些类型值对应于哪些文件类型的详细信息,请参阅 MS-OGRAPH 规范的section 2.2.23

    4. 将记录的其余部分读取到内存中,并保存为记录标头指定的文件类型。

  6. 开始读取下一个 OfficeArtBStoreContainerFileBlock 记录,并以同一方式继续操作,直至处理完所有位图为止。

结论

对任何 Microsoft Office 二进制文件进行更改都需要将该文件读取到内部表现形式,编辑该表现形式,然后重新编写该文件。由于具有这些要求,因此保存操作需要彻底了解涉及的文件格式,这不在本文的讨论范围之内。本文和同系列中的相关文章提供执行简单提取和便于更好地理解 MS-ODRAW 格式所需的步骤和信息。

具体来说,具备 MS-ODRAW 格式的基础知识使您能够在 Microsoft Office 二进制文件中遇到图形对象和位图时识别和分析它们,从而有助于提高您处理其他 Microsoft Office 二进制文件格式的能力。

其他资源

有关详细信息,请参阅以下资源: