001/*
002 *  TwoUpPDF
003 *  a simple tool to format a PDF document's pages as 2Up pages that have been
004 *  scaled/maximized for readablity when 2Up.
005 *
006 *  $URL: svn://svn.webarts.bc.ca/open/trunk/projects/WebARTS/ca/bc/webarts/tools/pdf/CropRotatePDF.java $
007 *  $REVISION: $
008 *  Copyright (C) 2003 Tom Gutwin
009 *  tgutwin@webarts.bc.ca
010 *
011 *
012 *  This program is free software; you can redistribute it and/or
013 *  modify it under the terms of the GNU General Public License
014 *  as published by the Free Software Foundation; either version 2
015 *  of the License, or any later version.
016 *
017 *  This program is distributed in the hope that it will be useful,
018 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
019 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
020 *  GNU General Public License for more details.
021 *
022 *  You should have received a copy of the GNU General Public License
023 *  along with the jEdit program; if not, write to the Free Software
024 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
025 */
026
027package ca.bc.webarts.tools.pdf;
028
029import ca.bc.webarts.tools.NativeAppLauncher;
030
031import com.itextpdf.text.Document;
032import com.itextpdf.text.PageSize;
033import com.itextpdf.text.Rectangle;
034import com.itextpdf.text.pdf.PdfContentByte;
035import com.itextpdf.text.pdf.PdfImportedPage;
036import com.itextpdf.text.pdf.PdfReader;
037import com.itextpdf.text.pdf.PdfWriter;
038
039import java.io.File;
040import java.io.FileOutputStream;
041
042
043/**
044 *  A tool to manipulate PDF files by cropping each page by the specified
045 *  amounts.
046 *
047 * @author    tgutwin
048 */
049public class CropRotatePDF
050{
051
052  /**  Description of the Field */
053  private static String outFileName_ = "CroppedOutput.pdf";
054  /**  Description of the Field */
055  private static String inFileName_ = "infile.pdf";
056  /**  Description of the Field */
057  private static float leftCropBorder_ = 0.0f;
058  /**  Description of the Field */
059  private static float rightCropBorder_ = 0.0f;
060  /**  Description of the Field */
061  private static float topCropBorder_ = 0.0f;
062  /**  Description of the Field */
063  private static float bottomCropBorder_ = 0.0f;
064  /**  Description of the Field */
065  private static float scale_ = (11.0f / 2.0f) /
066                                (8.5f - (leftCropBorder_ + rightCropBorder_));
067  /**  Description of the Field */
068  private static int offset_ = 0;
069  /**  Description of the Field */
070  private static double rotation_ = Math.toRadians(270);
071  /**  Description of the Field */
072  private static Rectangle outputPageSize_ = PageSize.LETTER;//PageSize.A4;
073  /**  Description of the Field */
074  private static boolean launchAcroread_ = false;
075  /**  Description of the Field */
076  private static boolean doTheScale_ = false;
077  /**  Description of the Field */
078  private static String acroCmd_ = "/home/tgutwin/bin/acro";
079  /**  Description of the Field */
080  private static String usage_ = "SYNTAX: CropRotatePDF [leftPageCrop] [rightPageCrop] [topPageCrop] [bottomPageCrop] PDFFilename\n" +
081      "        where pageCrop is in inches";
082
083
084  /**
085   *  The main program for the CropPDF class
086   *
087   * @param  args  The command line arguments
088   */
089  public static void main(String[] args)
090  {
091    boolean validParms = false;
092
093    switch (args.length)
094    {
095        case (1):
096          if (args[0].endsWith(".pdf"))
097          {
098            validParms = true;
099          }
100          break;
101        case (2):
102          try
103          {
104            leftCropBorder_ = Float.parseFloat(args[0]);
105            if (args[args.length - 1].endsWith(".pdf"))
106            {
107              validParms = true;
108            }
109          }
110          catch (NumberFormatException numEx)
111          {
112            System.out.println("Left Crop Size error: ");
113            System.out.println(usage_);
114            System.exit(1);
115          }
116          break;
117        case (3):
118          try
119          {
120            leftCropBorder_ = Float.parseFloat(args[0]);
121            rightCropBorder_ = Float.parseFloat(args[1]);
122            if (args[args.length - 1].endsWith(".pdf"))
123            {
124              validParms = true;
125            }
126          }
127          catch (NumberFormatException numEx)
128          {
129            System.out.println("Crop Size error: ");
130            System.out.println(usage_);
131            System.exit(1);
132          }
133          break;
134        case (4):
135          try
136          {
137            leftCropBorder_ = Float.parseFloat(args[0]);
138            rightCropBorder_ = Float.parseFloat(args[1]);
139            topCropBorder_ = Float.parseFloat(args[2]);
140            if (args[args.length - 1].endsWith(".pdf"))
141            {
142              validParms = true;
143            }
144          }
145          catch (NumberFormatException numEx)
146          {
147            System.out.println("Crop Size error: ");
148            System.out.println(usage_);
149            System.exit(1);
150          }
151          break;
152        case (5):
153          try
154          {
155            leftCropBorder_ = Float.parseFloat(args[0]);
156            rightCropBorder_ = Float.parseFloat(args[1]);
157            topCropBorder_ = Float.parseFloat(args[2]);
158            bottomCropBorder_ = Float.parseFloat(args[3]);
159            if (args[args.length - 1].endsWith(".pdf"))
160            {
161              validParms = true;
162            }
163          }
164          catch (NumberFormatException numEx)
165          {
166            System.out.println("Crop Size error: ");
167            System.out.println(usage_);
168            System.exit(1);
169          }
170          break;
171        default:
172          System.out.println("Commandline parameter error: ");
173          System.out.println(usage_);
174          System.exit(1);
175    }
176
177    /*
178     *  Parms are now parsed.... start the transform/crop
179     */
180    if (validParms)
181    {
182      inFileName_ = args[args.length - 1];
183      outFileName_ = args[args.length - 1].substring(
184          0, args[args.length - 1].length() - 4) + "-Crop.pdf";
185      try
186      {
187        // we create a reader for a certain document
188        System.out.println("Reading: " + inFileName_);
189        PdfReader reader = new PdfReader(inFileName_);
190
191        // The next two are swapped to rotate the resultant page
192        float width_DPI = reader.getPageSize(1).getHeight();
193        float height_DPI = reader.getPageSize(1).getWidth();
194        float width = width_DPI / 72.0f;
195        float height = height_DPI / 72.0f;
196
197        if (doTheScale_)
198        {
199          scale_ = (width) / (width - (leftCropBorder_ + rightCropBorder_));
200        }
201        else
202        {
203          scale_ = 1.0f;
204        }
205
206        // we retrieve the total number of pages
207        int numPages = reader.getNumberOfPages();
208        System.out.println("Cropping " + numPages + "-" + width + "x" + height +
209            " pages by (left=" + leftCropBorder_ + " right=" + rightCropBorder_ +
210            " Top=" + topCropBorder_ + " bottom=" + bottomCropBorder_ +
211            " scale=" + scale_ + "  offset=" + offset_ + ")");
212
213        // step 1: creation of a document-object
214        Rectangle newPageSize = null;
215        if (doTheScale_)
216        {
217          newPageSize = reader.getPageSize(1);
218        }
219        else
220        {
221          newPageSize = new Rectangle(
222              width_DPI - (leftCropBorder_ + rightCropBorder_) * 72.0f,
223              height_DPI - (topCropBorder_ + bottomCropBorder_) * 72.0f);
224        }
225
226        Document document =
227            new Document(newPageSize, 0, 0, 0, 0);// Margins: left, right,top, bottom
228
229        // step 2: we create a writer that listens to the document
230        System.out.println("Writing: " + outFileName_);
231        FileOutputStream outFileStream = new FileOutputStream(outFileName_);
232        PdfWriter writer = PdfWriter.getInstance(document, outFileStream);
233
234        // step 3: we open the document
235        document.open();
236
237        // step 4: calculate the new scaling / layout postion
238        PdfContentByte cb = writer.getDirectContent();
239        System.out.println("There are " + numPages +
240            " pages in the document. w="+newPageSize.getWidth()+" h="+newPageSize.getHeight());
241        PdfImportedPage leftPage;
242        PdfImportedPage rightPage;
243        int currentPage = 0;
244
245        // Calculate the Transfor parameters to use given the scale and postion
246        float cosRotation = (new Float(Math.cos(rotation_))).floatValue();
247        float sinRotation = (new Float(Math.sin(rotation_))).floatValue();
248        float a = scale_ * cosRotation;
249        float b = scale_ * sinRotation;
250        float c = -1.0f * scale_ * sinRotation;
251        float d = scale_ * cosRotation;
252        //System.out.println("a= " +a);
253        //System.out.println("b= " +b);
254        //System.out.println("c= " +c);
255        //System.out.println("d= " +d);
256
257        /*
258         *  step 5: Start Copying the pages to the new Doc
259         */
260        /*
261         *  ******* ******************************************************
262         */
263        while (currentPage < numPages)
264        {
265          document.newPage();
266          leftPage = writer.getImportedPage(reader, ++currentPage);
267          cb.addTemplate(leftPage, a, b, c, d, 0, newPageSize.getHeight());
268        }
269
270        // step 6: we close the document
271        document.close();
272        // optional launch the acroreader
273        if (launchAcroread_)
274        {
275          System.out.println("Launching acroread " + outFileName_);
276          String[] appArgs = {(new File(outFileName_)).getAbsolutePath()};
277          new NativeAppLauncher(acroCmd_, appArgs);
278        }
279
280      }
281      catch (Exception de)
282      {
283        de.printStackTrace();
284      }
285    }
286    else
287    {
288    }
289  }
290}
291