AWARE SYSTEMS
TIFF and LibTiff Mail List Archive

2006.08.31 12:48 "[Tiff] Patch for enhanced version of tiff2ps", by Richard Nolde

I recently posted a new version of tiff2ps.c to the bugzilla forum on the libtiff site, but I have been advised that members of the tiff list might also wish to see it. This version adds support for rotation of images by 90,180,270 or "auto" which chooses portrait or landscape orientation and rotates the image accordingly to fit the specified page size. Added the ability to produce multiple images constrained by a maximum width (but not at the same time as using the maximum page height already present) from a single image, in effect tiling the image into a series of images of that width. The PlaceImage routine has been modified to support image sizes smaller or larger than the physical page size while still preserving the aspect ratio. There are still a few unsupported combinations in the tiling option, but the code has been in production use for over a year at my company.

To save space, I am only including a patch file rather than the entire source code here. I can supply the full source if that would be helpful. This patch applies against the version of libtiff distributed as an RPM for Linux IA32, or POWER64 (AIX on IBM Pseries) with revisions 3.7.2 or 3.8.2. I have seen a bugzilla report that there is a problem with the bounding box size not being correctly set in the current release, and I do not think that this patch addresses that issue yet. Recent testing of this versions suggests that the described bug is still present in this patched version but I have not had time to get back to it to check.

If my current work on a tiffcrop utility pans out, I may develop an option for tiff2ps that actually crops the image before writing it out to postscript as this would make for much smaller file sizes with large images that are tiled using the -W or -H option. The current code appears to rely on the Postscript mask operator to do the masking rather than removing the unwanted parts of the image from the file.

As always, comments and corrections are welcome.

Richard Nolde

--- tools/tiff2ps.c.orig        2006-07-14 16:35:54.000000000 -0600
+++ tools/tiff2ps.c     2006-07-21 12:39:45.000000000 -0600
@@ -38,9 +38,27 @@
 
 #include "tiffio.h"
 
+/* #define DEBUG */
 /*
  * Revision history
  *
+ * 2005-June-3
+ *    Richard Nolde: Added support for rotations of 90, 180, 270
+ *    and auto using -r <90|180|270|auto>.  Auto picks the best
+ *    fit for the image on the specified paper size (eg portrait
+ *    or landscape) if -h or -w is specified. Rotation is in
+ *    degrees counterclockwise since that is how Postscript does
+ *    it.  Auto rotates 90 degrees ccw to produce landscape.
+ *
+ *    Added maxPageWidth option using -W flag. MaxPageHeight and
+ *    MaxPageWidth are mutually exclusive since the aspect ratio
+ *    cannot be maintained if you set both.
+ *    Rewrote PlaceImage to allow maxPageHeight and maxPageWidth
+ *    options to work with values smaller or larger than the
+ *    physical paper size and still preserve the aspect ratio.
+ *    This is accomplished by creating multiple pages across
+ *    as well as down if need be.
+ *
  * 2001-Mar-21
  *    I (Bruce A. Mallett) added this revision history comment ;)
  *

@@ -106,6 +124,10 @@
 #define FALSE 0
 #endif

+#define HORIZONTAL 1
+#define VERTICAL 2
+
+

 int    ascii85 = FALSE;                /* use ASCII85 encoding */
 int    interpolate = TRUE;             /* interpolate level2 image */
 int    level2 = FALSE;                 /* generate PostScript level 2 */
@@ -115,9 +137,11 @@
 int    PSduplex = FALSE;               /* enable duplex printing */
 int    PStumble = FALSE;               /* enable top edge binding */
 int    PSavoiddeadzone = TRUE;         /* enable avoiding printer deadzone */
-double maxPageHeight = 0;              /* maximum size to fit on page */
+double maxPageHeight = 0;              /* maximum height to select from image and print per page */
+double maxPageWidth  = 0;              /* maximum width  to select from image and print per page */
 double splitOverlap = 0;               /* amount for split pages to overlag */
