]> git.imager.perl.org - imager.git/blobdiff - tiff.c
change C<allow_partial> to C<allow_incomplete> to match the tag name
[imager.git] / tiff.c
diff --git a/tiff.c b/tiff.c
index 2ac76674f55a80f00cc8280b4706a2fd5afec1d8..8406ca6b5dca1c5fb13065e275ceb97aa34b97bd 100644 (file)
--- a/tiff.c
+++ b/tiff.c
@@ -151,7 +151,7 @@ comp_munmap(thandle_t h, tdata_t p, toff_t off) {
   /* do nothing */
 }
 
-static i_img *read_one_tiff(TIFF *tif) {
+static i_img *read_one_tiff(TIFF *tif, int allow_incomplete) {
   i_img *im;
   uint32 width, height;
   uint16 channels;
@@ -178,6 +178,26 @@ static i_img *read_one_tiff(TIFF *tif) {
   mm_log((1, "i_readtiff_wiol: %stiled\n", tiled?"":"not "));
   mm_log((1, "i_readtiff_wiol: %sbyte swapped\n", TIFFIsByteSwapped(tif)?"":"not "));
 
+  /* separated defaults to CMYK, but if the user is using some strange
+     ink system we can't work out the color anyway */
+  if (photometric == PHOTOMETRIC_SEPARATED && channels >= 4) {
+    /* TIFF can have more than one alpha channel on an image,
+       but Imager can't, only store the first one */
+    
+    channels = channels == 4 ? 3 : 4;
+
+    /* unfortunately the RGBA functions don't try to deal with the alpha
+       channel on CMYK images, at some point I'm planning on expanding
+       TIFF support to handle 16-bit/sample images and I'll deal with
+       it then */
+  }
+
+  /* TIFF images can have more than one alpha channel, but Imager can't
+     this ignores the possibility of 2 channel images with 2 alpha,
+     but there's not much I can do about that */
+  if (channels > 4)
+    channels = 4;
+
   if (photometric == PHOTOMETRIC_PALETTE && bits_per_sample <= 8) {
     channels = 3;
     im = i_img_pal_new(width, height, channels, 256);
@@ -276,6 +296,14 @@ static i_img *read_one_tiff(TIFF *tif) {
       ++row;
     }
     if (row < height) {
+      if (allow_incomplete) {
+        i_tags_setn(&im->tags, "i_lines_read", row);
+      }
+      else {
+        i_img_destroy(im);
+        _TIFFfree(buffer);
+        return NULL;
+      }
       error = 1;
     }
     /* Ideally we'd optimize the palette, but that could be expensive
@@ -362,8 +390,17 @@ static i_img *read_one_tiff(TIFF *tif) {
         uint32 newrows, i_row;
         
         if (!TIFFReadRGBAStrip(tif, row, raster)) {
-          error++;
-          break;
+          if (allow_incomplete) {
+            i_tags_setn(&im->tags, "i_lines_read", row);
+            error++;
+            break;
+          }
+          else {
+            i_push_error(0, "could not read TIFF image strip");
+            _TIFFfree(raster);
+            i_img_destroy(im);
+            return NULL;
+          }
         }
         
         newrows = (row+rowsperstrip > height) ? height-row : rowsperstrip;
@@ -386,7 +423,7 @@ static i_img *read_one_tiff(TIFF *tif) {
   }
   if (error) {
     mm_log((1, "i_readtiff_wiol: error during reading\n"));
-    i_tags_addn(&im->tags, "i_incomplete", 0, 1);
+    i_tags_setn(&im->tags, "i_incomplete", 1);
   }
   if (raster)
     _TIFFfree( raster );
@@ -400,7 +437,7 @@ static i_img *read_one_tiff(TIFF *tif) {
 =cut
 */
 i_img*
-i_readtiff_wiol(io_glue *ig, int length, int page) {
+i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
   TIFF* tif;
   TIFFErrorHandler old_handler;
   TIFFErrorHandler old_warn_handler;
@@ -416,7 +453,7 @@ i_readtiff_wiol(io_glue *ig, int length, int page) {
   /* Also add code to check for mmapped code */
 
   io_glue_commit_types(ig);
-  mm_log((1, "i_readtiff_wiol(ig %p, length %d)\n", ig, length));
+  mm_log((1, "i_readtiff_wiol(ig %p, allow_incomplete %d, page %d)\n", ig, allow_incomplete, page));
   
   tif = TIFFClientOpen("(Iolayer)", 
                       "rm", 
@@ -443,11 +480,12 @@ i_readtiff_wiol(io_glue *ig, int length, int page) {
       i_push_errorf(0, "could not switch to page %d", page);
       TIFFSetErrorHandler(old_handler);
       TIFFSetWarningHandler(old_warn_handler);
+      TIFFClose(tif);
       return NULL;
     }
   }
 
-  im = read_one_tiff(tif);
+  im = read_one_tiff(tif, allow_incomplete);
 
   if (TIFFLastDirectory(tif)) mm_log((1, "Last directory of tiff file\n"));
   TIFFSetErrorHandler(old_handler);
@@ -505,7 +543,7 @@ i_readtiff_multi_wiol(io_glue *ig, int length, int *count) {
 
   *count = 0;
   do {
-    i_img *im = read_one_tiff(tif);
+    i_img *im = read_one_tiff(tif, 0);
     if (!im)
       break;
     if (++*count > result_alloc) {
@@ -580,7 +618,7 @@ i_writetiff_low_faxable(TIFF *tif, i_img *im, int fine) {
     { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField bitpersample=1\n")); return 0; }
   if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG))
     { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField planarconfig\n")); return 0; }
-  if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK))
+  if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE))
     { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField photometric=%d\n", PHOTOMETRIC_MINISBLACK)); return 0; }
   if (!TIFFSetField(tif, TIFFTAG_COMPRESSION, 3))
     { mm_log((1, "i_writetiff_wiol_faxable: TIFFSetField compression=3\n")); return 0; }
@@ -620,7 +658,7 @@ i_writetiff_low_faxable(TIFF *tif, i_img *im, int fine) {
       bits = width-x; if(bits>8) bits=8;
       i_gsamp(im, x, x+8, y, luma, &luma_chan, 1);
       for(bitpos=0;bitpos<bits;bitpos++) {
-       linebuf[linebufpos] |= ((luma[bitpos]>=128)?bitval:0);
+       linebuf[linebufpos] |= ((luma[bitpos] < 128) ? bitval : 0);
        bitval >>= 1;
       }
       linebufpos++;