# HG changeset patch # User magedrifaat # Date 1662144767 -7200 # Node ID e5e8cb049b4b3ea62e8e42ffc38adcea987b8836 # Parent 4e8152ccc61aa972d4a2fa8e2dc72506b82aaea3 __tiff_imfinfo__: converted to private octave function * libinterp/corefcn/__tiff__.cc: removed internal function __tiff__imfinfo__. * scipts/image/private/__tiff_imfinfo__.m: implemented private octave function __tiff_imfinfo__. * scripts/image/module.mk: added entry for the new function. diff -r 4e8152ccc61a -r e5e8cb049b4b libinterp/corefcn/__tiff__.cc --- a/libinterp/corefcn/__tiff__.cc Fri Sep 02 03:41:05 2022 +0200 +++ b/libinterp/corefcn/__tiff__.cc Fri Sep 02 20:52:47 2022 +0200 @@ -3602,307 +3602,4 @@ err_disabled_feature ("F__tiff_make_tagid__", "Tiff"); #endif } - - DEFUN (__tiff_imfinfo__, args, , - "Handler for imfinfo that uses Tiff interface") - { -#if defined (HAVE_TIFF) - int nargin = args.length (); - - if (nargin < 1) - error ("imfinfo: missing filename argument"); - - if (! args(0).is_string ()) - error ("imfinfo: filename must be a string"); - - std::string filename = args(0).string_value (); - - const sys::file_stat fs (filename); - if (! fs) - error ("imfinfo: error reading '%s': %s", filename.c_str (), - fs.error ().c_str ()); - - TIFF *tif = TIFFOpen (filename.c_str (), "rc"); - if (! tif) - error ("imfinfo: error reading '%s': LibTIFF failed to read file", - filename.c_str ()); - - // The destructor for this object will be called when the function returnd - // or in case of an error so the file will always get closed at the end - octave_tiff_handle tiff_handle (tif); - - // A lot of the logic here is copied from __magick_finfo__ due to the - // great similarity between the two functions but this function is - // format specific so a lot of the details are different - uint16_t dir_count = TIFFNumberOfDirectories (tif); - - // Null terminated char* list to be used to create a string_vector - static const char *fields[] = { - "Filename", - "FileModDate", - "FileSize", - "Format", - "FormatVersion", - "Width", - "Height", - "BitDepth", - "ColorType", - "FormatSignature", - "ByteOrder", - "NewSubFileType", - "BitsPerSample", - "Compression", - "PhotometricInterpretation", - "StripOffsets", - "SamplesPerPixel", - "RowsPerStrip", - "StripByteCounts", - "XResolution", - "YResolution", - "ResolutionUnit", - "Colormap", - "PlanarConfiguration", - "TileWidth", - "TileLength", - "TileOffsets", - "TileByteCounts", - "Orientation", - "FillOrder", - "GrayResponseUnit", - "MaxSampleValue", - "MinSampleValue", - "Thresholding", - "Offset", - "ImageDescription", - nullptr - }; - - // A map to be used as a struct array to hold a scalar_map for each - // directory - octave_map info (dim_vector (dir_count, 1), string_vector (fields)); - - // populate template_info with the info that is common between all - // directories in the file - octave_scalar_map template_info = (string_vector (fields)); - template_info.setfield ("Format", octave_value ("tif")); - template_info.setfield ("FormatVersion", octave_value ("")); - const sys::localtime mtime (fs.mtime ()); - const std::string filetime = mtime.strftime ("%e-%b-%Y %H:%M:%S"); - template_info.setfield ("Filename", octave_value (filename)); - template_info.setfield ("FileModDate", octave_value (filetime)); - template_info.setfield ("FileSize", octave_value (fs.size ())); - - // Extract the image signature (first 4 bytes in file) - std::ifstream tif_file; -#if defined (OCTAVE_USE_WINDOWS_API) - std::wstring wname = sys::u8_to_wstring (filename); - tif_file.open (wname.c_str (), std::ios_base::binary); -#else - tif_file.open (filename.c_str (), std::ios_base::binary); -#endif - uint8NDArray signature (dim_vector (1, 4));; - tif_file.read (reinterpret_cast (signature.fortran_vec ()), 4); - tif_file.close (); - template_info.setfield ("FormatSignature", octave_value (signature)); - - std::string byte_order - = TIFFIsBigEndian (tif)? "big-endian": "little-endian"; - template_info.setfield ("ByteOrder", octave_value (byte_order)); - - // Extract directory specific information - for (uint16_t dir = 0; dir < dir_count; dir++) - { - octave_scalar_map dir_info (template_info); - - // Switch to the directory - if (! TIFFSetDirectory (tif, dir)) - error ("imfinfo: Failed to access frame %d\n", dir); - - tiff_image_data image_data (tif); - dir_info.setfield ("Width", octave_value (image_data.width)); - - dir_info.setfield ("Height", octave_value (image_data.height)); - - uint16_t bit_depth = image_data.samples_per_pixel - * image_data.bits_per_sample; - dir_info.setfield ("BitDepth", octave_value (bit_depth)); - - std::string planar = "unrecognized"; - if (image_data.planar_configuration == 1) - planar = "Chunky"; - else if (image_data.planar_configuration == 2) - planar = "Separate"; - dir_info.setfield ("PlanarConfiguration", octave_value (planar)); - - // Extract photometric information as well as color map if exists - std::string color_str, photometric_str; - uint16_t photometric = PHOTOMETRIC_MINISBLACK; - octave_value cmap = octave_value (Matrix ()); - const TIFFField *fip; - TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photometric); - switch (photometric) - { - case PHOTOMETRIC_MINISBLACK: - color_str = "grayscale"; - photometric_str = "BlasckIsZero"; - break; - case PHOTOMETRIC_MINISWHITE: - color_str = "grayscale"; - photometric_str = "WhiteIsZero"; - break; - case PHOTOMETRIC_RGB: - color_str = "truecolor"; - photometric_str = "RGB"; - break; - case PHOTOMETRIC_PALETTE: - color_str = "indexed"; - photometric_str = "RGB Palette"; - fip = TIFFFieldWithTag (tif, TIFFTAG_COLORMAP); - cmap = get_field_data (tif, fip); - break; - case PHOTOMETRIC_SEPARATED: - color_str = "CMYK"; - photometric_str = "CMYK"; - break; - default: - color_str = "undefined"; - photometric_str = "undefined"; - } - dir_info.setfield ("ColorType", octave_value(color_str)); - dir_info.setfield ("PhotometricInterpretation", - octave_value(photometric_str)); - dir_info.setfield ("Colormap", octave_value (cmap)); - - fip = TIFFFieldWithTag (tif, TIFFTAG_SUBFILETYPE); - dir_info.setfield ("NewSubFileType", get_field_data (tif, fip)); - - fip = TIFFFieldWithTag (tif, TIFFTAG_BITSPERSAMPLE); - dir_info.setfield ("BitsPerSample", get_field_data (tif, fip)); - - fip = TIFFFieldWithTag (tif, TIFFTAG_SAMPLESPERPIXEL); - dir_info.setfield ("SamplesPerPixel", get_field_data (tif, fip)); - - // Use LibTIFF's compression codec to extract compression scheme name - uint16_t compression; - TIFFGetFieldDefaulted (tif, TIFFTAG_COMPRESSION, &compression); - std::string comp_str = "unrecognized"; - const TIFFCodec *codec = TIFFFindCODEC (compression); - if (codec) - comp_str = codec->name; - dir_info.setfield ("Compression", octave_value (comp_str)); - - // Set strip-specific and tile-specific fields accordingly - bool tiled = TIFFIsTiled (tif); - fip = TIFFFieldWithTag (tif, TIFFTAG_TILELENGTH); - dir_info.setfield ("TileLength", tiled? get_field_data (tif, fip) - : octave_value (Matrix ())); - fip = TIFFFieldWithTag (tif, TIFFTAG_TILEWIDTH); - dir_info.setfield ("TileWidth", tiled? get_field_data (tif, fip) - : octave_value (Matrix ())); - fip = TIFFFieldWithTag (tif, TIFFTAG_TILEOFFSETS); - dir_info.setfield ("TileOffsets", tiled? get_field_data (tif, fip) - : octave_value (Matrix ())); - fip = TIFFFieldWithTag (tif, TIFFTAG_TILEBYTECOUNTS); - dir_info.setfield ("TileByteCounts", tiled? get_field_data (tif, fip) - : octave_value (Matrix ())); - fip = TIFFFieldWithTag (tif, TIFFTAG_ROWSPERSTRIP); - dir_info.setfield ("RowsPerStrip", tiled? octave_value (Matrix ()) - : get_field_data (tif, fip)); - fip = TIFFFieldWithTag (tif, TIFFTAG_STRIPOFFSETS); - dir_info.setfield ("StripOffsets", tiled? octave_value (Matrix ()) - : get_field_data (tif, fip)); - fip = TIFFFieldWithTag (tif, TIFFTAG_STRIPBYTECOUNTS); - dir_info.setfield ("StripByteCounts", tiled? octave_value (Matrix ()) - : get_field_data (tif, fip)); - - uint16_t res; - if (TIFFGetField (tif, TIFFTAG_XRESOLUTION, &res)) - dir_info.setfield ("XResolution", octave_value (res)); - else - dir_info.setfield ("XResolution", octave_value (Matrix ())); - - if (TIFFGetField (tif, TIFFTAG_YRESOLUTION, &res)) - dir_info.setfield ("YResolution", octave_value (res)); - else - dir_info.setfield ("YResolution", octave_value (Matrix ())); - - TIFFGetFieldDefaulted (tif, TIFFTAG_RESOLUTIONUNIT, &res); - std::string res_unit = "Inch"; - if (res == 1) - res_unit = "None"; - else if (res == 3) - res_unit = "Centimeter"; - dir_info.setfield ("ResolutionUnit", octave_value(res_unit)); - - fip = TIFFFieldWithTag (tif, TIFFTAG_ORIENTATION); - dir_info.setfield ("Orientation", get_field_data (tif, fip)); - - fip = TIFFFieldWithTag (tif, TIFFTAG_FILLORDER); - dir_info.setfield ("FillOrder", get_field_data (tif, fip)); - - // The current version of LibTIFF (4.4.0) doesn't set the deafult - // value for GrayResponseUnit corectly, so we can't use - // TIFFGetFieldDefaulted, instead we set the default value ourselves - double gray_response_unit = 0.01; - uint16_t gray_unit_val; - if (TIFFGetField (tif, TIFFTAG_GRAYRESPONSEUNIT, &gray_unit_val)) - { - switch (gray_unit_val) - { - case GRAYRESPONSEUNIT_10S: - gray_response_unit = 0.1; - break; - case GRAYRESPONSEUNIT_100S: - gray_response_unit = 0.01; - break; - case GRAYRESPONSEUNIT_1000S: - gray_response_unit = 0.001; - break; - case GRAYRESPONSEUNIT_10000S: - gray_response_unit = 0.0001; - break; - case GRAYRESPONSEUNIT_100000S: - gray_response_unit = 0.00001; - break; - } - } - dir_info.setfield ("GrayResponseUnit", - octave_value (gray_response_unit)); - - // The current version of LibTIFF (4.4.0) doesn't set the deafult - // value for MinSampleValue and MaxSampleValue, so we can't use - // TIFFGetFieldDefaulted, instead we set the default value ourselves - uint16_t min_sample_value = 0; - uint16_t max_sample_value = (1< 0 + error ("imfinfo: Failed to access file: %s", msg); + endif + + for dir_idx = 1:dir_count + info(dir_idx).Filename = filename; + info(dir_idx).FileModDate = strftime ("%e-%b-%Y %H:%M:%S", + localtime (file_stat.ctime)); + info(dir_idx).FileSize = file_stat.size; + info(dir_idx).Format = "tif"; + info(dir_idx).FormatVersion = ""; + endfor + endif + + for dir_idx = 1:dir_count + tif.setDirectory (dir_idx); + + ## Read the file signature (first 4 bytes) + a = fopen (filename); + info(dir_idx).FormatSignature = reshape (fread (a, 4, "uint8"), [1, 4]); + fclose (a); + + info(dir_idx).Width = tif.getTag (Tiff.TagID.ImageWidth); + info(dir_idx).Height = tif.getTag (Tiff.TagID.ImageLength); + + info(dir_idx).SamplesPerPixel = tif.getTag (Tiff.TagID.SamplesPerPixel); + info(dir_idx).BitsPerSample = tif.getTag (Tiff.TagID.BitsPerSample); + info(dir_idx).BitDepth = info(dir_idx).SamplesPerPixel ... + * info(dir_idx).BitsPerSample; + + planar = tif.getTag (Tiff.TagID.PlanarConfiguration); + if planar == Tiff.PlanarConfiguration.Chunky + info(dir_idx).PlanarConfiguration = "Chunky"; + elseif planar == Tiff.PlanarConfiguration.Separate + info(dir_idx).PlanarConfiguration = "Separate"; + else + info(dir_idx).PlanarConfiguration = "Unrecognized"; + endif + + info(dir_idx).Colormap = []; + + photometrics = [Tiff.Photometric.MinIsBlack, Tiff.Photometric.MinIsWhite,... + Tiff.Photometric.RGB, Tiff.Photometric.Palette,... + Tiff.Photometric.Separated]; + color_types = {"grayscale", "grayscale", "truecolor", "indexed", "cmyk"}; + photometric_strs = {"BlackIsZero", "WhiteIsZero", "RGB",... + "RGB Palette", "CMYK"}; + + photometric = get_tag_defaulted (tif, Tiff.TagID.Photometric, + Tiff.Photometric.MinIsBlack); + idx = (photometric == photometrics); + if ! any (idx) + info(dir_idx).ColorType = "undefined"; + info(dir_idx).PhotometricInterpretation = "undefined"; + else + info(dir_idx).ColorType = color_types{idx}; + info(dir_idx).PhotometricInterpretation = photometric_strs{idx}; + if (photometric == Tiff.Photometric.Palette) + info(dir_idx).Colormap ... + = get_tag_defaulted (tif, Tiff.TagID.ColorMap, []); + endif + endif + + ## FIXME: implement isBigEndian + # if (tif.isBigEndian ()) + # info(dir_idx).ByteOrder = "big-endian"; + # else + # info(dir_idx).ByteOrder = "little-endian"; + # endif + + info(dir_idx).NewSubFileType ... + = get_tag_defaulted (tif, Tiff.TagID.SubFileType, + Tiff.SubFileType.Default); + + + info(dir_idx).Compression = "unrecognized"; + compressions = fieldnames (Tiff.Compression); + compression = tif.getTag (Tiff.TagID.Compression); + for comp_idx = 1:numel (compressions) + if (compression == Tiff.Compression.(compressions{comp_idx})) + info(dir_idx).Compression = compressions{comp_idx}; + break; + endif + endfor + + info(dir_idx).TileLength ... + = get_tag_defaulted (tif, Tiff.TagID.TileLength, []); + info(dir_idx).TileWidth ... + = get_tag_defaulted (tif, Tiff.TagID.TileWidth, []); + + info(dir_idx).TileOffsets ... + = get_tag_defaulted (tif, Tiff.TagID.TileOffsets, []); + info(dir_idx).TileByteCounts ... + = get_tag_defaulted (tif, Tiff.TagID.TileByteCounts, []); + + info(dir_idx).RowsPerStrip ... + = get_tag_defaulted (tif, Tiff.TagID.RowsPerStrip, []); + info(dir_idx).StripOffsets ... + = get_tag_defaulted (tif, Tiff.TagID.StripOffsets, []); + info(dir_idx).StripByteCounts ... + = get_tag_defaulted (tif, Tiff.TagID.StripByteCounts, []); + + info(dir_idx).XResolution ... + = get_tag_defaulted (tif, Tiff.TagID.XResolution, []); + info(dir_idx).YResolution ... + = get_tag_defaulted (tif, Tiff.TagID.YResolution, []); + + info(dir_idx).ResolutionUnit = "Inch"; + try + resunit = tif.getTag (tiff.TagID.ResolutionUnit); + if (resunit == Tiff.ResolutionUnit.None) + info(dir_idx).ResolutionUnit = "None"; + elseif (resuint == Tiff.ResolutionUnit.Centimeter) + info(dir_idx).ResolutionUnit = "Centimeter"; + endif + end_try_catch + + info(dir_idx).Orientation ... + = get_tag_defaulted (tif, Tiff.TagID.Orientation, + Tiff.Orientation.TopLeft); + + info(dir_idx).FillOrder ... + = get_tag_defaulted (tif, Tiff.TagID.FillOrder, 1); + + gray_unit = get_tag_defaulted (tif, Tiff.TagID.GrayResponseUnit, 2); + info(dir_idx).GrayResponseUnit = 1 / (10 ^ gray_unit); + + info(dir_idx).MinSampleValue ... + = get_tag_defaulted (tif, Tiff.TagID.MinSampleValue, 0); + info(dir_idx).MaxSampleValue ... + = get_tag_defaulted (tif, Tiff.TagID.MaxSampleValue, + 2^info(dir_idx).BitsPerSample - 1); + info(dir_idx).MinSampleValue ... + = repmat (info(dir_idx).MinSampleValue, + [1, info(dir_idx).SamplesPerPixel]); + info(dir_idx).MaxSampleValue ... + = repmat (info(dir_idx).MaxSampleValue, + [1, info(dir_idx).SamplesPerPixel]); + + info(dir_idx).Thresholding ... + = get_tag_defaulted (tif, Tiff.TagID.Thresholding, + Tiff.Thresholding.BiLevel); + + ## FIXME: implement getDirectoryOffset method + # info(dir_idx).Offset = tif.getDirectoryOffset (); + + info(dir_idx).ImageDescription ... + = get_tag_defaulted (tif, Tiff.TagID.ImageDescription, ""); + + info(dir_idx).Photoshop ... + = get_tag_defaulted (tif, Tiff.TagID.Photoshop, []); + + info(dir_idx).XMP ... + = get_tag_defaulted (tif, Tiff.TagID.XMP, ""); + endfor +endfunction + +function tag_val = get_tag_defaulted (tif, tag, default_val) + tag_val = default_val; + try + tag_val = tif.getTag (tag); + end_try_catch +endfunction diff -r 4e8152ccc61a -r e5e8cb049b4b scripts/image/private/__tiff_imread__.m --- a/scripts/image/private/__tiff_imread__.m Fri Sep 02 03:41:05 2022 +0200 +++ b/scripts/image/private/__tiff_imread__.m Fri Sep 02 20:52:47 2022 +0200 @@ -144,7 +144,7 @@ info.height = img.getTag (Tiff.TagID.ImageLength); info.width = img.getTag (Tiff.TagID.ImageWidth); info.bitdepth = img.getTag (Tiff.TagID.BitsPerSample); - info.nchannels = img.getTag (Tiff.TagID.BitsPerSample); + info.nchannels = img.getTag (Tiff.TagID.SamplesPerPixel); info.datatype = img.getTag (Tiff.TagID.SampleFormat); info.photometric = img.getTag (Tiff.TagID.Photometric); endfunction \ No newline at end of file