This article is part of the “Building documents with code snippets” series.

Welcome to yet another installment in the series. Sorry for the small delay, I was busy starting the Open XML Objects project, go ahead and check it out!

This time I will show how to add an image to your document. The basic actions you need to take to do this is first store the image as a PackagePart inside the Package, next add the necessary WordProcessingML xml nodes to the document. There is a snippet available for each of these two actions. The first stores an external file inside the package and gives you the new PackagePart. The second one is able to create the correct WordProcessingML and DrawingML structure (yep, we will be leaving WordProcessingML land). There is a third snippet which combines the other two into one method call so it will remain easy to use.

Storing files inside a Package

When you store an external file in the package, you can obviously decide on the filename and directory to use inside the package. Because a file can already be present at the location you choose you need to take care of creating unique filenames or else start throwing around exceptions or something. I’ll take the first option.

The Packaging API provides a pretty easy method to determine if a file location is available inside the package, just check if a PackagePart already exists at a specific location. The following code returns a unique filename by appending a number ranging from 1 to 10000 to the starting filename until it is unique. When that doesn’t help, Guids are used to generate the filename. Guids can be a viable option because a PackagePart will normally be referenced using a specific relationship ID, not the file location itself.

        static string CreateUniqueFilename(string fileName, 
                string targetFolder, Package package)
        {
            string fileNameWithoutExtension = 
                Path.GetFileNameWithoutExtension(fileName);
            string extension = Path.GetExtension(fileName);
            int count = 1;
            string targetFileName = Path.Combine(targetFolder, 
                Path.GetFileName(fileName));
            while ((targetFileName = ValidateFilename(targetFileName, 
                package)) == null)
            {
                if (count < 10000)
                {
                    targetFileName = Path.Combine(
                        targetFolder, fileNameWithoutExtension + count + 
                        extension);
                    count++;
                }
                else
                {
                    targetFileName = Path.Combine(
                        targetFolder, Guid.NewGuid().ToString() + extension);
                }
            }
            return targetFileName;
        }

Now that  a unique filename can be obtained, the next step involves using the Packaging API to store the file inside the package and create a PackagePart for it. Just your basic byte array based copying algorithm using two streams.  Because a file inside the package has a specific content type attached, you can specify this as a parameter. There are a few rough edges when working with content types, the sidebar explains it a bit more.

        static PackagePart StoreFile(string fileName,
            string targetFolder,
            string contentType,
            Package owner)
        {
            string targetFilename = CreateUniqueFilename(fileName, 
                targetFolder, owner);
            PackagePart part = owner.CreatePart(
                new Uri(targetFilename, UriKind.Relative), contentType);
            using (Stream targetStream = part.GetStream())
            {
                using (FileStream sourceStream = new FileStream(fileName, 
                        FileMode.Open, FileAccess.Read))
                {
                    byte[] buffer = new byte[1024];
                    int nrBytesWritten = sourceStream.Read(buffer, 0, 1024);
                    while (nrBytesWritten > 0)
                    {
                        targetStream.Write(buffer, 0, nrBytesWritten);
                        nrBytesWritten = sourceStream.Read(buffer, 0, 1024);
                    }
                }
            }
            return part;
        }

Referencing the new image

So, storing  a file is done. Next we will need to create the correct WordProcessingML structure. The second snippet creates the minimal xml structure required for displaying an image. What nodes are needed can be determined using the Open XML specification, or you can just peek below this paragraph and look at the sample. This time we will not only make use of WordProcessingML, but also throw some DrawingML into the mix, take note of the different namespaces used. The drawing structure displayed below uses the relationship ID to reference the image inside the package.

<w:drawing>
  <wp:inline>
    <wp:extent cx="3000000" cy="3000000" />
    <wp:docPr name="test.png" id="1" />
    <a:graphic xmlns:a="
http://schemas.openxmlformats.org/drawingml/2006/3/main">
      <a:graphicData uri="
http://schemas.openxmlformats.org/drawingml/2006/3/picture">
        <pic:pic xmlns:pic="
http://schemas.openxmlformats.org/drawingml/2006/3/picture">
          <pic:nvPicPr>
            <pic:cNvPr id="2" name="test.png" />
            <pic:cNvPicPr />
          </pic:nvPicPr>
          <pic:blipFill>
            <a:blip r:embed="R564dd6f276f347c3" />
            <a:stretch>
              <a:fillRect />
            </a:stretch>
          </pic:blipFill>
          <pic:spPr>
            <a:xfrm>
              <a:off x="0" y="0" />
              <a:ext cx="3000000" cy="3000000" />
            </a:xfrm>
            <a:prstGeom prst="rect" />
          </pic:spPr>
        </pic:pic>
      </a:graphicData>
    </a:graphic>
  </wp:inline>
</w:drawing>

The structure starts with the w:drawing node. This tells the text editor that a drawing structure (not a DrawingML structure) is present at that location in the document, which could be just about anything. The wp:inline node indicates the data for the DrawingML structure is stored inline in the DrawingML object, you can also use anchors to external items.
First up inside the w:inline node is the wp:extent node which defines the size of the drawing object and the wp:docPr node to specify two required properties, a name and an ID for the drawing. The size defined within the wp:extent node is specified in EMUs, which is a unit I am yet to find out what it means,  but EMUs it is…  The id attribute is important here. The value must be unique inside the document, which means a bit of code to create this unique ID.

The a:graphic node is required at this point. It uses the a:graphicData to store the data for the drawing, and this is the node which defines what the actual content of the drawing object will be. This information is specified using the uri attribute. The rest of the contents of the a:graphicData node is dependent on the value of this attribute. A few of the possible values for this attribute include:

This sample uses a DrawingML picture inside the graphic object. The picture starts with the pic:pic node. The first child node is nvPicPr, or non-visual picture properties. This grouping node defines properties which have nothing to do with the visual appearance of the picture. It is divided into three groups. First is cNvPr or the non-visual drawing properties, which is aids the application to keep track of the object on the canvas. The second node cNvPicPr contains information which is specific to pictures, hence the separate node. You can for instance lock the aspect ratio with this node. The final node in the group is nvPr, which we will not use in this sample.

Right after the group of properties you will find the blipFill node. It specifies the image which will be used to fill the picture with. The image is referenced using a specific relationship ID. The a:stretch node causes the image to stretch the entire canvas area assigned, you can tile the image horizontally and vertically.

The DrawingML picture finishes up with another properties node named pic:spPr. These are the shape properties, which change the visual appearance of the picture. The options specifiable include scaling, moving  and rotating the image, or creating shadows. I’ll do a follow up on my blog next week and show you some samples.

Now for the code. There are two methods which you get when using the WDAddImage snippet. The first generates a unique ID value for the various elements described above. The second is a boring long method which creates the node structure.

        static string DetermineUniqueIDAttribute(XmlDocument document)
        {
        }

        static void AddImage(XmlNode parentNode, XmlNamespaceManager namespaces,
 string fileName, string relationshipID, SizeF imageSize)
        {
        }

That’s it for storing files and images inside your document. The final snippet called WDStoreAndAddImage just uses the above two snippets to allow you to use one single method call.

Join me for the next and last article in the WordProcessingML series, it is on custom xml and content controls.