# HG changeset patch # User magedrifaat # Date 1660503778 -7200 # Node ID 3f5f1404af8a25cb38bca9bcfd929828d22e9f88 # Parent 8bf3fa6b6977cd77b7229fd79cb5cb9e107d4428 Tiff: added directory methods (currentDirectory, nextDirectory, ...) * __tiff__.cc: implemented the internal functions for the directory methods. * Tiff.m: added the methods to the class and added a test for the methods. diff -r 8bf3fa6b6977 -r 3f5f1404af8a libinterp/corefcn/__tiff__.cc --- a/libinterp/corefcn/__tiff__.cc Sun Aug 14 02:40:03 2022 +0200 +++ b/libinterp/corefcn/__tiff__.cc Sun Aug 14 21:02:58 2022 +0200 @@ -1181,11 +1181,18 @@ if (TIFFFieldPassCount (fip)) error ("Unsupported tag"); + TIFFDataType tag_datatype = TIFFFieldDataType (fip); + // According to matlab, the value must be a scalar double - if (! tag_ov.is_scalar_type () || ! tag_ov.is_double_type ()) + // except for strings + if (tag_datatype == TIFF_ASCII) + { + if (! tag_ov.is_string ()) + error ("Expected string for ascii tag"); + } + else if (! tag_ov.is_scalar_type () || ! tag_ov.is_double_type ()) error ("Tag value must be a scalar double"); - TIFFDataType tag_datatype = TIFFFieldDataType (fip); switch (tag_datatype) { case TIFF_BYTE: @@ -2400,6 +2407,7 @@ 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 uint32_t row = args (1).uint32_scalar_value (); tiff_image_data image_data (tif); @@ -2409,7 +2417,6 @@ if (row < 1 || row > image_data.height) error ("Row out of bounds of the image"); - // TODO(maged): check if matlab require the first row in strip as well // Convert from 1-based indexing to zero-based row--; @@ -2437,6 +2444,7 @@ = reinterpret_cast (strip_data.fortran_vec ()); // 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)) error ("Failed to read strip"); @@ -2882,6 +2890,165 @@ #endif } + DEFUN (__tiff_current_directory__, args, , + "Get the index of the current directory") + { +#if defined (HAVE_TIFF) + int nargin = args.length (); + + if (nargin != 1) + error ("Wrong number of arguments\n"); + + TIFF *tif = (TIFF *)(args(0).uint64_value ()); + + // TODO(maged): check matlab behavior + uint16_t dir = TIFFCurrentDirectory (tif); + if (dir == (uint16_t)-1) + dir = 0; + + return octave_value_list (octave_value (dir + 1)); +#else + err_disabled_feature ("currentDirectory", "Tiff"); +#endif + } + + DEFUN (__tiff_last_directory__, args, , + "Get the whether the current directory is the last") + { +#if defined (HAVE_TIFF) + int nargin = args.length (); + + if (nargin != 1) + error ("Wrong number of arguments\n"); + + TIFF *tif = (TIFF *)(args(0).uint64_value ()); + + bool is_last = TIFFLastDirectory (tif); + + return octave_value_list (octave_value (is_last)); +#else + err_disabled_feature ("lastDirectory", "Tiff"); +#endif + } + + DEFUN (__tiff_next_directory__, args, , + "Set the next IFD as the current IFD") + { +#if defined (HAVE_TIFF) + int nargin = args.length (); + + if (nargin != 1) + error ("Wrong number of arguments\n"); + + 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"); + + if (! TIFFReadDirectory (tif)) + error ("Failed to read the next directory"); + + return octave_value_list (); +#else + err_disabled_feature ("nextDirectory", "Tiff"); +#endif + } + + DEFUN (__tiff_set_directory__, args, , + "Set the current IFD using the given index") + { +#if defined (HAVE_TIFF) + int nargin = args.length (); + + if (nargin != 2) + error ("Wrong number of arguments\n"); + + 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"); + + dir--; + + if (! TIFFSetDirectory(tif, dir)) + error ("Failed to read directory"); + + return octave_value_list (); +#else + err_disabled_feature ("setDirectory", "Tiff"); +#endif + } + + DEFUN (__tiff_write_directory__, args, , + "Write the current IFD to file and create a new one") + { +#if defined (HAVE_TIFF) + int nargin = args.length (); + + if (nargin != 1) + 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+) + if (! TIFFWriteDirectory(tif)) + error ("Failed to write directory"); + + return octave_value_list (); +#else + err_disabled_feature ("writeDirectory", "Tiff"); +#endif + } + + DEFUN (__tiff_rewrite_directory__, args, , + "Rewrite modifications to the current IFD") + { +#if defined (HAVE_TIFF) + int nargin = args.length (); + + if (nargin != 1) + 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"); + + return octave_value_list (); +#else + err_disabled_feature ("rewriteDirectory", "Tiff"); +#endif + } + + DEFUN (__tiff_set_sub_directory__, args, , + "Set the given offset directory as the current IFD") + { +#if defined (HAVE_TIFF) + int nargin = args.length (); + + if (nargin != 2) + error ("Wrong number of arguments\n"); + + TIFF *tif = (TIFF *)(args(0).uint64_value ()); + + // TODO(maged): check if matlab requires scalar double + uint64_t offset = args(1).uint64_scalar_value (); + if (! TIFFSetSubDirectory (tif, offset)) + error ("Failed to switch to the sub directory"); + + return octave_value_list (); +#else + err_disabled_feature ("setSubDirectory", "Tiff"); +#endif + } + DEFUN (__tiff_version__, , , "Get the version stamp of LibTIFF") { diff -r 8bf3fa6b6977 -r 3f5f1404af8a scripts/io/Tiff.m --- a/scripts/io/Tiff.m Sun Aug 14 02:40:03 2022 +0200 +++ b/scripts/io/Tiff.m Sun Aug 14 21:02:58 2022 +0200 @@ -330,6 +330,55 @@ tileNumber = __tiff_compute_tile__ (t.tiff_handle, varargin{:}); endfunction + function dirNum = currentDirectory (t) + if (t.closed) + error ("Image file was closed"); + endif + dirNum = __tiff_current_directory__ (t.tiff_handle); + endfunction + + function isLast = lastDirectory (t) + if (t.closed) + error ("Image file was closed"); + endif + isLast = __tiff_last_directory__ (t.tiff_handle); + endfunction + + function nextDirectory (t) + if (t.closed) + error ("Image file was closed"); + endif + __tiff_next_directory__ (t.tiff_handle); + endfunction + + function setDirectory (t, dirNum) + if (t.closed) + error ("Image file was closed"); + endif + __tiff_set_directory__ (t.tiff_handle, dirNum); + endfunction + + function writeDirectory (t) + if (t.closed) + error ("Image file was closed"); + endif + __tiff_write_directory__ (t.tiff_handle); + endfunction + + function rewriteDirectory (t) + if (t.closed) + error ("Image file was closed"); + endif + __tiff_rewrite_directory__ (t.tiff_handle); + endfunction + + function setSubDirectory (t, offset) + if (t.closed) + error ("Image file was closed"); + endif + __tiff_set_sub_directory__ (t.tiff_handle, offset); + endfunction + % TODO(maged): add documentation and make print_usage work endmethods @@ -1624,3 +1673,28 @@ %! assert (alpha, data(1:16,1:32,4)); %! endfunction %! file_wrapper (@test_fn); + +## test directory manipulation +%!testif HAVE_TIFF +%! function test_fn (filename) +%! img = Tiff (filename, "w"); +%! tags = struct ( +%! "ImageLength", 10, "ImageWidth", 10, "BitsPerSample", 8 +%! ); +%! setTag (img, tags); +%! data = uint8 (reshape (1:100, [10, 10])); +%! write(img, data); +%! img.writeDirectory (); +%! setTag (img, tags); +%! write(img, data); +%! img.close(); +%! img = Tiff (filename); +%! assert (img.currentDirectory, 1); +%! assert (img.lastDirectory, logical (0)); +%! img.nextDirectory (); +%! assert (img.currentDirectory, 2); +%! assert (img.lastDirectory, logical (1)); +%! img.setDirectory (1); +%! assert (img.currentDirectory, 1); +%! endfunction +%! file_wrapper (@test_fn) \ No newline at end of file