changeset 31174:1f19e9a06f2d

Tiff: modified readRGBAStrip/Tile to correctly use the orientation tag * __tiff__.cc (F__tiff_read_rgba_strip__, F__read_rgba_tile__): modified the logic to use the orientation tag correctly.
author magedrifaat <magedrifaat@gmail.com>
date Tue, 16 Aug 2022 18:01:12 +0200
parents 0abc9779f751
children ed329571ec88
files libinterp/corefcn/__tiff__.cc
diffstat 1 files changed, 59 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/__tiff__.cc	Tue Aug 16 16:10:10 2022 +0200
+++ b/libinterp/corefcn/__tiff__.cc	Tue Aug 16 18:01:12 2022 +0200
@@ -2455,6 +2455,10 @@
     uint32_t strip_no = TIFFComputeStrip (tif, row, 0);
     rows_in_strip = get_rows_in_strip (strip_no, TIFFNumberOfStrips (tif),
                                         rows_in_strip, &image_data);
+    
+    uint16_t orientation;
+    if (! TIFFGetFieldDefaulted (tif, TIFFTAG_ORIENTATION, &orientation))
+      orientation = ORIENTATION_LEFTTOP;
 
     // Start with reversed dimensions to be aligned with LibTIFF and
     // permute to the correct order later
@@ -2465,7 +2469,25 @@
     
     // TODO(maged): check if matlab does anything with orientation tag
     // matlab uses the orientation tag to correct the data
-    if (! TIFFReadRGBAStrip (tif, row, strip_ptr))
+    // if (! TIFFReadRGBAStrip (tif, row, strip_ptr))
+    //   error ("Failed to read strip");
+
+    TIFFRGBAImage img_config;
+    char emsg[1024];
+    if (! TIFFRGBAImageOK (tif, emsg)
+        || ! TIFFRGBAImageBegin (&img_config, tif, 0, emsg))
+      error ("Failed to read strip");
+    
+    img_config.orientation = ORIENTATION_TOPLEFT;
+    img_config.req_orientation = orientation;
+    img_config.row_offset = row;
+    img_config.col_offset = 0;
+
+    bool success = TIFFRGBAImageGet (&img_config, strip_ptr, img_config.width,
+                                     rows_in_strip);
+                                     
+    TIFFRGBAImageEnd (&img_config);
+    if (!success)
       error ("Failed to read strip");
     
     // Permute to the correct order of dimensions for Octave
@@ -2476,9 +2498,9 @@
     strip_data = strip_data.permute (perm);
 
     // Slice the data into RGB and alpha
-    // The rows are reversed because LibTIFF assumes a bottom-left orientation
+    // TODO(maged): refactor into a function
     Array<idx_vector> idx (dim_vector (3, 1));
-    idx(0) = idx_vector (rows_in_strip - 1, -1, -1);
+    idx(0) = idx_vector (':');
     idx(1) = idx_vector (':');
     idx(2) = idx_vector (0, 3);
     uint8NDArray rgb = uint8NDArray (strip_data.index (idx));
@@ -2535,16 +2557,46 @@
     row -= row % tile_height;
     col -= col % tile_width;
     
+    uint16_t orientation;
+    if (! TIFFGetFieldDefaulted (tif, TIFFTAG_ORIENTATION, &orientation))
+      orientation = ORIENTATION_LEFTTOP;
+
+    // Calculate the correct dimensions for boundary tiles
+    uint32_t corrected_height = tile_height;
+    uint32_t corrected_width = tile_width;
+    if (row + tile_height > image_data.height)
+      corrected_height = image_data.height - row;
+    if (col + tile_width > image_data.width)
+      corrected_width = image_data.width - col;
+
     // Start with reversed dimensions to be aligned with LibTIFF and
     // permute to the correct order later
-    dim_vector tile_dims (4, tile_width, tile_height);
+    dim_vector tile_dims (4, corrected_width, corrected_height);
     uint8NDArray tile_data (tile_dims);
     uint32_t *tile_ptr
       = reinterpret_cast <uint32_t *> (tile_data.fortran_vec ());
     
     // TODO(maged): check if matlab does anything with orientation tag
     // matlab uses orientation tag to correct the data
-    if (! TIFFReadRGBATile (tif, col, row, tile_ptr))
+    // if (! TIFFReadRGBATile (tif, col, row, tile_ptr))
+    //   error ("Failed to read tile");
+
+    TIFFRGBAImage img_config;
+    char emsg[1024];
+    if (! TIFFRGBAImageOK (tif, emsg)
+        || ! TIFFRGBAImageBegin (&img_config, tif, 0, emsg))
+      error ("Failed to read tile");
+    
+    img_config.orientation = ORIENTATION_TOPLEFT;
+    img_config.req_orientation = orientation;
+    img_config.row_offset = row;
+    img_config.col_offset = col;
+
+    bool success = TIFFRGBAImageGet (&img_config, tile_ptr, corrected_width,
+                                     corrected_height);
+                                     
+    TIFFRGBAImageEnd (&img_config);
+    if (!success)
       error ("Failed to read tile");
     
     // Permute to the correct order of dimensions for Octave
@@ -2553,25 +2605,11 @@
     perm(1) = 1;
     perm(2) = 0;
     tile_data = tile_data.permute (perm);
-
-    // Calculate the correct dimensions for boundary tiles
-    uint32_t corrected_height = tile_height;
-    uint32_t corrected_width = tile_width;
-    if (row + tile_height > image_data.height)
-      corrected_height = image_data.height - row;
-    if (col + tile_width > image_data.width)
-      corrected_width = image_data.width - col;
     
     // Slice the data into RGB and alpha
-    // LibTIFF assumes the image has bottom-left orientation and returns
-    // the rows flipped vertically, so we need to reverse them and remove
-    // the padding which is at the top since the rows are flipped
     Array<idx_vector> idx (dim_vector (3, 1));
-    // Must cast the unsigned values to signed because otherwise the output
-    // can't be negative (C++ is the best).
-    idx(0) = idx_vector (tile_height - 1,
-                         int64_t(tile_height - corrected_height) - 1, -1);
-    idx(1) = idx_vector (0, corrected_width);
+    idx(0) = idx_vector (':');
+    idx(1) = idx_vector (':');
     idx(2) = idx_vector (0, 3);
     uint8NDArray rgb = uint8NDArray (tile_data.index (idx));
     idx(2) = idx_vector (3);