changeset 31150:6bede2d6f273

Tiff: added computeStrip and computeTile methods * Tiff.m: added computeStrip and computeTile methods to the tiff class and added tests for the twwo methods. * __tiff__.cc: added the internal function that implements the two methods.
author magedrifaat <magedrifaat@gmail.com>
date Mon, 01 Aug 2022 00:34:34 +0200
parents d4dbc69f301e
children 6fb54834aa93
files libinterp/dldfcn/__tiff__.cc scripts/io/Tiff.m
diffstat 2 files changed, 202 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/__tiff__.cc	Sun Jul 31 22:32:02 2022 +0200
+++ b/libinterp/dldfcn/__tiff__.cc	Mon Aug 01 00:34:34 2022 +0200
@@ -1226,11 +1226,11 @@
         error ("No filename supplied\n");
       }
 
-    std::string filename = args (0).string_value ();
+    std::string filename = args(0).string_value ();
     std::string mode = "r";
 
     if (nargin == 2)
-      mode = args (1).string_value ();
+      mode = args(1).string_value ();
 
     const std::vector<std::string> supported_modes {"r", "w", "w8", "a"};
       
@@ -1267,7 +1267,7 @@
     if (nargin == 0)
       error ("No handle provided\n");
     
-    TIFF *tif = (TIFF *)(args (0).uint64_value ());
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
     TIFFClose (tif);
 
     return octave_value_list ();
@@ -1289,14 +1289,14 @@
     if (nargin < 2)
       error ("No tag name provided\n");
     
-    TIFF *tif = (TIFF *)(args (0).uint64_value ());
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
 
     uint32_t tag_id;
     const TIFFField *fip;
     
-    if (args (1).is_string ())
+    if (args(1).is_string ())
       {
-        std::string tagName = args (1).string_value ();
+        std::string tagName = args(1).string_value ();
         fip = TIFFFieldWithName (tif, tagName.c_str ());
         if (! fip)
           error ("Tiff tag not found");
@@ -1305,7 +1305,7 @@
       }
     else
       {
-        tag_id = args (1).int_value ();
+        tag_id = args(1).int_value ();
         fip = TIFFFieldWithTag (tif, tag_id);
         
         if (! fip)
@@ -1328,11 +1328,11 @@
     if (nargin < 2)
       error ("Too few arguments provided\n");
     
-    TIFF *tif = (TIFF *)(args (0).uint64_value ());
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
     
-    if (args (1).isstruct ())
+    if (args(1).isstruct ())
       {
-        octave_scalar_map tags = args (1).scalar_map_value ();
+        octave_scalar_map tags = args(1).scalar_map_value ();
         string_vector keys = tags.fieldnames ();
         // Using iterators instead of this loop method seems to process
         // the elements of the struct in a different order than they were
@@ -1354,22 +1354,22 @@
 
         const TIFFField *fip;
         // TODO(maged): matlab actually checks for its own strings not LibTIFF's
-        if (args (1).is_string ())
+        if (args(1).is_string ())
           {
-            std::string tagName = args (1).string_value ();
+            std::string tagName = args(1).string_value ();
             fip = TIFFFieldWithName (tif, tagName.c_str ());
             if (! fip)
               error ("Tiff tag not found");
           }
         else
           {
-            uint32_t tag_id = args (1).int_value ();
+            uint32_t tag_id = args(1).int_value ();
             fip = TIFFFieldWithTag (tif, tag_id);
             if (! fip)
               error ("Tiff tag not found");
           }
         
-        set_field_data (tif, fip, args (2));
+        set_field_data (tif, fip, args(2));
       }
 
     return octave_value_list ();
@@ -1387,7 +1387,7 @@
     if (nargin == 0)
       error ("No handle provided\n");
     
-    TIFF *tif = (TIFF *)(args (0).uint64_value ());
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
 
     // TODO(maged): nargout and ycbcr
     octave_unused_parameter (nargout);
@@ -1456,7 +1456,7 @@
     if (nargin < 3)
       error ("Too few arguments provided\n");
     
-    TIFF *tif = (TIFF *)(args (0).uint64_value ());
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
 
     // TODO(maged): check on windows
     if (TIFFGetMode (tif) == O_RDONLY)
@@ -1468,7 +1468,7 @@
     if (image_data.is_tiled)
       error ("Can't write strips to a tiled image");
 
-    uint32_t strip_no = args (1).uint32_scalar_value ();
+    uint32_t strip_no = args(1).uint32_scalar_value ();
     if (strip_no < 1 || strip_no > TIFFNumberOfStrips (tif))
       error ("Strip number out of range");
     
@@ -1490,7 +1490,7 @@
     if (nargin < 3)
       error ("Too few arguments provided\n");
     
-    TIFF *tif = (TIFF *)(args (0).uint64_value ());
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
 
     // TODO(maged): check on windows
     if (TIFFGetMode (tif) == O_RDONLY)
@@ -1502,7 +1502,7 @@
     if (! image_data.is_tiled)
       error ("Can't write tiles to a stripped image");
 
-    uint32_t tile_no = args (1).uint32_scalar_value ();
+    uint32_t tile_no = args(1).uint32_scalar_value ();
     if (tile_no < 1 || tile_no > TIFFNumberOfTiles (tif))
       error ("Tile number out of range");
 
@@ -1514,7 +1514,7 @@
 #endif
   }
   
