changeset 31196:1da6d747bf78

__tiff_imread__: converted to private octave function * libinterp/corefcn/__tiff__.cc: removed internal function __tiff_imread__. * scripts/image/private/__tiff_imread__.m: added private function __tiff_imread__. * scripts/image/module.mk: added entry for the private function __tiff_imread__.
author magedrifaat <magedrifaat@gmail.com>
date Thu, 01 Sep 2022 00:10:37 +0200
parents f8baeb850b36
children 1604c8812b67
files libinterp/corefcn/__tiff__.cc libinterp/corefcn/module.mk scripts/image/module.mk
diffstat 3 files changed, 7 insertions(+), 191 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/__tiff__.cc	Tue Aug 30 20:32:50 2022 +0200
+++ b/libinterp/corefcn/__tiff__.cc	Thu Sep 01 00:10:37 2022 +0200
@@ -2767,6 +2767,7 @@
         || ! TIFFRGBAImageBegin (&img_config, tif, 0, emsg))
       error ("Failed to read image");
     
+    // FIXME: rotated orientation don't work correctly (e.g. LeftTop)
     img_config.orientation = ORIENTATION_TOPLEFT;
     img_config.req_orientation = orientation;
 
@@ -3565,197 +3566,6 @@
 #endif
   }
 
-  DEFUN (__tiff_imread__, args, nargout,
-         "Handler for imread that uses Tiff interface")
-  {
-#if defined (HAVE_TIFF)
-    int nargin = args.length ();
-
-    if (nargin == 0 || ! args(0).is_string ())
-      error ("No filename provided\n");
-    
-    uint16_t offset = 1;
-    
-    TIFF *tif = TIFFOpen (args(0).string_value ().c_str (), "r");
-    if (! tif)
-      error ("Failed to open file %s", args(0).string_value ().c_str ());
-    
-    // A simple way to make sure the file will be closed when the function
-    // returns or when an error occurs as the destructor will always be called
-    octave_tiff_handle tiff_handle (tif);
-
-    uint16_t dir_count = TIFFNumberOfDirectories (tif);
-    uint16_t page = 1;
-
-    // Handle unpaired index parameter
-    if (nargin > 1 && ! args(1).is_string ())
-      {
-        if (is_numeric_scalar (args(1)))
-          page = args(1).uint16_scalar_value ();
-        else
-          error ("imread: index must be a numeric scalar");
-        offset++;
-      }
-    
-    if ((nargin - offset) % 2 != 0)
-      error ("imread: PARAM/VALUE arguments must occur in pairs");
-    
-    // Handle all index/frames params
-    bool found_index = false;
-    for (uint16_t arg_idx = offset; arg_idx < nargin; arg_idx+=2)
-      {
-        if (! args(arg_idx).is_string ())
-          error ("imread: PARAM in PARAM/VALUE pair must be string");
-        
-        const char *param_cstr = args(arg_idx).string_value ().c_str ();
-        if (strcasecmp (param_cstr, "index") == 0
-            || strcasecmp (param_cstr, "frames") == 0)
-          {
-            if (found_index)
-              error ("imread: Index or Frames may only be specified once");
-            
-            found_index = true;
-            octave_value val = args(arg_idx + 1);
-            if (is_numeric_scalar (val))
-              page = val.uint16_scalar_value ();
-            else
-              error ("imread: %s must be a numeric scalar", param_cstr);
-          }
-      }
-    
-    // validate frame numbers
-    if (page < 1 || page > dir_count)
-      error ("imread: index/frames specified are outside the number of images");
-    
-    // Convert to zero-based indexing
-    page = page - 1;
-
-    // Go to the first page
-    if (! TIFFSetDirectory (tif, page))
-      error ("imread: failed to read page %d", page);
-    
-    // Obtain image info
-    tiff_image_data image_data (tif);
-    
-    // Set the default region
-    uint32NDArray row_region (dim_vector (1, 3));
-    row_region(0) = 1;
-    row_region(1) = 1;
-    row_region(2) = image_data.height;
-    uint32NDArray col_region (dim_vector (1, 3));
-    col_region(0) = 1;
-    col_region(1) = 1;
-    col_region(2) = image_data.width;
-
-    // Obtain and validate other params (pixelregion, info)
-    for (uint16_t arg_idx = offset; arg_idx < nargin; arg_idx+=2)
-      {
-        if (! args(arg_idx).is_string ())
-          error ("imread: PARAM in PARAM/VALUE pair must be string");
-        
-        const char *param_cstr = args(arg_idx).string_value ().c_str ();
-        if (strcasecmp (param_cstr, "index") == 0
-            || strcasecmp (param_cstr, "frames") == 0)
-          {
-            // Already handled
-          }
-        else if (strcasecmp (param_cstr, "pixelregion") == 0)
-          {
-            octave_value region_ov = args(arg_idx + 1);
-            
-            if (! region_ov.iscell () || region_ov.numel () != 2)
-              error ("imread: %s must be a 2-element cell array", param_cstr);
-            
-            Cell region_cell = region_ov.cell_value ();
-            row_region = region_cell(0).floor ().uint32_array_value ();
-            col_region = region_cell(1).floor ().uint32_array_value ();
-            
-            if (row_region.numel () < 2 || row_region.numel () > 3
-                || col_region.numel () < 2 || col_region.numel () > 3)
-              error ("imread: range for %s must be a 2 or 3 element vector",
-                     param_cstr);
-            
-            if (row_region.numel () == 2)
-              {
-                row_region(2) = row_region(1);
-                row_region(1) = 1;
-              }
-            if (col_region.numel () == 2)
-              {
-                col_region(2) = col_region(1);
-                col_region(1) = 1;
-              }
-            
-            if (static_cast<uint32_t> (row_region(2)) > image_data.height)
-              error ("imread: end ROWS for PixelRegions option is larger than image height");
-            if (static_cast<uint32_t> (col_region(2)) > image_data.width)
-              error ("imread: end COLS for PixelRegions option is larger than image width");
-          }
-        else if (strcasecmp (param_cstr, "info") == 0)
-          {
-            // This isn't very useful here, ignoring it
-          }
-        else
-          error ("imread: invalid PARAMETER '%s'", param_cstr);
-      }
-
-    // Read image according to params
-    // FIXME: this should convert YCbCr images to RGB
-    uint16_t sample_format;
-    TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &sample_format);
-
-    octave_value_list retval (3, Matrix ());
-    switch (sample_format)
-      {
-      case 1:
-      case 4:
-        retval (0) = read_unsigned_image (tif, &image_data);
-        break;
-      case 2:
-        retval (0) = read_signed_image (tif, &image_data);
-        break;
-      case 3:
-        retval (0) = read_float_image (tif, &image_data);
-        break;
-      default:
-        error ("Unsupported sample format");
-      }
-    
-    // Use octave_value methods to slice the data without knowledge of
-    // the underlying data type to avoid code duplication
-    // FIXME: this approach is slow when the needed region is much smaller
-    // than the image size because the entire image will be read first
-    octave_value_list idx (3);
-    // Need to use range because normal idx_vector constuctor handles steps
-    // in a wrong way
-    idx(0) = idx_vector (range<double> (row_region (0), row_region (1),
-                                        row_region(2)));
-    idx(1) = idx_vector (range<double> (col_region (0), col_region (1),
-                                        col_region(2)));
-    idx(2) = idx_vector (':');
-    retval(0) = retval(0).index_op (idx);
-    
-    if (nargout > 1)
-      {
-        // Also return the color map if available
-        uint16_t photometric;
-        if (TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photometric)
-            && photometric == PHOTOMETRIC_PALETTE)
-          {
-            const TIFFField *fip
-              = TIFFFieldWithTag (tif, TIFFTAG_COLORMAP);
-            if (fip)
-              retval(1) = get_field_data (tif, fip);
-          }
-      }
-    // FIXME: matlab returns all channels in the first argout
-    // and doesnt separate the alpha
-    return retval;
-#else
-    err_disabled_feature ("imread", "Tiff");
-#endif
-  }
-
   DEFUN (__tiff_imwrite__, args, ,
          "Handler for imwrite that uses Tiff interface")
   {
--- a/libinterp/corefcn/module.mk	Tue Aug 30 20:32:50 2022 +0200
+++ b/libinterp/corefcn/module.mk	Thu Sep 01 00:10:37 2022 +0200
@@ -110,6 +110,11 @@
 ## oct-tex-parser.h is in the SRC list so that it will be distributed
 ## but not installed.
 
+## __tiff__.cc is a built-in function instead of a dynamically loaded
+## function to avoid issues on some systems where LibTIFF is unloaded when
+## it is needed for other components (e.g. Qt, GraphicsMagick)
+## More info: https://savannah.gnu.org/bugs/?41699
+
 COREFCN_SRC = \
   %reldir%/Cell.cc \
   %reldir%/__betainc__.cc \
--- a/scripts/image/module.mk	Tue Aug 30 20:32:50 2022 +0200
+++ b/scripts/image/module.mk	Thu Sep 01 00:10:37 2022 +0200
@@ -6,6 +6,7 @@
   %reldir%/private/__imfinfo__.m \
   %reldir%/private/__imread__.m \
   %reldir%/private/__imwrite__.m \
+  %reldir%/private/__tiff_imread__.m \
   %reldir%/private/colorspace_conversion_input_check.m \
   %reldir%/private/colorspace_conversion_revert.m \
   %reldir%/private/imageIO.m \