package cn.flightfeather.supervision.docx4j.simpleDemo;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart;
import org.docx4j.openpackaging.parts.WordprocessingML.ImagePngPart;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart.AddPartBehaviour;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.Hdr;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.SectPr;
import java.io.File;
import java.io.IOException;
/**
*
* A watermark is set via the headers.
*
* This is different to w:document/w:background (see BackgroundImage sample for that,
* though this WatermarkPicture is probably what you want.)
*
* @author jharrop
*/
public class WatermarkPicture
{
static String DOCX_OUT;
public static void main(String[] args) throws Exception
{
// The image to add
imageFile = new File(System.getProperty("user.dir") + "/src/main/resources/images/greentick.png" );
// Save it to
DOCX_OUT = System.getProperty("user.dir") + "/OUT_WaterMarkPicture.docx";
WatermarkPicture sample = new WatermarkPicture();
sample.addWaterMark();
}
static ObjectFactory factory = Context.getWmlObjectFactory();
static File imageFile;
private byte[] image;
private WordprocessingMLPackage wordMLPackage;
public void addWaterMark() throws Exception
{
image = this.getImage();
wordMLPackage = WordprocessingMLPackage
.createPackage();
// A watermark is defined in the headers, which are in turn set in sectPr
wordMLPackage.getMainDocumentPart().getContents().getBody().setSectPr(
createSectPr() );
File f = new File(DOCX_OUT);
wordMLPackage.save(f);
}
private SectPr createSectPr() throws Exception {
String openXML = ""
// Word adds the background image in each of 3 header parts
+ ""
+ ""
+ ""
// Word adds empty footer parts when you create a watermark, but its not necessary
// + ""
// + ""
// + ""
+ ""
+ ""
+ ""
+ ""
+"";
return (SectPr)XmlUtils.unmarshalString(openXML);
}
private Relationship createHeaderPart(String nameSuffix) throws Exception {
HeaderPart headerPart = new HeaderPart(new PartName("/word/header-" + nameSuffix + ".xml"));
Relationship rel = wordMLPackage.getMainDocumentPart().addTargetPart(headerPart);
setHdr( headerPart);
return rel;
}
private void setHdr(HeaderPart headerPart) throws Exception {
ImagePngPart imagePart = new ImagePngPart(new PartName("/media/background.png"));
imagePart.setBinaryData(image);
Relationship rel = headerPart.addTargetPart(imagePart, AddPartBehaviour.REUSE_EXISTING); // the one image is shared by the 3 header parts
String openXML = ""
+ ""
+ ""
+ ""
+""
+ ""
+ ""
+ ""
+""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+""
+ ""
+ ""
+""
+ ""
+ ""
+""
+""
+""
+""
+"";
Hdr hdr = (Hdr)XmlUtils.unmarshalString(openXML);
headerPart.setJaxbElement(hdr);
}
private byte[] getImage() throws IOException {
// Our utility method wants that as a byte array
java.io.InputStream is = new java.io.FileInputStream(imageFile );
long length = imageFile.length();
// You cannot create an array using a long type.
// It needs to be an int type.
if (length > Integer.MAX_VALUE) {
System.out.println("File too large!!");
}
byte[] bytes = new byte[(int)length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
System.out.println("Could not completely read file "+imageFile.getName());
}
is.close();
return bytes;
}
}