-int    rotate = FALSE;                 /* rotate image by 180 degrees */
+int    rotate = FALSE;                 /* rotate image by angle 90, 180, 270 degrees */
+int    rotation = 0;                   /* optional value for rotation angle */
 char   *filename;                      /* input filename */
 int    useImagemask = FALSE;           /* Use imagemask instead of image operator */
 uint16 res_unit = 0;                   /* Resolution units: 2 - inches, 3 - cm */

@@ -164,7 +188,7 @@
        extern int optind;
        FILE* output = stdout;

-       while ((c = getopt(argc, argv, "b:d:h:H:L:i:w:l:o:O:acelmrxyzps1238DT")) != -1)
+       while ((c = getopt(argc, argv, "b:d:h:H:W:L:i:w:l:o:O:r:acelmxyzps1238DT")) != -1)
                switch (c) {
                case 'b':
                        bottommargin = atof(optarg);
@@ -195,6 +219,10 @@
                        maxPageHeight = atof(optarg);
                        if (pageHeight==0) pageHeight = maxPageHeight;
                        break;
+               case 'W':
+                       maxPageWidth = atof(optarg);
+                       if (pageWidth==0) pageWidth = maxPageWidth;
+                       break;
                case 'L':
                        splitOverlap = atof(optarg);
                        break;
@@ -224,6 +252,21 @@
                        break;
                case 'r':
                        rotate = TRUE;
+                        if (strcmp (optarg, "auto") == 0)
+                          rotation = 0;
+                        else
+                         rotation = atoi(optarg);
+                        switch (rotation)
+                          {
+                         case   0:
+                          case  90:
+                          case 180:
+                          case 270:
+                           break;
+                         default:
+                            fprintf (stderr, "Rotation angle must be 90, 180, 270 (degrees ccw) or auto\n");
+                           exit (-2);
+                         }
                        break;
                case 's':
                        printAll = FALSE;
@@ -463,74 +506,242 @@
  * pagewidth & pageheight are inches
  */
 int
-PlaceImage(FILE *fp, double pagewidth, double pageheight,
-          double imagewidth, double imageheight, int splitpage,
-          double lm, double bm, int cnt)
-{
+PlaceImage(TIFF *tif, FILE *fp, int *npages, uint32 w, uint32 h,
+           double pagewidth, double pageheight,
+          double imagewidth, double imageheight,
+           int splitpage, double lm, double bm, int cnt)
+{
+        int    i       = 0;
+        int    ximages = 0;
+        int    yimages = 0;
+        int    splitaxis = 0;
        double xtran = 0;
        double ytran = 0;
        double xscale = 1;
        double yscale = 1;
-       double left_offset = lm * PS_UNIT_SIZE;
-       double bottom_offset = bm * PS_UNIT_SIZE;
-       double subimageheight;
-       double splitheight;
-       double overlap;
+       double left_margin    = 0;
+       double bottom_margin  = 0;
+       double left_offset    = lm * PS_UNIT_SIZE;
+       double bottom_offset  = bm * PS_UNIT_SIZE;
+       double splitwidth     = 0;
+       double splitheight    = 0;
+       double subimageheight = 0;
+       double subimagewidth  = 0;
+       double overlap        = 0;
+       double overlapspace   = 0;
 
-       pagewidth *= PS_UNIT_SIZE;
+       pagewidth  *= PS_UNIT_SIZE;
        pageheight *= PS_UNIT_SIZE;
 
-       if (maxPageHeight==0)
-               splitheight = 0;
-       else
-               splitheight = maxPageHeight * PS_UNIT_SIZE;
-       overlap = splitOverlap * PS_UNIT_SIZE;
+       splitheight = maxPageHeight * PS_UNIT_SIZE;
+       splitwidth  = maxPageWidth  * PS_UNIT_SIZE;
+       overlap     = splitOverlap  * PS_UNIT_SIZE;
+
+#ifdef DEBUG
+        fprintf (stderr, "-------------------------\n");
+       fprintf (stderr, "Page Width: %3.2f, Page Height: %3.2f Image Width: %3.2f Image Height: %3.2f\n",
+                 pagewidth, pageheight, imagewidth, imageheight);
+        fprintf (stderr, "Split Height: %3.2f, Split Width: %3.2f, Overlap: %3.2f, Pagesplits: %d\n", 
+                 splitheight, splitwidth, overlap, splitpage);
+#endif
+        /* These have to be mutually exclusive to maintain the aspect ratio */
+        if (splitheight != 0)
+          splitaxis = VERTICAL;
+        else {
+           if (splitwidth != 0)
+             splitaxis = HORIZONTAL;
+           else {
+             fprintf (stderr, "You must specify either a maximum page height or width\n");
+             return (0);
+           }
+        }

-       /*
-        * WIDTH:
-        *      if too wide, scrunch to fit
-        *      else leave it alone
-        */

-       if (imagewidth <= pagewidth) {
-               xscale = imagewidth;
-       } else {
-               xscale = pagewidth;
-       }
+        if (splitaxis == VERTICAL) {
+         if (imageheight <= splitheight) {
+           /* Simple case, no splitting or scaling for image height */
+           yscale = imageheight;
+           ytran = pageheight - imageheight;
+         } else { /* imageheight > splitheight */
+             subimageheight = imageheight - ((splitheight - overlap) * splitpage);
+
+              yscale = imageheight * (pageheight / splitheight);
+             ytran  = pageheight - subimageheight * (pageheight / splitheight);
+           
+              if (subimageheight > splitheight) {
+               splitpage++;
+             } else {
+                 splitpage = 0;
+                 } 
+         }
+         bottom_offset += ytran / (cnt?2:1);
+          left_margin = left_offset / (cnt ? 2 : 1);
+
+         /*
+           * WIDTH: We can't rescale height based on width so we need to make multiple
+           *   pages from each horizontal segment if the image is wider than pagewidth
+           */
+
+          ximages = ceil (imagewidth / pagewidth);
+          overlapspace = (ximages - 1) * overlap;
+#ifdef DEBUG
+         fprintf (stderr, "Image Width / Page Width: %3.2f, Ximages: %d, Overlap %3.2f, \n", 
+                  (imagewidth / pagewidth), ximages, overlapspace);
 
-       /* HEIGHT:
-        *      if too long, scrunch to fit
-        *      if too short, move to top of page
-        */
-       if (imageheight <= pageheight) {
-               yscale = imageheight;
-               ytran = pageheight - imageheight;
-       } else if (imageheight > pageheight &&
-               (splitheight == 0 || imageheight <= splitheight)) {
-               yscale = pageheight;
-       } else /* imageheight > splitheight */ {
-               subimageheight = imageheight - (pageheight-overlap)*splitpage;
-               if (subimageheight <= pageheight) {
-                       yscale = imageheight;
-                       ytran = pageheight - subimageheight;
-                       splitpage = 0;
-               } else if ( subimageheight > pageheight && subimageheight <= splitheight) {
-                       yscale = imageheight * pageheight / subimageheight;
-                       ytran = 0;
-                       splitpage = 0;
-               } else /* sumimageheight > splitheight */ {
-                       yscale = imageheight;
-                       ytran = pageheight - subimageheight;
-                       splitpage++;
-               }
+         fprintf (stderr, "Image Width plus overlap: %3.2f Printable width: %3.2f\n", 
+                   imagewidth + overlapspace, ximages * pagewidth);
+#endif
+          if (((imagewidth + overlapspace) * (pageheight / splitheight)) > (ximages * pagewidth)) {
+            ximages++;
+            overlapspace += overlap;
+#ifdef DEBUG
+           fprintf (stderr, "Adjusted Image Width plus overlap: %3.2f Printable width: %3.2f\n", 
+                   imagewidth + overlapspace, ximages * pagewidth);
+#endif
+         }
+
+          xscale = (imagewidth + overlapspace) * (pageheight / splitheight);
+         if (imagewidth <= pagewidth) {
+            left_offset = left_margin;
+            bottom_offset = bottom_margin;
+           fprintf(fp, "%f %f translate\n", left_offset, bottom_offset);
+           fprintf(fp, "%f %f scale\n", xscale, yscale);
+#ifdef DEBUG
+           fprintf (stderr, "Translate: %3.2f,  %3.2f, Scale: %3.2f,  %3.2f\n",
+                  left_offset, bottom_offset, xscale, yscale);
+#endif
+         } else {
+            for (i = 0; i < ximages; i++) {
+              xtran = i * (pagewidth - ((i > 0) ? overlap : 0));
+             left_offset = -xtran + left_margin;
+
+             fprintf(fp, "%f %f translate\n", left_offset, bottom_offset);
+             fprintf(fp, "%f %f scale\n", xscale, yscale);
+
+#ifdef DEBUG
+             fprintf (stderr, "Page:   %d\n", *npages);
+             fprintf (stderr, "Translate: %3.2f,  %3.2f, Scale: %3.2f,  %3.2f\n",
+                     left_offset, bottom_offset, xscale, yscale);
+#endif
+              if ( i < (ximages - 1)) {
+               PSpage(fp, tif, w, h);
+               fprintf(fp, "end\n");
+               fprintf(fp, "grestore\n");
+               fprintf(fp, "showpage\n");
+               (*npages)++;
+               fprintf(fp, "%%%%Page: %d %d\n", (*npages), (*npages));
+               fprintf(fp, "gsave\n");
+               fprintf(fp, "100 dict begin\n");
+               }
+           }
+         }
+        } else {  /* splitaxis is HORIZONTAL */
+          ximages = ceil (imagewidth / splitwidth);
+          overlapspace = (ximages - 1) * overlap;
+#ifdef DEBUG
+         fprintf (stderr, "Image Width / Split Width: %3.2f, Ximages: %d, Overlap %3.2f, \n", 
+                  (imagewidth / splitwidth), ximages, overlapspace);
+
+         fprintf (stderr, "Image Width plus overlap: %3.2f Printable width: %3.2f\n", 
+                   imagewidth + overlapspace, ximages * pagewidth);
+#endif
+          if (((imagewidth + overlapspace) * (pagewidth / splitwidth)) > (ximages * pagewidth)) {
+            ximages++;
+            overlapspace += overlap;
+#ifdef DEBUG
+           fprintf (stderr, "Adjusted Image Width plus overlap: %3.2f Printable width: %3.2f\n", 
+                   imagewidth + overlapspace, ximages * pagewidth);
+#endif
+         }
+         if (ximages == 1) {
+           /* Simple case, no splitting or scaling for image width */
+           xscale = imagewidth;
+           xtran = 0;
+            splitpage = 0;
+         } else {
+#ifdef DEBUG
+              fprintf (stderr, "Image exceeds requested split width: %3.2f\n", splitwidth);
+#endif
+             subimagewidth  = imagewidth  - ((splitwidth - overlap) * splitpage);
+
+              xscale = imagewidth * (pagewidth / splitwidth);
+             xtran  = imagewidth - (subimagewidth * (pagewidth / splitwidth));
+
+              splitheight = pageheight;
+             subimageheight = imageheight - ((splitheight - overlap) * splitpage);
+#ifdef DEBUG
+             fprintf (stderr, "\nSubimage height is %3.2f\n", subimageheight);
+#endif
+              yscale = (imageheight + overlapspace);
+             ytran  = pageheight - subimageheight  + (overlapspace * (pagewidth / splitwidth));
+
+              if (subimageheight > splitheight) {
+               splitpage++;
+             } else {
+                 splitpage = 0;
+                 } 
+         }
+          bottom_margin = bottom_offset / (cnt ? 2 : 1);
+         bottom_offset = bottom_margin + ytran;
+          left_margin = left_offset / (cnt ? 2 : 1);
+#ifdef DEBUG
+          fprintf (stderr, "Imagewidth: %3.2f, Subimage width: %3.2f, Splitpage: %d\n",
+                           imagewidth, subimagewidth, splitpage);
+          fprintf (stderr, "Bottom offset is %3.2f\n", bottom_offset);
+#endif
+         if (imagewidth <= pagewidth) {
+            left_offset = left_margin;
+            bottom_offset = bottom_margin;
+           fprintf(fp, "%f %f translate\n", left_offset, bottom_offset);
+           fprintf(fp, "%f %f scale\n", xscale, yscale);
+#ifdef DEBUG
+           fprintf (stderr, "Translate: %3.2f,  %3.2f, Scale: %3.2f,  %3.2f\n",
+                  left_offset, bottom_offset, xscale, yscale);
+#endif
+         } else {
+#ifdef DEBUG
+             fprintf (stderr, "Image will be spread across %d horizontal images\n", ximages);
+#endif
+              for (i = 0; i < ximages; i++) {
+                xtran = i * (pagewidth - ((i > 0) ? overlap : 0));
+               left_offset = left_margin - xtran;
+               fprintf(fp, "%f %f translate\n", left_offset, bottom_offset);
+               fprintf(fp, "%f %f scale\n", xscale, yscale);
+#ifdef DEBUG
+               fprintf (stderr, "Page:   %d\n", *npages);
+               fprintf (stderr, "Translate: %3.2f,  %3.2f, Scale: %3.2f,  %3.2f\n",
+                     left_offset, bottom_offset, xscale, yscale);
+#endif
+                if ( i < (ximages - 1)) {
+                 PSpage(fp, tif, w, h);
+                 fprintf(fp, "end\n");
+                 fprintf(fp, "grestore\n");
+                 fprintf(fp, "showpage\n");
+                 (*npages)++;
+                 fprintf(fp, "%%%%Page: %d %d\n", (*npages), (*npages));
+                 fprintf(fp, "gsave\n");
+                 fprintf(fp, "100 dict begin\n");
+               }
+             }
+         }
        }
-       
-       bottom_offset += ytran / (cnt?2:1);
-       if (cnt)
-           left_offset += xtran / 2;
-       fprintf(fp, "%f %f translate\n", left_offset, bottom_offset);
-       fprintf(fp, "%f %f scale\n", xscale, yscale);
+
        if (rotate)
-           fputs ("1 1 translate 180 rotate\n", fp);
+           {
+           /* fprintf (stderr, "Rotate not supported at this time\n");
+               return 0;
+           */
+           if (rotation == 180 )
+              {
+             fprintf(fp, "%f %f translate\n", left_offset, bottom_offset);
+             fprintf(fp, "%f %f scale\n", xscale, yscale);
+              }
+            else
+              {
+             fprintf(fp, "%f %f translate\n", bottom_offset, left_offset);
+             fprintf(fp, "%f %f scale\n", yscale, xscale);
+              }
+           fprintf (fp, "1 1 translate %d rotate\n", rotation);
+            }
 
        return splitpage;
 }
@@ -541,10 +752,15 @@
 TIFF2PS(FILE* fd, TIFF* tif,
        double pw, double ph, double lm, double bm, int cnt)
 {
-       uint32 w, h;
-       float ox, oy;
-        double prw, prh;
-       double scale = 1.0;
+       uint32 w = 0, h = 0;
+       float  ox, oy;
+        double maxsource, maxtarget;    /* Used for auto rotations */
+        double hcenter, vcenter;        /* Used for centering */
+        double prw, prh;    /* Original Image width and height in Postscript points */
+       double psw, psh;    /* Scaled image width and height in Postscript points */
+       double xscale, yscale, scale = 1.0;
+       double left_offset = lm * PS_UNIT_SIZE;
+       double bottom_offset = bm * PS_UNIT_SIZE;
        uint32 subfiletype;
        uint16* sampleinfo;
        static int npages = 0;
@@ -554,15 +770,67 @@
                ox = 0;
        if (!TIFFGetField(tif, TIFFTAG_YPOSITION, &oy))
                oy = 0;
-       setupPageState(tif, &w, &h, &prw, &prh);
-
+       /* setupPageState(tif, &w, &h, &prw, &prh); */
        do {
                tf_numberstrips = TIFFNumberOfStrips(tif);
                TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP,
                    &tf_rowsperstrip);
                setupPageState(tif, &w, &h, &prw, &prh);
-               if (!npages)
-                       PSHead(fd, tif, w, h, prw, prh, ox, oy);
+#ifdef DEBUG
+               fprintf (stderr, "\nPixel Width: %4d, Pixel Height: %4d\n"\
+                                 "Original printable area is %3.2f x %3.2f (%3.2f x %3.2f inches)\n",
+                          w, h, prw, prh, prw / 72.0, prh / 72.0);
+#endif
+                if (pw != 0) {
+                    psw = pw * PS_UNIT_SIZE;
+                   if (res_unit == RESUNIT_CENTIMETER)
+                       psw *= 2.54F;
+               }
+                else
+                  psw = prw;
+
+                if (ph != 0) {
+                    psh = ph * PS_UNIT_SIZE;
+                   if (res_unit == RESUNIT_CENTIMETER)
+                       psh *= 2.54F;
+               }
+                else
+                  psh = prh;
+
+                /* auto rotate for best fit */
+                if (rotate && rotation == 0) {
+                  maxsource = (prw >= prh) ? prw : prh;
+                  maxtarget = (psw >= psh) ? psw : psh;
+                  if (((maxsource == prw) && (maxtarget != psw)) ||
+                      ((maxsource == prh) && (maxtarget != psh))) {
+                   rotation = 90;
+                 } 
+               }
+
+                /* scaling depends on rotation and new page size */
+                switch (rotation) {
+                  case   0:  
+                  case 180:
+                    xscale = (psw - left_offset)/prw;
+                    yscale = (psh - bottom_offset)/prh;
+                   if (!npages)
+                     PSHead(fd, tif, w, h, psw, psh, ox, oy);
+                    break;
+                 case  90:
+                  case 270:
+                    xscale = (psw - bottom_offset) /prh;
+                    yscale = (psh - left_offset) /prw;
+                   if (!npages)
+                     PSHead(fd, tif, w, h, psh, psw, oy, ox);
+                    break;
+               }
+#ifdef DEBUG
+                fprintf (stderr, "Adjusted printable area is %6.2f x %6.2f (%3.2f x %3.2f inches)\n",
+                         psw, psh, psw / 72.0, psh / 72.0);
+                fprintf (stderr, "Psw: %6.2f, Prw: %6.2f, X Ratio: %3.2f\n"\
+                                 "Psh: %6.2f, Prh: %6.2f, Y Ratio: %3.2f\n",
+                                 psw, prw, xscale, psh, prh, yscale);
+#endif
                TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE,
                    &bitspersample);
                TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL,
@@ -595,19 +863,6 @@
                        npages++;
                        fprintf(fd, "%%%%Page: %d %d\n", npages, npages);
                        if (!generateEPSF && ( level2 || level3 )) {
-                               double psw, psh;
-                               if (pw != 0.0) {
-                                       psw = pw * PS_UNIT_SIZE;
-                                       if (res_unit == RESUNIT_CENTIMETER)
-                                               psw *= 2.54F;
-                               } else
-                                       psw=rotate ? prh:prw;
-                               if (ph != 0.0) {
-                                       psh = ph * PS_UNIT_SIZE;
-                                       if (res_unit == RESUNIT_CENTIMETER)
-                                               psh *= 2.54F;
-                               } else
-                                       psh=rotate ? prw:prh;
                                fprintf(fd,
        "1 dict begin /PageSize [ %f %f ] def currentdict end setpagedevice\n",
                                        psw, psh);
@@ -617,15 +872,11 @@
                        }
                        fprintf(fd, "gsave\n");
                        fprintf(fd, "100 dict begin\n");
+                        /* N.B. Setting maxPageHeight also sets ph if not set explicitly */
                        if (pw != 0 || ph != 0) {
-                               double psw = pw, psh = ph;
-                               if (!psw)
-                                       psw = prw;
-                               if (!psh)
-                                       psh = prh;
-                               if (maxPageHeight) { /* used -H option */
-                                       split = PlaceImage(fd,psw,psh,prw,prh,
-                                                          0,lm,bm,cnt);
+                               if (maxPageHeight || maxPageWidth)  { /* used -H or -W options */
+                                 split = PlaceImage(tif,fd,&npages,w,h,pw,ph,prw,prh,
+                                    0,lm,bm,cnt);
                                        while( split ) {
                                            PSpage(fd, tif, w, h);
                                            fprintf(fd, "end\n");
@@ -636,37 +887,95 @@
                                                    npages, npages);
                                            fprintf(fd, "gsave\n");
                                            fprintf(fd, "100 dict begin\n");
-                                           split = PlaceImage(fd,psw,psh,prw,prh,
-                                                              split,lm,bm,cnt);
-                                       }
-                               } else {
-                                       double left_offset = lm * PS_UNIT_SIZE;
-                                       double bottom_offset = bm * PS_UNIT_SIZE;
-                                       psw *= PS_UNIT_SIZE;
-                                       psh *= PS_UNIT_SIZE;
-
-                                       /* NB: maintain image aspect ratio */
-                                       scale = psw/prw < psh/prh ?
-                                               psw/prw : psh/prh;
-                                       if (scale > 1.0)
-                                               scale = 1.0;
-                                       if (cnt) {
-                                               bottom_offset +=
-                                                       (psh - prh * scale) / 2;
-                                               left_offset +=
-                                                       (psw - prw * scale) / 2;
+                                           split = PlaceImage(tif,fd,&npages,w,h,pw,ph,prw,prh,
+                                               split,lm,bm,cnt);
                                        }
-                                       fprintf(fd, "%f %f translate\n",
-                                               left_offset, bottom_offset);
-                                       fprintf(fd, "%f %f scale\n",
-                                               prw * scale, prh * scale);
-                                       if (rotate)
-                                               fputs ("1 1 translate 180 rotate\n", fd);
+                               } 
+                                else {
+                                   /* NB: maintain image aspect ratio */
+                                    scale = (xscale < yscale) ? xscale : yscale; 
+                                   if (scale > 1.0)
+                                       scale = 1.0;
+
+                                    /* Adjust offsets for centering */
+                                   if (cnt) {
+                                      switch (rotation) {
+                                       case   90:
+                                        case  270:
+                                           hcenter = (psw - prh * scale) / 2;
+                                           vcenter = (psh - prw * scale) / 2;
+                                            break;
+                                       case    0:
+                                        case  180:
+                                       default:
+                                           hcenter = (psw - prw * scale) / 2;
+                                           vcenter = (psh - prh * scale) / 2;
+                                            break;
+                                     }
+#ifdef DEBUG                                         
+                                    fprintf (stderr, "Left offset: %5.2f Bottom offset: %5.2f\n", hcenter, vcenter);
+#endif
+                                   }
+                                 else 
+                                      hcenter = 0.0, vcenter = 0.0;
+#ifdef DEBUG                                         
+                                 fprintf (stderr, "Pw/Ph are non-zero: Width scaled: %6.2f, Height scaled: %6.3f Rotation: %d\n",
+                                           prw * scale, prh * scale, rotation);
+                                 fprintf (stderr, "Scaling %6.2f %6.2f %d %d translate %d rotate\n",
+                                           prw * scale, prh * scale, 1, 0, rotation);
+#endif
+                                  if (cnt)
+                                    fprintf (fd, "%f %f translate\n", hcenter, vcenter);
+                                  switch (rotation) {
+                                   case 0:
+                                       fprintf (fd, "%f %f scale\n", prw * scale, prh * scale);
+                                        break;
+                                   case 90:
+                                       fprintf (fd, "%f %f scale\n1 0 translate 90 rotate\n", prh * scale, prw * scale);
+                                        break;
+                                    case 180:
+                                       fprintf (fd, "%f %f scale\n1 1 translate 180 rotate\n", prw * scale, prh * scale);
+                                       break;
+                                   case 270:
+                                       fprintf (fd, "%f %f scale\n0 1 translate 270 rotate\n", prh * scale, prw * scale);
+                                       break;
+                                   default:
+                                       fprintf (stderr, "Unsupported angle. No rotation\n");
+                                       fprintf (fd, "%f %f scale\n", prw * scale, prh * scale);
+                                        break;
+                                 }
                                }
                        } else {
-                               fprintf(fd, "%f %f scale\n", prw, prh);
-                               if (rotate)
-                                       fputs ("1 1 translate 180 rotate\n", fd);
+                           if (rotate)
+                              {
+                             /* Width and height have already been enchanged for 90/270 rotations */
+#ifdef DEBUG                                         
+                             fprintf (stderr, "Scaling %3.2f %3.2f %d %d translation %d rotatation\n",
+                                       prw, prh, 1, 0, rotation);
+#endif
+                             switch (rotation) {
+                                case   0:
+                                    fprintf (fd, "%f %f scale\n", prw, prh);
+                                case  90:
+                                    fprintf (fd, "%f %f scale\n1 0 translate 90 rotate\n", prw, prh); 
+                                     break;
+                                 case 180:
+                                    fprintf (fd, "%f %f scale\n1 1 translate 180 rotate\n", prw, prh);
+                                     break;
+                                case 270:
+                                    fprintf (fd, "%f %f scale\n0 1 translate 270 rotate\n", prw, prh); 
+                                     break;
+                                default:
+                                    fprintf (stderr, "Unsupported angle. No rotation\n");
+                                    fprintf( fd, "%f %f scale\n", prw, prh);
+                                     break;
+                                }
+                             }
+                            else
+                             {
+                             fprintf (stderr, "No rotation\n");
+                             fprintf (fd, "%f %f scale\n", prw, prh);
+                             }
                        }
                        PSpage(fd, tif, w, h);
                        fprintf(fd, "end\n");
@@ -730,8 +1039,13 @@
        fprintf(fd, "%%%%DocumentData: Clean7Bit\n");
        fprintf(fd, "%%%%Origin: %ld %ld\n", (long) ox, (long) oy);
        /* NB: should use PageBoundingBox */
-       fprintf(fd, "%%%%BoundingBox: 0 0 %ld %ld\n",
-           (long) ceil(pw), (long) ceil(ph));
+        if (rotate && (rotation == 90 || rotation == 270))
+         fprintf(fd, "%%%%BoundingBox: 0 0 %ld %ld\n",
+           (long) ceil(ph), (long) ceil(pw));
+        else
+          fprintf(fd, "%%%%BoundingBox: 0 0 %ld %ld\n",
+           (long) ceil(pw), (long) ceil(ph));         
+
        fprintf(fd, "%%%%LanguageLevel: %d\n", (level3 ? 3 : (level2 ? 2 : 1)));
        fprintf(fd, "%%%%Pages: (atend)\n");
        fprintf(fd, "%%%%EndComments\n");
@@ -2068,6 +2382,7 @@

 " -h #          assume printed page height is # inches (default 11)",
 " -w #          assume printed page width is # inches (default 8.5)",
 " -H #          split image if height is more than # inches",
+" -W #          split image if width is more than # inches",
 " -L #          overLap split images by # inches",
 " -i #          enable/disable (Nz/0) pixel interpolation (default: enable)",
 " -l #          set the left margin to # inches",
@@ -2075,7 +2390,7 @@
 " -o #          convert directory at file offset #",
 " -O file       write PostScript to file instead of standard output",
 " -p            generate regular PostScript",
-" -r            rotate by 180 degrees",
+" -r # or auto  rotate by 90, 180, 270 degrees or auto",
 " -s            generate PostScript for a single image",
 " -T            print pages for top edge binding",
 " -x            override resolution units as centimeters",