# HG changeset patch # User magedrifaat # Date 1661983837 -7200 # Node ID 1da6d747bf78424d5379a68ac61f2cce08d23c8b # Parent f8baeb850b3697005d87431b71eff42085283ca9 __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__. diff -r f8baeb850b36 -r 1da6d747bf78 libinterp/corefcn/__tiff__.cc --- 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 (row_region(2)) > image_data.height) - error ("imread: end ROWS for PixelRegions option is larger than image height"); - if (static_cast (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 (row_region (0), row_region (1), - row_region(2))); - idx(1) = idx_vector (range (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") { diff -r f8baeb850b36 -r 1da6d747bf78 libinterp/corefcn/module.mk --- 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 \ diff -r f8baeb850b36 -r 1da6d747bf78 scripts/image/module.mk --- 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 \