Mercurial > octave-libtiff
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 } |