Mercurial > octave-libtiff
changeset 31175:ed329571ec88
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.
author | magedrifaat <magedrifaat@gmail.com> |
---|---|
date | Tue, 16 Aug 2022 22:57:21 +0200 |
parents | 1f19e9a06f2d |
children | c07461ca34d6 |
files | libinterp/corefcn/__tiff__.cc |
diffstat | 1 files changed, 85 insertions(+), 78 deletions(-) [+] |
line wrap: on
line diff
--- 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<double> (*(reinterpret_cast<uint8_t *> (data))); - break; - } + retval = static_cast<double> (*(reinterpret_cast<uint8_t *> (data))); + break; case TIFF_SHORT: - { - retval = static_cast<double> (*(reinterpret_cast<uint16_t *> (data))); - break; - } + retval = static_cast<double> (*(reinterpret_cast<uint16_t *> (data))); + break; case TIFF_LONG: - { - retval = static_cast<double> (*(reinterpret_cast<uint32_t *> (data))); - break; - } + retval = static_cast<double> (*(reinterpret_cast<uint32_t *> (data))); + break; case TIFF_LONG8: - { - retval = static_cast<double> (*(reinterpret_cast<uint64_t *> (data))); - break; - } + retval = static_cast<double> (*(reinterpret_cast<uint64_t *> (data))); + break; case TIFF_RATIONAL: - { - retval = *(reinterpret_cast<float *> (data)); - break; - } + retval = *(reinterpret_cast<float *> (data)); + break; case TIFF_SBYTE: - { - retval = static_cast<double> (*(reinterpret_cast<int8_t *> (data))); - break; - } + retval = static_cast<double> (*(reinterpret_cast<int8_t *> (data))); + break; case TIFF_SSHORT: - { - retval = static_cast<double> (*(reinterpret_cast<int16_t *> (data))); - break; - } + retval = static_cast<double> (*(reinterpret_cast<int16_t *> (data))); + break; case TIFF_SLONG: - { - retval = static_cast<double> (*(reinterpret_cast<int32_t *> (data))); - break; - } + retval = static_cast<double> (*(reinterpret_cast<int32_t *> (data))); + break; case TIFF_SLONG8: - { - retval = static_cast<double> (*(reinterpret_cast<int64_t *> (data))); - break; - } + retval = static_cast<double> (*(reinterpret_cast<int64_t *> (data))); + break; case TIFF_FLOAT: - { - retval = *(reinterpret_cast<float *> (data)); - break; - } + retval = *(reinterpret_cast<float *> (data)); + break; case TIFF_DOUBLE: - { - retval = *(reinterpret_cast<double *> (data)); - break; - } + retval = *(reinterpret_cast<double *> (data)); + break; case TIFF_SRATIONAL: - { - retval = *(reinterpret_cast<float *> (data)); - break; - } + retval = *(reinterpret_cast<float *> (data)); + break; case TIFF_IFD: + retval = static_cast<double> (*(reinterpret_cast<uint32_t *> (data))); + break; case TIFF_IFD8: - error ("Unimplemented IFFD data type"); + retval = static_cast<double> (*(reinterpret_cast<uint64_t *> (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<uint32_t *> (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<uint64_t *> (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<uint64_t []> subifd_offsets + = std::make_unique<uint64_t []> (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 <uint32_t *> (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 <uint32_t *> (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<double> (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");