changeset 31173:0abc9779f751

Tiff: modified readRGBAImage to use the orientation tag correctly * __tiff__.cc (F__tiff_read_rgba_image__): modified the way the image is read to use the orientation tag in the correct way.
author magedrifaat <magedrifaat@gmail.com>
date Tue, 16 Aug 2022 16:10:10 +0200
parents 3f5f1404af8a
children 1f19e9a06f2d
files libinterp/corefcn/__tiff__.cc scripts/io/Tiff.m
diffstat 2 files changed, 37 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/__tiff__.cc	Sun Aug 14 21:02:58 2022 +0200
+++ b/libinterp/corefcn/__tiff__.cc	Tue Aug 16 16:10:10 2022 +0200
@@ -796,6 +796,8 @@
     octave_value retval;
     // Apparently matlab converts scalar numerical values into double
     // but doesn't do the same for arrays
+    // TODO(maged): matlab returns double for array tags as well, except
+    // for a selected set of tags (e.g. StripByteCounts)
     if (count == 1 && tag_datatype != TIFF_ASCII)
       {
         retval = interpret_scalar_tag_data (data, tag_datatype);
@@ -2360,14 +2362,30 @@
 
     tiff_image_data image_data (tif);
 
+    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
     dim_vector img_dims (4, image_data.width, image_data.height);
     uint8NDArray img (img_dims);
     uint32_t *img_ptr = reinterpret_cast <uint32_t *> (img.fortran_vec ());
-    // Matlab (R2022a) uses a top-left orientation ignoring the tag if present
-    if (! TIFFReadRGBAImageOriented (tif, image_data.width, image_data.height,
-                                     img_ptr, 1))
+    
+    TIFFRGBAImage img_config;
+    char emsg[1024];
+    if (! TIFFRGBAImageOK (tif, emsg)
+        || ! TIFFRGBAImageBegin (&img_config, tif, 0, emsg))
+      error ("Failed to read image");
+    
+    img_config.orientation = ORIENTATION_TOPLEFT;
+    img_config.req_orientation = orientation;
+
+    bool success = TIFFRGBAImageGet (&img_config, img_ptr, img_config.width,
+                                     img_config.height);
+                                     
+    TIFFRGBAImageEnd (&img_config);
+    if (!success)
       error ("Failed to read image");
     
     // Permute to the correct Octave dimension order
@@ -2406,8 +2424,10 @@
     
     TIFF *tif = (TIFF *)(args(0).uint64_value ());
 
-    // TODO(maged): check matlab behavior for missing/ wrong/ out of bounds row
-    // matlab row must be double (scalar or array),  and checks bounds
+    // Matlab (R2022a) requires row to be double
+    if (! args(1).is_double_type ())
+      error ("row must be double");
+    
     uint32_t row = args (1).uint32_scalar_value ();
     
     tiff_image_data image_data (tif);
@@ -2486,6 +2506,7 @@
     TIFF *tif = (TIFF *)(args(0).uint64_value ());
 
     // TODO(maged): check matlab behavior for missing/ wrong/ out of bounds vals
+    // matlab checks bounds and requires double vals (scalar or array)
     uint32_t row = args (1).uint32_scalar_value ();
     uint32_t col = args (2).uint32_scalar_value ();
     
@@ -2498,7 +2519,6 @@
     if (col < 1 || col > image_data.width)
       error ("Column out of bounds of the image");
     
-    // TODO(maged): check if matlab require the first row,col in tile as well
     // Convert from 1-based indexing to zero-based
     row--;
     col--;
@@ -2523,6 +2543,7 @@
       = 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))
       error ("Failed to read tile");
     
@@ -2902,6 +2923,7 @@
     TIFF *tif = (TIFF *)(args(0).uint64_value ());
 
     // TODO(maged): check matlab behavior
+    // matlab returns double and handles the special case as 0!
     uint16_t dir = TIFFCurrentDirectory (tif);
     if (dir == (uint16_t)-1)
       dir = 0;
@@ -2942,8 +2964,6 @@
     
     TIFF *tif = (TIFF *)(args(0).uint64_value ());
 
-    // TODO(maged): check if matlab handles this case different from
-    // an erronous next IFD
     bool is_last = TIFFLastDirectory (tif);
     if (is_last)
       error ("Current directory is the last directory");
@@ -2968,8 +2988,6 @@
     
     TIFF *tif = (TIFF *)(args(0).uint64_value ());
 
-    // TODO(maged): check matlab behavior for wrong argument type
-    // and out of bounds index
     uint16_t dir = args(1).uint16_scalar_value ();
     if (dir < 1 || dir > TIFFNumberOfDirectories (tif))
       error ("Directory index out of bounds");
@@ -2995,8 +3013,8 @@
       error ("Wrong number of arguments\n");
     
     TIFF *tif = (TIFF *)(args(0).uint64_value ());
-    // TODO(maged): check if matlab errors for leaving a corrupt directory
-    // Check if mtalab always writes directories at the end for both w and a (And r+)
+    // TODO(maged): Check if mtalab always writes directories at the end for both w and a (And r+)
+    // it does
     if (! TIFFWriteDirectory(tif))
       error ("Failed to write directory");
 
@@ -3016,8 +3034,7 @@
       error ("Wrong number of arguments\n");
     
     TIFF *tif = (TIFF *)(args(0).uint64_value ());
-    // TODO(maged): check if matlab errors for leaving a corrupt directory
-    // check if matlab changes directory after the call or switches back
+
     if (! TIFFRewriteDirectory(tif))
       error ("Failed to rewrite directory");
 
@@ -3039,6 +3056,8 @@
     TIFF *tif = (TIFF *)(args(0).uint64_value ());
     
     // TODO(maged): check if matlab requires scalar double
+    // matlab expects double, uint32, or uint64
+    // and checks the subIFD tag first
     uint64_t offset = args(1).uint64_scalar_value ();
     if (! TIFFSetSubDirectory (tif, offset))
       error ("Failed to switch to the sub directory");
--- a/scripts/io/Tiff.m	Sun Aug 14 21:02:58 2022 +0200
+++ b/scripts/io/Tiff.m	Tue Aug 16 16:10:10 2022 +0200
@@ -387,6 +387,10 @@
       versionString = __tiff_version__ ();
     endfunction
 
+    function tagNames = getTagNames ()
+      tagNames = fieldnames (Tiff.TagID);
+    endfunction
+
     function setLibTIFFErrorsEnabled(state)
       __tiff_set_errors_enabled__ (state);
     endfunction