comparison libinterp/corefcn/__tiff__.cc @ 31201:e5e8cb049b4b

__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.
author magedrifaat <magedrifaat@gmail.com>
date Fri, 02 Sep 2022 20:52:47 +0200
parents 4e8152ccc61a
children be6ccdcd5775
comparison
equal deleted inserted replaced
31200:4e8152ccc61a 31201:e5e8cb049b4b
3600 return octave_value_list(octave_scalar_map (tag_ov_map)); 3600 return octave_value_list(octave_scalar_map (tag_ov_map));
3601 #else 3601 #else
3602 err_disabled_feature ("F__tiff_make_tagid__", "Tiff"); 3602 err_disabled_feature ("F__tiff_make_tagid__", "Tiff");
3603 #endif 3603 #endif
3604 } 3604 }
3605
3606 DEFUN (__tiff_imfinfo__, args, ,
3607 "Handler for imfinfo that uses Tiff interface")
3608 {
3609 #if defined (HAVE_TIFF)
3610 int nargin = args.length ();
3611
3612 if (nargin < 1)
3613 error ("imfinfo: missing filename argument");
3614
3615 if (! args(0).is_string ())
3616 error ("imfinfo: filename must be a string");
3617
3618 std::string filename = args(0).string_value ();
3619
3620 const sys::file_stat fs (filename);
3621 if (! fs)
3622 error ("imfinfo: error reading '%s': %s", filename.c_str (),
3623 fs.error ().c_str ());
3624
3625 TIFF *tif = TIFFOpen (filename.c_str (), "rc");
3626 if (! tif)
3627 error ("imfinfo: error reading '%s': LibTIFF failed to read file",
3628 filename.c_str ());
3629
3630 // The destructor for this object will be called when the function returnd
3631 // or in case of an error so the file will always get closed at the end
3632 octave_tiff_handle tiff_handle (tif);
3633
3634 // A lot of the logic here is copied from __magick_finfo__ due to the
3635 // great similarity between the two functions but this function is
3636 // format specific so a lot of the details are different
3637 uint16_t dir_count = TIFFNumberOfDirectories (tif);
3638
3639 // Null terminated char* list to be used to create a string_vector
3640 static const char *fields[] = {
3641 "Filename",
3642 "FileModDate",
3643 "FileSize",
3644 "Format",
3645 "FormatVersion",
3646 "Width",
3647 "Height",
3648 "BitDepth",
3649 "ColorType",
3650 "FormatSignature",
3651 "ByteOrder",
3652 "NewSubFileType",
3653 "BitsPerSample",
3654 "Compression",
3655 "PhotometricInterpretation",
3656 "StripOffsets",
3657 "SamplesPerPixel",
3658 "RowsPerStrip",
3659 "StripByteCounts",
3660 "XResolution",
3661 "YResolution",
3662 "ResolutionUnit",
3663 "Colormap",
3664 "PlanarConfiguration",
3665 "TileWidth",
3666 "TileLength",
3667 "TileOffsets",
3668 "TileByteCounts",
3669 "Orientation",
3670 "FillOrder",
3671 "GrayResponseUnit",
3672 "MaxSampleValue",
3673 "MinSampleValue",
3674 "Thresholding",
3675 "Offset",
3676 "ImageDescription",
3677 nullptr
3678 };
3679
3680 // A map to be used as a struct array to hold a scalar_map for each
3681 // directory
3682 octave_map info (dim_vector (dir_count, 1), string_vector (fields));
3683
3684 // populate template_info with the info that is common between all
3685 // directories in the file
3686 octave_scalar_map template_info = (string_vector (fields));
3687 template_info.setfield ("Format", octave_value ("tif"));
3688 template_info.setfield ("FormatVersion", octave_value (""));
3689 const sys::localtime mtime (fs.mtime ());
3690 const std::string filetime = mtime.strftime ("%e-%b-%Y %H:%M:%S");
3691 template_info.setfield ("Filename", octave_value (filename));
3692 template_info.setfield ("FileModDate", octave_value (filetime));
3693 template_info.setfield ("FileSize", octave_value (fs.size ()));
3694
3695 // Extract the image signature (first 4 bytes in file)
3696 std::ifstream tif_file;
3697 #if defined (OCTAVE_USE_WINDOWS_API)
3698 std::wstring wname = sys::u8_to_wstring (filename);
3699 tif_file.open (wname.c_str (), std::ios_base::binary);
3700 #else
3701 tif_file.open (filename.c_str (), std::ios_base::binary);
3702 #endif
3703 uint8NDArray signature (dim_vector (1, 4));;
3704 tif_file.read (reinterpret_cast<char *> (signature.fortran_vec ()), 4);
3705 tif_file.close ();
3706 template_info.setfield ("FormatSignature", octave_value (signature));
3707
3708 std::string byte_order
3709 = TIFFIsBigEndian (tif)? "big-endian": "little-endian";
3710 template_info.setfield ("ByteOrder", octave_value (byte_order));
3711
3712 // Extract directory specific information
3713 for (uint16_t dir = 0; dir < dir_count; dir++)
3714 {
3715 octave_scalar_map dir_info (template_info);
3716
3717 // Switch to the directory
3718 if (! TIFFSetDirectory (tif, dir))
3719 error ("imfinfo: Failed to access frame %d\n", dir);
3720
3721 tiff_image_data image_data (tif);
3722 dir_info.setfield ("Width", octave_value (image_data.width));
3723
3724 dir_info.setfield ("Height", octave_value (image_data.height));
3725
3726 uint16_t bit_depth = image_data.samples_per_pixel
3727 * image_data.bits_per_sample;
3728 dir_info.setfield ("BitDepth", octave_value (bit_depth));
3729
3730 std::string planar = "unrecognized";
3731 if (image_data.planar_configuration == 1)
3732 planar = "Chunky";
3733 else if (image_data.planar_configuration == 2)
3734 planar = "Separate";
3735 dir_info.setfield ("PlanarConfiguration", octave_value (planar));
3736
3737 // Extract photometric information as well as color map if exists
3738 std::string color_str, photometric_str;
3739 uint16_t photometric = PHOTOMETRIC_MINISBLACK;
3740 octave_value cmap = octave_value (Matrix ());
3741 const TIFFField *fip;
3742 TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photometric);
3743 switch (photometric)
3744 {
3745 case PHOTOMETRIC_MINISBLACK:
3746 color_str = "grayscale";
3747 photometric_str = "BlasckIsZero";
3748 break;
3749 case PHOTOMETRIC_MINISWHITE:
3750 color_str = "grayscale";
3751 photometric_str = "WhiteIsZero";
3752 break;
3753 case PHOTOMETRIC_RGB:
3754 color_str = "truecolor";
3755 photometric_str = "RGB";
3756 break;
3757 case PHOTOMETRIC_PALETTE:
3758 color_str = "indexed";
3759 photometric_str = "RGB Palette";
3760 fip = TIFFFieldWithTag (tif, TIFFTAG_COLORMAP);
3761 cmap = get_field_data (tif, fip);
3762 break;
3763 case PHOTOMETRIC_SEPARATED:
3764 color_str = "CMYK";
3765 photometric_str = "CMYK";
3766 break;
3767 default:
3768 color_str = "undefined";
3769 photometric_str = "undefined";
3770 }
3771 dir_info.setfield ("ColorType", octave_value(color_str));
3772 dir_info.setfield ("PhotometricInterpretation",
3773 octave_value(photometric_str));
3774 dir_info.setfield ("Colormap", octave_value (cmap));
3775
3776 fip = TIFFFieldWithTag (tif, TIFFTAG_SUBFILETYPE);
3777 dir_info.setfield ("NewSubFileType", get_field_data (tif, fip));
3778
3779 fip = TIFFFieldWithTag (tif, TIFFTAG_BITSPERSAMPLE);
3780 dir_info.setfield ("BitsPerSample", get_field_data (tif, fip));
3781
3782 fip = TIFFFieldWithTag (tif, TIFFTAG_SAMPLESPERPIXEL);
3783 dir_info.setfield ("SamplesPerPixel", get_field_data (tif, fip));
3784
3785 // Use LibTIFF's compression codec to extract compression scheme name
3786 uint16_t compression;
3787 TIFFGetFieldDefaulted (tif, TIFFTAG_COMPRESSION, &compression);
3788 std::string comp_str = "unrecognized";
3789 const TIFFCodec *codec = TIFFFindCODEC (compression);
3790 if (codec)
3791 comp_str = codec->name;
3792 dir_info.setfield ("Compression", octave_value (comp_str));
3793
3794 // Set strip-specific and tile-specific fields accordingly
3795 bool tiled = TIFFIsTiled (tif);
3796 fip = TIFFFieldWithTag (tif, TIFFTAG_TILELENGTH);
3797 dir_info.setfield ("TileLength", tiled? get_field_data (tif, fip)
3798 : octave_value (Matrix ()));
3799 fip = TIFFFieldWithTag (tif, TIFFTAG_TILEWIDTH);
3800 dir_info.setfield ("TileWidth", tiled? get_field_data (tif, fip)
3801 : octave_value (Matrix ()));
3802 fip = TIFFFieldWithTag (tif, TIFFTAG_TILEOFFSETS);
3803 dir_info.setfield ("TileOffsets", tiled? get_field_data (tif, fip)
3804 : octave_value (Matrix ()));
3805 fip = TIFFFieldWithTag (tif, TIFFTAG_TILEBYTECOUNTS);
3806 dir_info.setfield ("TileByteCounts", tiled? get_field_data (tif, fip)
3807 : octave_value (Matrix ()));
3808 fip = TIFFFieldWithTag (tif, TIFFTAG_ROWSPERSTRIP);
3809 dir_info.setfield ("RowsPerStrip", tiled? octave_value (Matrix ())
3810 : get_field_data (tif, fip));
3811 fip = TIFFFieldWithTag (tif, TIFFTAG_STRIPOFFSETS);
3812 dir_info.setfield ("StripOffsets", tiled? octave_value (Matrix ())
3813 : get_field_data (tif, fip));
3814 fip = TIFFFieldWithTag (tif, TIFFTAG_STRIPBYTECOUNTS);
3815 dir_info.setfield ("StripByteCounts", tiled? octave_value (Matrix ())
3816 : get_field_data (tif, fip));
3817
3818 uint16_t res;
3819 if (TIFFGetField (tif, TIFFTAG_XRESOLUTION, &res))
3820 dir_info.setfield ("XResolution", octave_value (res));
3821 else
3822 dir_info.setfield ("XResolution", octave_value (Matrix ()));
3823
3824 if (TIFFGetField (tif, TIFFTAG_YRESOLUTION, &res))
3825 dir_info.setfield ("YResolution", octave_value (res));
3826 else
3827 dir_info.setfield ("YResolution", octave_value (Matrix ()));
3828
3829 TIFFGetFieldDefaulted (tif, TIFFTAG_RESOLUTIONUNIT, &res);
3830 std::string res_unit = "Inch";
3831 if (res == 1)
3832 res_unit = "None";
3833 else if (res == 3)
3834 res_unit = "Centimeter";
3835 dir_info.setfield ("ResolutionUnit", octave_value(res_unit));
3836
3837 fip = TIFFFieldWithTag (tif, TIFFTAG_ORIENTATION);
3838 dir_info.setfield ("Orientation", get_field_data (tif, fip));
3839
3840 fip = TIFFFieldWithTag (tif, TIFFTAG_FILLORDER);
3841 dir_info.setfield ("FillOrder", get_field_data (tif, fip));
3842
3843 // The current version of LibTIFF (4.4.0) doesn't set the deafult
3844 // value for GrayResponseUnit corectly, so we can't use
3845 // TIFFGetFieldDefaulted, instead we set the default value ourselves
3846 double gray_response_unit = 0.01;
3847 uint16_t gray_unit_val;
3848 if (TIFFGetField (tif, TIFFTAG_GRAYRESPONSEUNIT, &gray_unit_val))
3849 {
3850 switch (gray_unit_val)
3851 {
3852 case GRAYRESPONSEUNIT_10S:
3853 gray_response_unit = 0.1;
3854 break;
3855 case GRAYRESPONSEUNIT_100S:
3856 gray_response_unit = 0.01;
3857 break;
3858 case GRAYRESPONSEUNIT_1000S:
3859 gray_response_unit = 0.001;
3860 break;
3861 case GRAYRESPONSEUNIT_10000S:
3862 gray_response_unit = 0.0001;
3863 break;
3864 case GRAYRESPONSEUNIT_100000S:
3865 gray_response_unit = 0.00001;
3866 break;
3867 }
3868 }
3869 dir_info.setfield ("GrayResponseUnit",
3870 octave_value (gray_response_unit));
3871
3872 // The current version of LibTIFF (4.4.0) doesn't set the deafult
3873 // value for MinSampleValue and MaxSampleValue, so we can't use
3874 // TIFFGetFieldDefaulted, instead we set the default value ourselves
3875 uint16_t min_sample_value = 0;
3876 uint16_t max_sample_value = (1<<image_data.bits_per_sample) - 1;
3877 TIFFGetField (tif, TIFFTAG_MINSAMPLEVALUE, &min_sample_value);
3878 TIFFGetField (tif, TIFFTAG_MAXSAMPLEVALUE, &max_sample_value);
3879 dim_vector vector_dims = dim_vector (1, image_data.samples_per_pixel);
3880 NDArray min_sample_values (vector_dims, min_sample_value);
3881 NDArray max_sample_values (vector_dims, max_sample_value);
3882 dir_info.setfield ("MinSampleValue",
3883 octave_value (min_sample_values));
3884 dir_info.setfield ("MaxSampleValue",
3885 octave_value (max_sample_values));
3886
3887 fip = TIFFFieldWithTag (tif, TIFFTAG_THRESHHOLDING);
3888 dir_info.setfield ("Thresholding", get_field_data (tif, fip));
3889
3890 dir_info.setfield ("Offset",
3891 octave_value (TIFFCurrentDirOffset (tif)));
3892
3893 char *desc = NULL;
3894 if (TIFFGetField (tif, TIFFTAG_IMAGEDESCRIPTION, &desc))
3895 dir_info.setfield ("ImageDescription", octave_value (desc));
3896 else
3897 dir_info.setfield ("ImageDescription", octave_value (""));
3898
3899 // Insert the directory information into the map
3900 info.fast_elem_insert (dir, dir_info);
3901 }
3902
3903 return ovl (info);
3904 #else
3905 err_disabled_feature ("imfinfo", "Tiff");
3906 #endif
3907 }
3908 } 3605 }