# HG changeset patch # User magedrifaat # Date 1660683441 -7200 # Node ID ed329571ec88aab5dfc79ee150f5d7b537057dd6 # Parent 1f19e9a06f2df31f258afcb38395dc0934d0193e Tiff: added support for creating and reading sub-directories * __tiff__.cc (F__tiff_set_sub_directory__): added logic to check existance and validation of offsets. * __tiff__,cc (set_field_data): handled SubIFD tag correctly to enable creating sub-directories. diff -r 1f19e9a06f2d -r ed329571ec88 libinterp/corefcn/__tiff__.cc --- a/libinterp/corefcn/__tiff__.cc Tue Aug 16 18:01:12 2022 +0200 +++ b/libinterp/corefcn/__tiff__.cc Tue Aug 16 22:57:21 2022 +0200 @@ -718,68 +718,46 @@ { case TIFF_BYTE: case TIFF_UNDEFINED: - { - retval = static_cast (*(reinterpret_cast (data))); - break; - } + retval = static_cast (*(reinterpret_cast (data))); + break; case TIFF_SHORT: - { - retval = static_cast (*(reinterpret_cast (data))); - break; - } + retval = static_cast (*(reinterpret_cast (data))); + break; case TIFF_LONG: - { - retval = static_cast (*(reinterpret_cast (data))); - break; - } + retval = static_cast (*(reinterpret_cast (data))); + break; case TIFF_LONG8: - { - retval = static_cast (*(reinterpret_cast (data))); - break; - } + retval = static_cast (*(reinterpret_cast (data))); + break; case TIFF_RATIONAL: - { - retval = *(reinterpret_cast (data)); - break; - } + retval = *(reinterpret_cast (data)); + break; case TIFF_SBYTE: - { - retval = static_cast (*(reinterpret_cast (data))); - break; - } + retval = static_cast (*(reinterpret_cast (data))); + break; case TIFF_SSHORT: - { - retval = static_cast (*(reinterpret_cast (data))); - break; - } + retval = static_cast (*(reinterpret_cast (data))); + break; case TIFF_SLONG: - { - retval = static_cast (*(reinterpret_cast (data))); - break; - } + retval = static_cast (*(reinterpret_cast (data))); + break; case TIFF_SLONG8: - { - retval = static_cast (*(reinterpret_cast (data))); - break; - } + retval = static_cast (*(reinterpret_cast (data))); + break; case TIFF_FLOAT: - { - retval = *(reinterpret_cast (data)); - break; - } + retval = *(reinterpret_cast (data)); + break; case TIFF_DOUBLE: - { - retval = *(reinterpret_cast (data)); - break; - } + retval = *(reinterpret_cast (data)); + break; case TIFF_SRATIONAL: - { - retval = *(reinterpret_cast (data)); - break; - } + retval = *(reinterpret_cast (data)); + break; case TIFF_IFD: + retval = static_cast (*(reinterpret_cast (data))); + break; case TIFF_IFD8: - error ("Unimplemented IFFD data type"); + retval = static_cast (*(reinterpret_cast (data))); break; default: error ("Unsupported tag data type"); @@ -935,10 +913,25 @@ break; } case TIFF_IFD: + { + uint32NDArray arr (arr_dims); + for (uint32_t i = 0; i < count; i++) + { + arr(i) = (reinterpret_cast (data))[i]; + } + retval = octave_value (arr); + break; + } case TIFF_IFD8: - // TODO(maged): implement IFD datatype? - error ("Unimplemented IFD data type"); - break; + { + uint64NDArray arr (arr_dims); + for (uint32_t i = 0; i < count; i++) + { + arr(i) = (reinterpret_cast (data))[i]; + } + retval = octave_value (arr); + break; + } default: error ("Unsupported tag data type"); } @@ -1439,9 +1432,12 @@ } case TIFFTAG_SUBIFD: { - // TODO(maged): Matlab doesnt error on setting this tag - // but returns 0 for getTag - error ("Unsupported tag"); + uint16_t subifd_count = tag_ov.uint16_scalar_value (); + std::unique_ptr subifd_offsets + = std::make_unique (subifd_count); + uint64_t *offfsets_ptr = subifd_offsets.get (); + if (! TIFFSetField (tif, tag_id, subifd_count, offfsets_ptr)) + error ("Failed to set tag"); break; } case TIFFTAG_EXTRASAMPLES: @@ -2426,9 +2422,9 @@ // Matlab (R2022a) requires row to be double if (! args(1).is_double_type ()) - error ("row must be double"); + error ("row should be of type double"); - uint32_t row = args (1).uint32_scalar_value (); + uint32_t row = args(1).uint32_scalar_value (); tiff_image_data image_data (tif); if (image_data.is_tiled) @@ -2466,11 +2462,6 @@ uint8NDArray strip_data (strip_dims); uint32_t *strip_ptr = 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"); TIFFRGBAImage img_config; char emsg[1024]; @@ -2527,10 +2518,13 @@ 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 (); + if (! args(1).is_double_type ()) + error ("row should be of type double"); + if (! args(2).is_double_type ()) + error ("col should be of type double"); + + uint32_t row = args(1).uint32_scalar_value (); + uint32_t col = args(2).uint32_scalar_value (); tiff_image_data image_data (tif); if (! image_data.is_tiled) @@ -2575,11 +2569,6 @@ uint8NDArray tile_data (tile_dims); uint32_t *tile_ptr = reinterpret_cast (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"); TIFFRGBAImage img_config; char emsg[1024]; @@ -2960,13 +2949,10 @@ 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; + dir++; - return octave_value_list (octave_value (dir + 1)); + return octave_value_list (octave_value (static_cast (dir))); #else err_disabled_feature ("currentDirectory", "Tiff"); #endif @@ -3051,8 +3037,7 @@ error ("Wrong number of arguments\n"); TIFF *tif = (TIFF *)(args(0).uint64_value ()); - // 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"); @@ -3096,7 +3081,29 @@ // TODO(maged): check if matlab requires scalar double // matlab expects double, uint32, or uint64 // and checks the subIFD tag first + if (! args(1).is_double_type () && ! args(1).is_uint32_type () + && ! args(1).is_uint64_type ()) + error ("Expected offset of type double, uint32 or uint64"); + + uint16_t count; + uint64_t *offsets; + if (! TIFFGetField (tif, TIFFTAG_SUBIFD, &count, &offsets)) + error ("The current directory doesn't have sub directories"); + uint64_t offset = args(1).uint64_scalar_value (); + + // TODO(maged): check if matlab validates the offset + int found = 0; + for (uint16_t i = 0; i < count; i++) + if (offset == offsets[i]) + { + found = 1; + break; + } + + if (! found) + error ("No Sub directory with the given offset"); + if (! TIFFSetSubDirectory (tif, offset)) error ("Failed to switch to the sub directory");