Open XML Images: 3D effects

One of the key benefits of the Open XML file formats is that they support all of the things you can do in Office documents. If you've created documents in past version of Word, Excel or PowerPoint that have unusual or complex formatting, you can simply save as Open XML (the new default format) from within the Office 2007 clients, and you'll preserve all of the formatting nuances. Every single detail will be preserved in the conversion to Open XML, right down to the angle of the light source for the shadow effect on the border of an image in the document.

To get a feel for how this works, let's try a little experiment: we'll manually create a document in Word 2007 that contains an image, then change some of the properties of the embedded image and see what that does to the underlying XML markup.

It's worth noting that this approach doesn't yield the simplest possible markup, because we're letting Word save the document. Word structures the internal details of a document to allow for consistency across many different scenarios, and much of that structure isn't relevant to what I'm demonstrating in this simple example. For a great example of the simplest possible markup to embed an image, check out Brian Jones's video on creating a simple WordprocessingML document. Another good "Hello World" example can be found in Tom Ngo's Open XML whitepaper. Those examples show the type of approach you'd take if you're programmatically generating a document; the examples below are for educational purposes only.

An image in a DOCX

First let's create a very simple document with nothing but a plain image in it. Fire up Word 2007 Beta 2 Tech Refresh and insert an image. Then save the document as DOCX, rename that DOCX to a ZIP extension, drill down into the word folder inside the package, and take a look at the contents of document.xml. You should see something like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<w:document ...>
<w:body>
  <w:p>
    <w:r ...>
      <w:drawing>
        <wp:inline ...>
          <a:graphic ...>
            <a:graphicData ...>
              <pic:pic ...>
                <pic:blipFill>
                   <a:blip r:embed="rId4" cstate="print">

I've removed some tags and attributes from this example, to make it easy to see the logical structure of the document. Note that last tag above, with its r:embed attribute. That attribute says, in essence, "insert here an embedded image as defined by relationship rId4." If you go look at that relationship in the rels folder, it probably looks something like this:

<Relationship Id="rId4" Type="https://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.jpeg"/>

The image you inserted is stored in the media folder as image1.jpeg, and the relationship points to it there. This is a very loosely coupled approach: the relationship or the image itself can be changed without changing anything in the WordprocessingML document.

Note that the name of the image has changed, by the way -- Word changed it to image1.jpeg, but my original image in this case was doug.jpg. The original name is stored as an attribute of a property tag inside the drawing node, and this allows for inserting any number of images that share the same name, regardless of whether they're really the same content or not.

Specifying 3D format/rotation

Now let's take that document and change a couple of properties on the picture. Right-click on the image in Word 2007, then select 3D format and pick the first option for Bevel/top, then select 3D rotation and pick the 3rd preset option. You'll get something like the image to the right. Now save this document, and take a look at what changed in document.xml.

The first thing you may notice is that the attributes of the wp:effectExtent element (located inside the wp:inline element) have changed. This tag specifices the "square wrapping extent" for the image, which specifies how text will wrap around the image. Since we're not doing anything with text in this example, let's skip that one for now.

The more significant change in document.xml is the a:scene3d element that has been added inside the pic element:

<a:scene3d>
  <a:camera prst="isometricTopUp" />
  <a:lightRig rig="threePt" dir="t" />
</a:scene3d>

The scene3d element (section 5.1.3.1.26 of the spec) is where 3D scene properties are stored. These properties define the relative position of the viewer (you) and the object (the image), as well as the position of optional light sources that will create shadows and highlights on the image's beveled border.

The first property defined inside the scene3d element above is the camera type, which is isometricTopUp. That's what makes the image appear to lay down a bit, with the top up -- it's a predefined set of properties that provides this particular perspective. There are 62 values like this one to choose from, all defined in the spec under the ST_PresentCameraType enumeration (section 5.1.11.48).

The second property you'll notice in the example above is also pretty intuitively named: lightRig. You'd expect that to specify the type of lighting for the scene, and indeed it does.

As with the camera position, there are predefined options available for the light rig. You'll find 27 to choose from in section 5.1.11.31, under the ST_LightRigType enumeration. The example used here, threePt, simulates three light sources as some predefined locations.

Learning more

To learn more about these sorts of options in Open XML, you can either look things up the spec and insert them into a document, or create documents with Word and then use the spec to read about the changes you observe in the underlying XML markup. In my previous post on table styles, I did the former; this time around, I did the latter.

For example, I took the original document created above and pasted a bunch of copies of the image into it, then tried changing various settings under right-click/Format picture. Then I pulled the document.xml part out of the resulting document and used the spec to look up the changes in the scene3d element. (By the way, if you don't have the final draft version of the Ecma spec, Brian's blog has links to where you can download it.)

Other great places to learn more about Open XML include the OpenXmlDeveloper.org web site, and if you're working in the .NET environment the XML in Office Developer Portal is a great resource, too.

As a final example of the flexibility of Open XML, I'd like to get back to the "loosely coupled" comment I made earlier about how relationships are defined between the container (document.xml) and the image embedded in it (image1.jpeg in this case). When you paste a bunch of copies of the same image into a document as I did above, those copies all refer to the same relationship, with the same target image. So you can replace image1.jpeg (in the word/media folder of the DOCX package) with another image, and that image will then appear in all of the copies of the image within the document.

For example, I took a picture of my wife Megan and replaced the picture of me in the sample doc with it. See how easy it is to make better-looking documents with Open XML. :-)