Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:36:59

0001 //
0002 // Copyright 2007-2008 Andreas Pokorny, Christian Henning
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 #ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_DEVICE_HPP
0009 #define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_DEVICE_HPP
0010 
0011 #include <boost/gil/extension/io/tiff/tags.hpp>
0012 #include <boost/gil/extension/io/tiff/detail/log.hpp>
0013 #include <boost/gil/detail/mp11.hpp>
0014 #include <boost/gil/io/base.hpp>
0015 #include <boost/gil/io/device.hpp>
0016 
0017 #include <algorithm>
0018 #include <cstdint>
0019 #include <memory>
0020 #include <sstream>
0021 #include <type_traits>
0022 
0023 // taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
0024 #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
0025     extern "C" {
0026 #endif
0027 
0028 #include <tiff.h>
0029 #include <tiffio.h>
0030 
0031 #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
0032     }
0033 #endif
0034 
0035 #include <tiffio.hxx>
0036 
0037 namespace boost { namespace gil { namespace detail {
0038 
0039 template <int n_args>
0040 struct get_property_f {
0041     template <typename Property>
0042     bool call_me(typename Property:: type& value, std::shared_ptr<TIFF>& file);
0043 };
0044 
0045 template <int n_args>
0046 struct set_property_f {
0047     template <typename Property>
0048     bool call_me(const typename Property:: type& value, std::shared_ptr<TIFF>& file) const;
0049 };
0050 
0051 template <> struct get_property_f <1>
0052 {
0053     // For single-valued properties
0054     template <typename Property>
0055     bool call_me(typename Property::type & value, std::shared_ptr<TIFF>& file) const
0056     {
0057         // @todo: defaulted, really?
0058         return (1 == TIFFGetFieldDefaulted( file.get()
0059                 , Property:: tag
0060                 , & value));
0061     }
0062 };
0063 
0064 template <> struct get_property_f <2>
0065 {
0066     // Specialisation for multi-valued properties. @todo: add one of
0067     // these for the three-parameter fields too.
0068     template <typename Property>
0069     bool call_me(typename Property::type& vs, std::shared_ptr<TIFF>& file) const
0070     {
0071         mp11::mp_at<typename Property::arg_types, std::integral_constant<int, 0>> length;
0072         mp11::mp_at<typename Property::arg_types, std::integral_constant<int, 1>> pointer;
0073         if (1 == TIFFGetFieldDefaulted(file.get(), Property:: tag, & length, & pointer))
0074         {
0075             std:: copy_n(static_cast<typename Property::type::const_pointer>(pointer), length, std:: back_inserter(vs));
0076             return true;
0077         } else
0078             return false;
0079     }
0080 };
0081 
0082 template <> struct set_property_f <1>
0083 {
0084     // For single-valued properties
0085     template <typename Property>
0086     inline
0087     bool call_me(typename Property:: type const & value, std::shared_ptr<TIFF>& file) const
0088     {
0089         return (1 == TIFFSetField( file.get()
0090                 , Property:: tag
0091                 , value));
0092     }
0093 };
0094 
0095 template <> struct set_property_f <2>
0096 {
0097     // Specialisation for multi-valued properties. @todo: add one
0098     // of these for the three-parameter fields too. Actually we
0099     // will need further templation / specialisation for the
0100     // two-element fields which aren't a length and a data buffer
0101     // (e.g. http://www.awaresystems.be/imaging/tiff/tifftags/dotrange.html
0102     // )
0103     template <typename Property>
0104     inline
0105     bool call_me(typename Property:: type const & values, std::shared_ptr<TIFF>& file) const
0106     {
0107         using length_t = mp11::mp_at_c<typename Property::arg_types, 0>;
0108         auto const length = static_cast<length_t>(values.size());
0109 
0110         using pointer_t = mp11::mp_at_c<typename Property::arg_types, 1>;
0111         auto const pointer = static_cast<pointer_t>(&(values.front()));
0112         return (1 == TIFFSetField( file.get(), Property:: tag, length, pointer));
0113     }
0114 };
0115 
0116 template< typename Log >
0117 class tiff_device_base
0118 {
0119 public:
0120     using tiff_file_t = std::shared_ptr<TIFF>;
0121 
0122     tiff_device_base()
0123     {}
0124 
0125     tiff_device_base( TIFF* tiff_file )
0126     : _tiff_file( tiff_file
0127                 , TIFFClose )
0128     {}
0129 
0130     template <typename Property>
0131     bool get_property( typename Property::type& value  )
0132     {
0133         return get_property_f<mp11::mp_size<typename Property::arg_types>::value>().template call_me<Property>(value, _tiff_file);
0134     }
0135 
0136     template <typename Property>
0137     inline
0138     bool set_property( const typename Property::type& value )
0139     {
0140       // http://www.remotesensing.org/libtiff/man/TIFFSetField.3tiff.html
0141       return set_property_f<mp11::mp_size<typename Property::arg_types>::value>().template call_me<Property>(value, _tiff_file);
0142     }
0143 
0144     // TIFFIsByteSwapped returns a non-zero value if the image data was in a different
0145     // byte-order than the host machine. Zero is returned if the TIFF file and local
0146     // host byte-orders are the same. Note that TIFFReadTile(), TIFFReadStrip() and TIFFReadScanline()
0147     // functions already normally perform byte swapping to local host order if needed.
0148     bool are_bytes_swapped()
0149     {
0150         return ( TIFFIsByteSwapped( _tiff_file.get() )) ? true : false;
0151     }
0152 
0153     bool is_tiled() const
0154     {
0155         return ( TIFFIsTiled( _tiff_file.get() )) ? true : false;
0156     }
0157 
0158     unsigned int get_default_strip_size()
0159     {
0160         return TIFFDefaultStripSize( _tiff_file.get()
0161                                    , 0 );
0162     }
0163 
0164     std::size_t get_scanline_size()
0165     {
0166       return TIFFScanlineSize( _tiff_file.get() );
0167     }
0168 
0169     std::size_t get_tile_size()
0170     {
0171       return TIFFTileSize( _tiff_file.get() );
0172     }
0173 
0174 
0175     int get_field_defaulted( uint16_t*& red
0176                            , uint16_t*& green
0177                            , uint16_t*& blue
0178                            )
0179     {
0180         return TIFFGetFieldDefaulted( _tiff_file.get()
0181                                     , TIFFTAG_COLORMAP
0182                                     , &red
0183                                     , &green
0184                                     , &blue
0185                                     );
0186     }
0187 
0188     template< typename Buffer >
0189     void read_scanline( Buffer&        buffer
0190                       , std::ptrdiff_t row
0191                       , tsample_t      plane
0192                       )
0193     {
0194         io_error_if( TIFFReadScanline( _tiff_file.get()
0195                                      , reinterpret_cast< tdata_t >( &buffer.front() )
0196                                      , static_cast<std::uint32_t>( row )
0197                                      , plane           ) == -1
0198                    , "Read error."
0199                    );
0200     }
0201 
0202     void read_scanline( byte_t*        buffer
0203                       , std::ptrdiff_t row
0204                       , tsample_t      plane
0205                       )
0206     {
0207         io_error_if( TIFFReadScanline( _tiff_file.get()
0208                                      , reinterpret_cast< tdata_t >( buffer )
0209                                      , static_cast<std::uint32_t>( row )
0210                                      , plane           ) == -1
0211                    , "Read error."
0212                    );
0213     }
0214 
0215     template< typename Buffer >
0216     void read_tile( Buffer&        buffer
0217                   , std::ptrdiff_t x
0218                   , std::ptrdiff_t y
0219                   , std::ptrdiff_t z
0220                   , tsample_t      plane
0221                   )
0222     {
0223         if( TIFFReadTile( _tiff_file.get()
0224                         , reinterpret_cast< tdata_t >( &buffer.front() )
0225                         , static_cast< std::uint32_t >( x )
0226                         , static_cast< std::uint32_t >( y )
0227                         , static_cast< std::uint32_t >( z )
0228                         , plane
0229                         ) == -1 )
0230         {
0231             std::ostringstream oss;
0232             oss << "Read tile error (" << x << "," << y << "," << z << "," << plane << ").";
0233             io_error(oss.str().c_str());
0234         }
0235     }
0236 
0237     template< typename Buffer >
0238     void write_scaline( Buffer&       buffer
0239                       , std::uint32_t row
0240                       , tsample_t     plane
0241                       )
0242     {
0243        io_error_if( TIFFWriteScanline( _tiff_file.get()
0244                                      , &buffer.front()
0245                                      , row
0246                                      , plane
0247                                      ) == -1
0248                    , "Write error"
0249                    );
0250     }
0251 
0252     void write_scaline( byte_t*        buffer
0253                       , std::uint32_t  row
0254                       , tsample_t      plane
0255                       )
0256     {
0257        io_error_if( TIFFWriteScanline( _tiff_file.get()
0258                                      , buffer
0259                                      , row
0260                                      , plane
0261                                      ) == -1
0262                    , "Write error"
0263                    );
0264     }
0265 
0266     template< typename Buffer >
0267     void write_tile( Buffer&         buffer
0268                    , std::uint32_t   x
0269                    , std::uint32_t   y
0270                    , std::uint32_t   z
0271                    , tsample_t       plane
0272                    )
0273     {
0274        if( TIFFWriteTile( _tiff_file.get()
0275                         , &buffer.front()
0276                         , x
0277                         , y
0278                         , z
0279                         , plane
0280                         ) == -1 )
0281            {
0282                std::ostringstream oss;
0283                oss << "Write tile error (" << x << "," << y << "," << z << "," << plane << ").";
0284                io_error(oss.str().c_str());
0285            }
0286     }
0287 
0288     void set_directory( tdir_t directory )
0289     {
0290         io_error_if( TIFFSetDirectory( _tiff_file.get()
0291                                      , directory
0292                                      ) != 1
0293                    , "Failing to set directory"
0294                    );
0295     }
0296 
0297     // return false if the given tile width or height is not TIFF compliant (multiple of 16) or larger than image size, true otherwise
0298     bool check_tile_size( tiff_tile_width::type&  width
0299                         , tiff_tile_length::type& height
0300 
0301                         )
0302     {
0303         bool result = true;
0304         std::uint32_t tw = static_cast< std::uint32_t >( width  );
0305         std::uint32_t th = static_cast< std::uint32_t >( height );
0306 
0307         TIFFDefaultTileSize( _tiff_file.get()
0308                            , &tw
0309                            , &th
0310                            );
0311 
0312         if(width==0 || width%16!=0)
0313         {
0314             width = tw;
0315             result = false;
0316         }
0317         if(height==0 || height%16!=0)
0318         {
0319             height = th;
0320             result = false;
0321         }
0322         return result;
0323     }
0324 
0325 protected:
0326 
0327    tiff_file_t _tiff_file;
0328 
0329     Log _log;
0330 };
0331 
0332 /*!
0333  *
0334  * file_stream_device specialization for tiff images, which are based on TIFF*.
0335  */
0336 template<>
0337 class file_stream_device< tiff_tag > : public tiff_device_base< tiff_no_log >
0338 {
0339 public:
0340 
0341     struct read_tag {};
0342     struct write_tag {};
0343 
0344     file_stream_device( std::string const& file_name, read_tag )
0345     {
0346         TIFF* tiff;
0347 
0348         io_error_if( ( tiff = TIFFOpen( file_name.c_str(), "r" )) == nullptr
0349                    , "file_stream_device: failed to open file" );
0350 
0351         _tiff_file = tiff_file_t( tiff, TIFFClose );
0352     }
0353 
0354     file_stream_device( std::string const& file_name, write_tag )
0355     {
0356         TIFF* tiff;
0357 
0358         io_error_if( ( tiff = TIFFOpen( file_name.c_str(), "w" )) == nullptr
0359                    , "file_stream_device: failed to open file" );
0360 
0361         _tiff_file = tiff_file_t( tiff, TIFFClose );
0362     }
0363 
0364     file_stream_device( TIFF* tiff_file )
0365     : tiff_device_base( tiff_file )
0366     {}
0367 };
0368 
0369 /*!
0370  *
0371  * ostream_device specialization for tiff images.
0372  */
0373 template<>
0374 class ostream_device< tiff_tag > : public tiff_device_base< tiff_no_log >
0375 {
0376 public:
0377     ostream_device( std::ostream & out )
0378     : _out( out )
0379     {
0380         TIFF* tiff;
0381 
0382         io_error_if( ( tiff = TIFFStreamOpen( ""
0383                                             , &_out
0384                                             )
0385                       ) == nullptr
0386                    , "ostream_device: failed to stream"
0387                    );
0388 
0389         _tiff_file = tiff_file_t( tiff, TIFFClose );
0390     }
0391 
0392 private:
0393     ostream_device& operator=( const ostream_device& ) { return *this; }
0394 
0395 private:
0396 
0397     std::ostream& _out;
0398 };
0399 
0400 /*!
0401  *
0402  * ostream_device specialization for tiff images.
0403  */
0404 template<>
0405 class istream_device< tiff_tag > : public tiff_device_base< tiff_no_log >
0406 {
0407 public:
0408     istream_device( std::istream & in )
0409     : _in( in )
0410     {
0411         TIFF* tiff;
0412 
0413         io_error_if( ( tiff = TIFFStreamOpen( ""
0414                                             , &_in
0415                                             )
0416                      ) == nullptr
0417                    , "istream_device: failed to stream"
0418                    );
0419 
0420         _tiff_file = tiff_file_t( tiff, TIFFClose );
0421     }
0422 
0423 private:
0424     istream_device& operator=( const istream_device& ) { return *this; }
0425 
0426 private:
0427 
0428     std::istream& _in;
0429 };
0430 
0431 /*
0432 template< typename T, typename D >
0433 struct is_adaptable_input_device< tiff_tag, T, D > : std::false_type {};
0434 */
0435 
0436 template<typename FormatTag>
0437 struct is_adaptable_input_device<FormatTag, TIFF*, void> : std::true_type
0438 {
0439     using device_type = file_stream_device<FormatTag>;
0440 };
0441 
0442 template<typename FormatTag>
0443 struct is_adaptable_output_device<FormatTag, TIFF*, void> : std::true_type
0444 {
0445     using device_type = file_stream_device<FormatTag>;
0446 };
0447 
0448 
0449 template <typename Channel>
0450 struct sample_format : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
0451 template<>
0452 struct sample_format<uint8_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
0453 template<>
0454 struct sample_format<uint16_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
0455 template<>
0456 struct sample_format<uint32_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
0457 template<>
0458 struct sample_format<float32_t> : std::integral_constant<int, SAMPLEFORMAT_IEEEFP> {};
0459 template<>
0460 struct sample_format<double> : std::integral_constant<int, SAMPLEFORMAT_IEEEFP> {};
0461 template<>
0462 struct sample_format<int8_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
0463 template<>
0464 struct sample_format<int16_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
0465 template<>
0466 struct sample_format<int32_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
0467 
0468 template <typename Channel>
0469 struct photometric_interpretation {};
0470 template<>
0471 struct photometric_interpretation<gray_t>
0472     : std::integral_constant<int, PHOTOMETRIC_MINISBLACK> {};
0473 template<>
0474 struct photometric_interpretation<rgb_t>
0475     : std::integral_constant<int, PHOTOMETRIC_RGB> {};
0476 template<>
0477 struct photometric_interpretation<rgba_t>
0478     : std::integral_constant<int, PHOTOMETRIC_RGB> {};
0479 template<>
0480 struct photometric_interpretation<cmyk_t>
0481     : std::integral_constant<int, PHOTOMETRIC_SEPARATED> {};
0482 
0483 } // namespace detail
0484 } // namespace gil
0485 } // namespace boost
0486 
0487 #endif