Hack 90 Superimpose PDF Pages

figs/expert.gif figs/hack90.gif

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.

Figure 6-18. Document creation split into layers
figs/pdfh_0618.gif


6.18.1 Superimpose Pages in Java with iText

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

6.18.2 Superimpose Pages with pdftk

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] ).