-  DEFUN_DLD (__is_tiled__, args, ,
+  DEFUN_DLD (__tiff_is_tiled__, args, ,
              "Get whether the image is tiled")
   {
 #if defined (HAVE_TIFF)
@@ -1523,15 +1523,15 @@
     if (nargin == 0)
       error ("No handle provided\n");
     
-    TIFF *tif = (TIFF *)(args (0).uint64_value ());
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
     bool is_tiled = static_cast<bool> (TIFFIsTiled (tif));
     return octave_value_list (octave_value (is_tiled));
 #else
-    err_disabled_feature ("close", "Tiff");
+    err_disabled_feature ("isTiled", "Tiff");
 #endif
   }
 
-  DEFUN_DLD (__number_of_strips__, args, ,
+  DEFUN_DLD (__tiff_number_of_strips__, args, ,
              "Get the number of strips in the image")
   {
 #if defined (HAVE_TIFF)
@@ -1540,14 +1540,122 @@
     if (nargin == 0)
       error ("No handle provided\n");
     
-    TIFF *tif = (TIFF *)(args (0).uint64_value ());
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
+    // What is the behavior in matlab?
     if (TIFFIsTiled (tif))
       error ("The image is tiled not stripped");
     
     double strip_count = static_cast<double> (TIFFNumberOfStrips (tif));
     return octave_value_list (octave_value (strip_count));
 #else
-    err_disabled_feature ("close", "Tiff");
+    err_disabled_feature ("numberOfStrips", "Tiff");
+#endif
+  }
+
+  DEFUN_DLD (__tiff_compute_strip__, args, ,
+             "Get the strip index containing the given row")
+  {
+#if defined (HAVE_TIFF)
+    int nargin = args.length ();
+
+    if (nargin < 2 || nargin > 3)
+      error ("Wrong number of arguments\n");
+    
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
+    // What is the behavior in matlab?
+    if (TIFFIsTiled (tif))
+      error ("The image is tiled not stripped");
+    
+    tiff_image_data image_data (tif);
+
+    uint32_t row = args(1).uint32_scalar_value ();
+    if (row > image_data.height)
+      row = image_data.height;
+
+    // Convert from 1-based to zero-based indexing but avoid underflow
+    if (row > 0)
+      row--;
+    
+    uint16_t plane;
+    if (nargin > 2)
+      {
+        plane = args(2).uint16_scalar_value ();
+        if (plane > image_data.samples_per_pixel)
+          plane = image_data.samples_per_pixel;
+        if (plane > 0)
+          plane--;
+      }
+    else
+      {
+        plane = 0;
+      }
+
+    // TODO(maged): What is the behavior in matlab for using/not using plane?
+    // TODO(maged): what is the behavior for out of bounds?
+    double strip_number = TIFFComputeStrip (tif, row, plane) + 1;
+    if (strip_number > TIFFNumberOfStrips (tif))
+      strip_number = TIFFNumberOfStrips (tif);
+    return octave_value_list (octave_value (strip_number));
+#else
+    err_disabled_feature ("computeStrip", "Tiff");
+#endif
+  }
+
+  DEFUN_DLD (__tiff_compute_tile__, args, ,
+             "Get the tile index containing the given row and column")
+  {
+#if defined (HAVE_TIFF)
+    int nargin = args.length ();
+
+    if (nargin < 2 || nargin > 3)
+      error ("Wrong number of arguments\n");
+    
+    TIFF *tif = (TIFF *)(args(0).uint64_value ());
+    // What is the behavior in matlab?
+    if (! TIFFIsTiled (tif))
+      error ("The image is stripped not tiled");
+    
+    uint32NDArray coords = args(1).uint32_array_value ();
+    if (coords.dim2() < 2)
+      error ("Coordinates must be in the shape [row, col]");
+    uint32_t row = coords(0, 0);
+    uint32_t col = coords(0, 1);
+
+    tiff_image_data image_data (tif);
+
+    if (col > image_data.width)
+      col = image_data.width;
+    if (row > image_data.height)
+      row = image_data.height;
+
+    // Convert from 1-based to zero-based indexing but avoid underflow
+    if (row > 0)
+      row--;
+    if (col > 0)
+      col--;
+    
+    uint16_t plane;
+    if (nargin > 2)
+      {
+        plane = args(2).uint16_scalar_value ();
+        if (plane > image_data.samples_per_pixel)
+          plane = image_data.samples_per_pixel;
+        if (plane > 0)
+          plane--;
+      }
+    else
+      {
+        plane = 0;
+      }
+
+    // TODO(maged): What is the behavior in matlab for using/not using plane?
+    // TODO(maged): what is the behavior for out of bounds?
+    double tile_number = TIFFComputeTile (tif, col, row, 0, plane) + 1;
+    if (tile_number > TIFFNumberOfTiles (tif))
+      tile_number = TIFFNumberOfTiles (tif);
+    return octave_value_list (octave_value (tile_number));
+#else
+    err_disabled_feature ("computeTile", "Tiff");
 #endif
   }
 
--- a/scripts/io/Tiff.m	Sun Jul 31 22:32:02 2022 +0200
+++ b/scripts/io/Tiff.m	Mon Aug 01 00:34:34 2022 +0200
@@ -134,14 +134,28 @@
       if (t.closed)
         error ("Image file was closed");
       endif
-      tf = __is_tiled__ (t.tiff_handle);
+      tf = __tiff_is_tiled__ (t.tiff_handle);
     endfunction
 
     function numStrips = numberOfStrips (t)
       if (t.closed)
         error ("Image file was closed");
       endif
-      numStrips = __number_of_strips__ (t.tiff_handle);
+      numStrips = __tiff_number_of_strips__ (t.tiff_handle);
+    endfunction
+
+    function stripNumber = computeStrip (t, varargin)
+      if (t.closed)
+        error ("Image file was closed");
+      endif
+      stripNumber = __tiff_compute_strip__ (t.tiff_handle, varargin{:});
+    endfunction
+
+    function tileNumber = computeTile (t, varargin)
+      if (t.closed)
+        error ("Image file was closed");
+      endif
+      tileNumber = __tiff_compute_tile__ (t.tiff_handle, varargin{:});
     endfunction
 
     % TODO(maged): add documentation and make print_usage work
@@ -795,4 +809,56 @@
 %!    setTag (img, "TileWidth", 16);
 %!    fail ("numberOfStrips (img)", "The image is tiled not stripped");
 %!  endfunction
-%!  file_wrapper (@test_fn);
\ No newline at end of file
+%!  file_wrapper (@test_fn);
+
+## test computeStrip returns the correct value
+%!testif HAVE_TIFF
+%!  function test_fn (filename)
+%!    img = Tiff (filename, "w");
+%!    setTag (img, struct ("ImageWidth", 10, "ImageLength", 10,
+%!                         "RowsPerStrip", 2, "BitsPerSample", 8,
+%!                         "SamplesPerPixel", 3, "PlanarConfiguration", 1));
+%!    assert (computeStrip (img, 1), 1);
+%!    assert (computeStrip (img, 2), 1);
+%!    assert (computeStrip (img, 0), 1);
+%!    assert (computeStrip (img, 10), 5);
+%!    assert (computeStrip (img, 11), 5);
+%!    setTag (img, "PlanarConfiguration", 2);
+%!    ## This is need for the tag to take effect, should be
+%!    ## replaced by rewriteDirectory
+%!    writeEncodedStrip (img, 1, uint8 (reshape (1:20, [2, 10])));
+%!    assert (computeStrip (img, 1, 2), 6);
+%!    assert (computeStrip (img, 100, 1), 5);
+%!    img = Tiff ("test.tif", "w");
+%!    setTag (img, "TileWidth", 16);
+%!    setTag (img, "TileLength", 16);
+%!    fail ("computeStrip (img, 1, 1)", "The image is tiled not stripped");
+%!  endfunction
+%!  file_wrapper (@test_fn);
+
+## test computeTile returns the correct value
+%!testif HAVE_TIFF
+%!  function test_fn (filename)
+%!    img = Tiff (filename, "w");
+%!    setTag (img, struct ("ImageWidth", 20, "ImageLength", 20,
+%!                         "BitsPerSample", 8, "SamplesPerPixel", 3,
+%!                         "TileLength", 16, "TileWidth", 16,
+%!                         "PlanarConfiguration", 1));
+%!    assert (computeTile (img, [1, 1]), 1);
+%!    assert (computeTile (img, [2, 2]), 1);
+%!    assert (computeTile (img, [0, 0]), 1);
+%!    assert (computeTile (img, [8, 17]), 2);
+%!    assert (computeTile (img, [19, 10]), 3);
+%!    assert (computeTile (img, [17, 17]), 4);
+%!    assert (computeTile (img, [100, 100]), 4);
+%!    setTag (img, "PlanarConfiguration", 2);
+%!    ## This is need for the tag to take effect, should be
+%!    ## replaced by rewriteDirectory
+%!    writeEncodedTile (img, 1, uint8 (reshape (1:256, [16, 16])));
+%!    assert (computeTile (img, [1, 1], 2), 5);
+%!    assert (computeTile (img, [100, 100], 1), 4);
+%!    img = Tiff ("test.tif", "w");
+%!    fail ("computeTile (img, 1, 1)", "The image is stripped not tiled");
+%!  endfunction
+%!  file_wrapper (@test_fn);
+