Generating a Custom Watermark with Open XML SDK

Category: open xml format sdk


AlanNHBC on Mon, 03 Oct 2011 14:08:29

I have successfully added text watermarks to Word documents with Open XML SDK, but now want to add a custom watermark using an image as a background.

I have created a simple document in Word 2007, saved it and then created another document with the original simple document having a custom watermark from a selected image.

I then compared the two documents using the Open XML SDK 2.0 Productivity Tool, but found a bewildering number of differences and I am not clear where to start.

What I had hoped to be able to do was to provide a C# method such as:

public static void InsertCustomWatermark(WordprocessingDocument wordDocument, String customImagePath)

I would be grateful for any help on this subject such as a reference to a 'How to' document.






许阳(无锡) on Wed, 05 Oct 2011 06:24:24

Hi AlanNHBC,


Thanks for posting in the MSDN Forum.


It’s seems that you want to insert a watermark into a current document file. Please take a look at this snippet, to see whether it can approach your goal.


using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using V = DocumentFormat.OpenXml.Vml;
using System.Diagnostics;

namespace WindowsFormsApplication3
    public partial class Form1 : Form
        public Form1()

        private void button1_Click(object sender, EventArgs e)
            using (WordprocessingDocument package = WordprocessingDocument.Open(@"C:\Users\*****\****.docx", true))
                InsertCustomWatermark(package, @"C:\Users\*******\****.jpg");

        private void InsertCustomWatermark(WordprocessingDocument package, string p)
            MainDocumentPart mainDocumentPart1 = package.MainDocumentPart;
            if (mainDocumentPart1 != null)
                HeaderPart headPart1 = mainDocumentPart1.AddNewPart<HeaderPart>();
                string rId = mainDocumentPart1.GetIdOfPart(headPart1);
                ImagePart image = headPart1.AddNewPart<ImagePart>("image/jpeg", "rId999");
                IEnumerable<SectionProperties> sectPrs = mainDocumentPart1.Document.Body.Elements<SectionProperties>();
                foreach (var sectPr in sectPrs)
                    sectPr.PrependChild<HeaderReference>(new HeaderReference() { Id = rId });
        private void GenerateHeaderPart1Content(HeaderPart headerPart1)
            Header header1 = new Header();
            Paragraph paragraph2 = new Paragraph();
            Run run1 = new Run();
            Picture picture1 = new Picture();
            V.Shape shape1 = new V.Shape() { Id = "WordPictureWatermark75517470", Style = "position:absolute;left:0;text-align:left;margin-left:0;margin-top:0;width:415.2pt;height:456.15pt;z-index:-251656192;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin", OptionalString = "_x0000_s2051", AllowInCell = false, Type = "#_x0000_t75" };
            V.ImageData imageData1 = new V.ImageData() { Gain = "19661f", BlackLevel = "22938f", Title = "水印", RelationshipId = "rId999" };
            headerPart1.Header = header1;
        private void GenerateImagePart1Content(ImagePart imagePart1)
            System.IO.Stream data = GetBinaryDataStream(imagePart1Data);
        private string imagePart1Data = "";
        private System.IO.Stream GetBinaryDataStream(string base64String)
            return new System.IO.MemoryStream(System.Convert.FromBase64String(base64String));
        public void SetWaterMarkPicture(string file)
            FileStream inFile;
            byte[] byteArray;
                inFile = new FileStream(file, FileMode.Open, FileAccess.Read);
                byteArray = new byte[inFile.Length];
                long byteRead = inFile.Read(byteArray, 0, (int)inFile.Length);
                imagePart1Data = Convert.ToBase64String(byteArray, 0, byteArray.Length);
            catch (Exception ex)


If you still have any questions, please feel free to let me know.


Have a good day,






AlanNHBC on Mon, 05 Dec 2011 16:18:07


Many thanks for your reply. Unfortunately I am unable to get this to work, as when I open the document using MS Word 2007, I get  "The file is corrupt and cannot be opened".

I have invoked your code above with:


Word word = new Word(true



WatermarkHandler.InsertCustomWatermark(WordprocessingDocument.Open("X:\\nhbcapps\\235HMW.docx", true



"X:\\nhbcapps\\D375_Buildmark Certi_B56F57.jpg");

The original 235HMW.docx opens successfully and so does D375_Buildmark Certi_B56F57.jpg.

I would be grateful if you could further advise.

Many thanks,    Alan.



AlanNHBC on Thu, 15 Dec 2011 16:59:11

My apologies Tom, a colleague has got this code working as follows:

using (WordprocessingDocument package = WordprocessingDocument.Open(@"E:\NickDevSources\WatermarkFiles\testdoc.docx", true))


                WatermarkHandler.InsertCustomWatermark(package, @"E:\NickDevSources\WatermarkFiles\Water.jpg");



Thank you again for your help.


TusharKantiNath on Tue, 11 Dec 2012 12:00:41

No event Handler called WatermarkHandler

Can't able to find WatermarkHandler.

Reply Soon 

Thank You

Naveen Gupta49 on Tue, 24 Apr 2018 13:52:31

Can you help me how to get TextWatermark instead of picture watermark?