Merge your PDF pages with a background letterhead, form, or watermark.
Sometimes it makes sense to divide document creation into layers. For example, you need to create an invoice's background form, with its logo and rules, only once. You can create the invoice data dynamically as needed and then superimpose it on this form to yield the final invoice.
Perform this final merge in Java with iText, or elsewhere with our command-line pdftk [Hack #79], producing the results in Figure 6-18.
iText (http://www.lowagie.com/iText/) is a powerful library for creating and manipulating PDF. The following Java program uses iText to apply one watermark PDF page to every page in a document. This watermark page can be any PDF page, such as a company letterhead design or an invoice form. The watermark will appear as though it is behind each page's content. Compile and run this program, or use its code in your Java application.
/* watermark_pdf, version 1.0 http://www.pdfhacks.com/watermark/ place a single "watermark" PDF page "underneath" all pages of the input document after compiling, invoke from the command line like this: java -classpath ./itext-paulo.jar:. \ watermark_pdf doc.pdf watermark.pdf output.pdf only the first page of watermark.pdf is used */ import java.io.*; import com.lowagie.text.*; import com.lowagie.text.pdf.*; public class watermark_pdf { public static void main( String[] args ) { if( args.length== 3 ) { try { // the document we're watermarking PdfReader document= new PdfReader( args[0] ); int num_pages= document.getNumberOfPages( ); // the watermark (or letterhead, etc.) PdfReader mark= new PdfReader( args[1] ); Rectangle mark_page_size= mark.getPageSize( 1 ); // the output document PdfStamper writer= new PdfStamper( document, new FileOutputStream( args[2] ) ); // create a PdfTemplate from the first page of mark // (PdfImportedPage is derived from PdfTemplate) PdfImportedPage mark_page= writer.getImportedPage( mark, 1 ); for( int ii= 0; ii< num_pages; ) { // iterate over document's pages, adding mark_page as // a layer 'underneath' the page content; scale mark_page // and move it so that it fits within the document's page; // if document's page is cropped, this scale might // not be small enough ++ii; Rectangle doc_page_size= document.getPageSize( ii ); float h_scale= doc_page_size.width( )/mark_page_size.width( ); float v_scale= doc_page_size.height( )/mark_page_size.height( ); float mark_scale= (h_scale< v_scale) ? h_scale : v_scale; float h_trans= (float)((doc_page_size.width( )- mark_page_size.width( )* mark_scale)/2.0); float v_trans= (float)((doc_page_size.height( )- mark_page_size.height( )* mark_scale)/2.0); PdfContentByte contentByte= writer.getUnderContent( ii ); contentByte.addTemplate( mark_page, mark_scale, 0, 0, mark_scale, h_trans, v_trans ); } writer.close( ); } catch( Exception ee ) { ee.printStackTrace( ); } } else { // input error System.err.println("arguments: in_document in_watermark out_pdf_fn"); } } }
To create a command-line Java program, copy the preceding code into a file named watermark_pdf.java. Then, compile watermark_pdf.java using javac, setting the classpath to the name and location of your iText jar:
javac -classpath ./itext-paulo.jar watermark_pdf.java
Finally, invoke watermark_pdf to apply the first page of form.pdf to every page of invoice.pdf to create watermarked.pdf, like so:
java -classpath ./itext-paulo.jar :. \ watermark_pdf invoice.pdf form.pdf watermarked.pdf
pdftk packs iText's power into a standalone program. Apply a single PDF page to the background of an entire document like so:
pdftk mydoc.pdf output mydoc.marked.pdf background watermark.pdf
pdftk will use the first page of watermark.pdf, if it has more than one page. You can combine this background option with additional input operations (such as assembling PDFs [Hack #51] ) and other output options (such as encryption [Hack #52] ).