AWARE SYSTEMS
TIFF and LibTiff Mail List Archive

2014.05.21 10:05 "[Tiff] [PATCH] Fix multi-page fax scaling", by Eduardo Robles Elvira

Hello everybody,

Hey I'm new to the list =) I'm Eduardo from Wadobo, a small software development company from Spain. In request from a client, we have created the following patch that we want to adapt as needed (and if possible) to contribute it upstream:

Basically we use libtiff to process fax tiff images. Some fax machines send multiple pages as one very long page. The trick here is to split the page at the correct A4 page boundary and keep the correct aspect ratio of the image.

We have a set of example files and a script to process them as a test case. Ideally, the output of the "test_pdf.sh" script should be the same as the input tiff images but in pdf. The test case can be downloaded from here [1].

I've created two patches, that you can find attached to this email: libtiffcrop-fix.patch and libtiff-correct-fax-scaling.patch:

1. libtiffcrop-fix.patch fixes a small problem in tiffcrop, it seems it was incorrectly using TIFFSetField instead of CopyField.

And in libtiff-correct-fax-scaling.patch we have some other changes:

2. I had to remove a check in main() that didn't allow maxPageWidth to be bigger than pageWidth.

3. in get_subimage_count() I had to comment some lines that were trying to calculate how many pages a subimage would need, because it really needed only one in our test case. This might need some improvement (any ideas?). This is the part of the patch:

+//                  if (pagewidth)

+//                    *ximages = (int)ceil((scale * imagewidth) /

(pagewidth - overlap));    /* Max horz pages needed */

+// else

4. the pagewidth variable was being set as the maxpagewidth instead, which made all the calculations bad. This made sense when the check in point 2 was in place, but not anymore. I've modified it so that pagewidth is set with the specified pagewidth when maxpagewidth is bigger. This part of the patch:

-    *view_height = maxPageHeight * PS_UNIT_SIZE;
+    if (pgheight != 0 && pgheight < maxPageHeight)

+      *view_height = pgheight * PS_UNIT_SIZE;
+    else
+      *view_height = maxPageHeight * PS_UNIT_SIZE;

5.

 * The remaining lines of the patch - in exportMaskedImage() -
basically fix the scaling.

Any and all constructive feedback that can help us get the patch in libtiff is welcome.

Thanks for your time,
--
[1] http://wadobo.com/static/test_fax_pdf.tar.bz2

--

Eduardo Robles Elvira     +34 668 824 393            skype: edulix2
http://www.wadobo.com    it's not magic, it's wadobo!

diff --git a/tools/tiff2ps.c b/tools/tiff2ps.c
index 372230a..6b9b7ba 100644
--- a/tools/tiff2ps.c
+++ b/tools/tiff2ps.c
@@ -414,12 +414,6 @@ main(int argc, char* argv[])
          exit (1);
           }

- }
-
         /* auto rotate requires a specified page width and height */
         if (auto_rotate == TRUE)
           {
@@ -726,9 +720,9 @@ int get_subimage_count(double pagewidth, double pageheight,
                  }
                 else
                  {
- if (pagewidth)

-                   *ximages = (int)ceil((scale * imagewidth) / (pagewidth - overlap));    /* Max horz pages needed */

-                  else
+//                  if (pagewidth)

+//                    *ximages = (int)ceil((scale * imagewidth) / (pagewidth - overlap));    /* Max horz pages needed */

+//                   else
                    *ximages = 1;

                  *yimages = 1;                                                     /* Max vert pages needed */

                  }
@@ -858,6 +852,9 @@ int exportMaskedImage(FILE *fp, double pagewidth, double pageheight,
                 {
                if (splitheight < imageheight) /* More than one vertical image segments */
                  {

+                 /* Intra2net: Keep correct apspect ratio */

+                 xscale = (imagewidth + overlap) * (pageheight / splitheight) * scale;

+
                  xtran = -1.0 * column * (pagewidth - overlap);
                   subimage_height = imageheight - ((splitheight - overlap) * row);

                  ytran  = pageheight - subimage_height * (pageheight / splitheight);

@@ -889,6 +886,14 @@ int exportMaskedImage(FILE *fp, double pagewidth, double pageheight,

                  xtran = 0;
                   }
                 }
+

+            if (imagewidth <= pagewidth) {
+                /* Intra2net: Crop page at the bottom instead of the top (-> output starts at the top).
+                     Only do this in non-page-split mode */
+                if (imageheight <= splitheight) {
+                    ytran = pageheight - imageheight; /* Note: Will be negative for images longer than page size */
+                }
+            }

               bott_offset += ytran / (center ? 2 : 1);
               left_offset += xtran / (center ? 2 : 1);

               break;
@@ -1393,7 +1398,10 @@ int get_viewport (double pgwidth, double pgheight, double pswidth, double psheig
   /* Only one of maxPageHeight or maxPageWidth can be specified */

   if (maxPageHeight != 0)   /* Clip the viewport to maxPageHeight on each page */

     {

-    *view_height = maxPageHeight * PS_UNIT_SIZE;
+    if (pgheight != 0 && pgheight < maxPageHeight)

+      *view_height = pgheight * PS_UNIT_SIZE;
+    else
+      *view_height = maxPageHeight * PS_UNIT_SIZE;

     /*
      * if (res_unit == RESUNIT_CENTIMETER)
      * *view_height /= 2.54F;

@@ -1423,7 +1431,10 @@ int get_viewport (double pgwidth, double pgheight, double pswidth, double psheig

   if (maxPageWidth != 0)   /* Clip the viewport to maxPageWidth on each page */

     {

-    *view_width = maxPageWidth * PS_UNIT_SIZE;
+    if (pgwidth != 0 && pgwidth < maxPageWidth)

+      *view_width = pgwidth * PS_UNIT_SIZE;
+    else
+      *view_width = maxPageWidth * PS_UNIT_SIZE;

     /* if (res_unit == RESUNIT_CENTIMETER)
      *  *view_width /= 2.54F;
      */

--- /home/edulix/tiff-4.0.3/tools/tiffcrop.c    2010-12-14 15:18:28.000000000 +0100

+++ tiff-4.0.3/tools/tiffcrop.c 2014-05-04 16:53:17.249693727 +0200
@@ -6934,7 +6934,7 @@
       TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
       }
     else /* Use the compression from the input file */
- TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
+ CopyField(TIFFTAG_COMPRESSION, compression);
     }

   if (compression == COMPRESSION_JPEG)