001/*
002 *  CombineTwoPDF
003 *  A simple tool to combine two PDF document's into one larger size pdf
004 *  containing both on the same page.  It is usefull when you have a scan of a
005 *  large doc that could not be scanned into one page. This will take two
006 *  seperate files and produce one file that has a page size twice the size of
007 *  the first docs page size with the original doc merged into the final double
008 *  size pdf doc.
009 *
010 *  $URL: svn://svn.webarts.bc.ca/open/trunk/projects/WebARTS/ca/bc/webarts/tools/pdf/CombineTwoPDF.java $
011 *  $REVISION: $
012 *  Copyright (C) 2003 Tom Gutwin
013 *  tgutwin@webarts.bc.ca
014 *
015 *
016 *  This program is free software; you can redistribute it and/or
017 *  modify it under the terms of the GNU General Public License
018 *  as published by the Free Software Foundation; either version 2
019 *  of the License, or any later version.
020 *
021 *  This program is distributed in the hope that it will be useful,
022 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
023 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
024 *  GNU General Public License for more details.
025 *
026 *  You should have received a copy of the GNU General Public License
027 *  along with the jEdit program; if not, write to the Free Software
028 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
029 */
030
031package ca.bc.webarts.tools.pdf;
032
033import ca.bc.webarts.tools.NativeAppLauncher;
034
035import com.itextpdf.text.*;
036import com.itextpdf.text.pdf.*;
037
038import java.io.*;
039
040
041/**
042 *  A Utility class to combine two PDF document's into one larger size pdf
043 *  containing both on the same page.  It is usefull when you have a scan of a
044 *  large doc that could not be scanned into one page. This will take two
045 *  seperate files and produce one file that has a page size twice the size of
046 *  the first docs page size with the original doc merged into the final double
047 *  size pdf doc.<br>
048 * <br>
049 * Examples:<br>
050 * java ca.bc.webarts.tools.CombineTwoPDF resultFilename file1.pdf file2.pdf<br>
051 * <p><b>It does it all in Java (no native code calls) and its FREE!</b></p>
052 * <br>All PDF document handling is done using the freely available iText PDF
053 * Java library -
054 * <a href="http://www.lowagie.com/iText/">http://www.lowagie.com/iText/</a>
055 * <hr><br>License: GNU GPL<pre>
056 * This program is free software; you can redistribute it and/or modify it
057 * under the terms of the GNU General Public License as published by the Free
058 * Software Foundation; version 2 of the License.
059 *
060 * This program is distributed in the hope that it will be useful, but WITHOUT
061 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
062 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
063 * more details.
064 *
065 * You should have received a copy of the GNU General Public License along
066 * with this program; if not, write to the Free Software Foundation, Inc.,
067 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.</pre>
068 *
069 * @author    TGutwin
070 */
071public class CombineTwoPDF
072{
073
074  /**  Description of the Field */
075  private static String outFileName_ = "combinedOut.pdf";
076
077  /**  Description of the Field */
078  private static String inFileName_ = "infile.pdf";
079  private static String inFileName2_ = "infile2.pdf";
080
081  /**  Description of the Field */
082  private static float cropBorder_ = 0.0f;
083
084  /**  Description of the Field */
085  private static Rectangle outputPageSize_ = PageSize.LETTER;//PageSize.A4;
086
087  /**  The amount to scale a page so it will fit 2Up on the page.
088       The Inital/default scale is based on a 8.5X11 page.**/
089  private static float scale_ = (outputPageSize_.getHeight() / 2.0f) / (outputPageSize_.getWidth() - (2.0f * cropBorder_));
090
091  /**  The offset amount to get it placed from the origin of the page.*/
092  private static int vertOffset_ = ((new Float(62.0f * cropBorder_)).intValue());
093  private static int horizOffset_ = ((new Float(62.0f * cropBorder_)).intValue());
094
095  /**  Description of the Field */
096  private static double rotation_ = Math.toRadians(0);
097
098  /**  Flags if acroreader is auto launched after this process. */
099  private static boolean launchAcroread_ = true;
100
101  /**  Flag for double sided printing binding offset on the long side of the page */
102  private static boolean bindingOffset_ = false;
103  /**
104    * The amount to offset the long side of the page if a double sided print
105    * page offset is requested. (default is 0.75 inches)
106   **/
107  private static float topOffsetAmount_ = ((new Float(62.0f * 0.0f)).intValue());
108  private static String acroCmd_ = "C:\\Progra~1\\Adobe\\Acroba~1.0\\Reader\\AcroRD32.exe";
109  /**  Description of the Field */
110  private static String usage_ ="SYNTAX: CombineTwoPDF resultFilename file1.pdf"+
111                              " file2.pdf [horizoffset vertoffset]\nThe "+
112                              "offsets apply to the placement of the 2ndpage only";
113
114
115  /**
116   *  The main program for the class.<br>It should be called with 3
117   * parameters specifying the Resultant Combined PDF file and the 2 files to
118   * combine.<br>
119   * <br>
120   * Examples:<br>
121   * java ca.bc.webarts.tools.CombineTwoPDF resultFilename file1.pdf file2.pdf<br>
122   *
123   * @param  args  The command line arguments
124   */
125  public static void main(String[] args)
126  {
127
128    if (args.length >2 &&
129        args[1].endsWith(".pdf") &&
130        args[2].endsWith(".pdf"))
131    {
132      if (args.length >3)
133        horizOffset_ = new Float(62.0f * (new Float(args[3])).floatValue()).intValue();
134      if (args.length >4)
135        vertOffset_ = new Float(62.0f * (new Float(args[4])).floatValue()).intValue();
136      inFileName_ = args[1];
137      inFileName2_ = args[2];
138      outFileName_ = args[0];
139    }
140    else
141    {
142      System.out.println("Filename error: ");
143      System.out.println(usage_);
144      System.exit(1);
145    }
146
147    try
148    {
149      // we create a reader for a certain document
150      System.out.println("Reading: " + inFileName_);
151      PdfReader reader = new PdfReader(inFileName_);
152      System.out.println("       :  Rotated = " + reader.getPageRotation(1));
153
154      // we retrieve the total number of pages
155      int numPages = reader.getNumberOfPages();
156      //System.out.println("Preformating a " + numPages +
157      //    " page PDF file for 2Up display. (scale=" + scale_ + "  offset=" + vertOffset_ + ")");
158
159      float width = reader.getPageSize(1).getWidth();
160      float height = reader.getPageSize(1).getHeight();
161
162      // step 1: creation of a document-object
163      System.out.println("New Document Size: =" + width *2.0f+" h="+height);
164      float newWidth = width;
165      float newHeight = 2.0f * height;
166      if (reader.getPageRotation(1) == 90)
167      {
168        newWidth = height;
169        newHeight = 2.0f * width;
170      }
171      Document document =
172          new Document(
173          new Rectangle(newWidth , newHeight), // these are doubled so the combined docs fit
174      0, 0, 0, 0);// Margins: left, right,top, bottom
175
176      // step 2: we create a writer that listens to the document
177      System.out.println("Writing: " + outFileName_);
178      FileOutputStream outFileStream = new FileOutputStream(outFileName_);
179      PdfWriter writer = PdfWriter.getInstance(document, outFileStream);
180
181      // step 3: we open the document
182      document.open();
183
184      // step 4: calculate the new scaling / layout postion
185      PdfContentByte cb = writer.getDirectContent();
186      System.out.println("There are " + numPages +
187          " pages in the document.");
188      System.out.println("Only the 1st page will be used");
189      int currentPage = 0;
190
191      /*
192       *  step 5: Start Copying the pages to the new Doc (in 2Up format)
193       */
194      /*
195       *  ******* ******************************************************
196       */
197      System.out.println("Page offset= -" +vertOffset_);
198      document.newPage();
199      // Calculate the Transfor parameters to use given the scale and postion
200      scale_ = 1.0f;
201      rotation_ = Math.toRadians(360-reader.getPageRotation(1));
202      float cosRotation = (new Float(Math.cos(rotation_))).floatValue();
203      float sinRotation = (new Float(Math.sin(rotation_))).floatValue();
204      float a = scale_ * cosRotation;
205      float b = scale_ * sinRotation;
206      float c = -1.0f * scale_ * sinRotation;
207      float d = scale_ * cosRotation;
208      //System.out.println("a= " +a);
209      //System.out.println("b= " +b);
210      //System.out.println("c= " +c);
211      //System.out.println("d= " +d);
212
213      // add the 1st doc page
214      PdfImportedPage firstPage = writer.getImportedPage(reader, 1);
215      cb.addTemplate(firstPage, a, b, c, d, 0, newHeight);
216
217      // add the 2nd doc page
218      reader = new PdfReader(inFileName2_);
219      PdfImportedPage secondPage = writer.getImportedPage(reader, 1);
220      cb.addTemplate(secondPage, a, b, c, d, horizOffset_,  height - vertOffset_);
221
222      // step 6: we close the document
223      document.close();
224
225      // optional launch the acroreader
226      if (launchAcroread_)
227      {
228        System.out.println("Launching acroread " + outFileName_);
229        String[] appArgs = {(new File(outFileName_)).getAbsolutePath()};
230        new NativeAppLauncher(acroCmd_, appArgs);
231      }
232    }
233    catch (Exception de)
234    {
235      de.printStackTrace();
236    }
237  }
238}
239