123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- //
- // Copyright 2007-2012 Christian Henning, Lubomir Bourdev
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- #ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_SCANLINE_READ_HPP
- #define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_SCANLINE_READ_HPP
- #include <boost/gil/extension/io/tiff/detail/device.hpp>
- #include <boost/gil/extension/io/tiff/detail/is_allowed.hpp>
- #include <boost/gil/extension/io/tiff/detail/reader_backend.hpp>
- #include <boost/gil/io/base.hpp>
- #include <boost/gil/io/bit_operations.hpp>
- #include <boost/gil/io/conversion_policies.hpp>
- #include <boost/gil/io/device.hpp>
- #include <boost/gil/io/reader_base.hpp>
- #include <boost/gil/io/row_buffer_helper.hpp>
- #include <boost/gil/io/scanline_read_iterator.hpp>
- #include <algorithm>
- #include <functional>
- #include <string>
- #include <type_traits>
- #include <vector>
- // taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
- #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
- extern "C" {
- #endif
- #include <tiff.h>
- #include <tiffio.h>
- #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
- }
- #endif
- namespace boost { namespace gil {
- ///
- /// TIFF scanline reader
- ///
- template< typename Device >
- class scanline_reader< Device
- , tiff_tag
- >
- : public reader_backend< Device
- , tiff_tag
- >
- {
- public:
- using tag_t = tiff_tag;
- using backend_t = reader_backend<Device, tag_t>;
- using this_t = scanline_reader<Device, tag_t>;
- using iterator_t = scanline_read_iterator<this_t>;
- scanline_reader( Device& device
- , const image_read_settings< tiff_tag >& settings
- )
- : backend_t( device
- , settings
- )
- {
- initialize();
- }
- /// Read part of image defined by View and return the data.
- void read( byte_t* dst, int pos )
- {
- _read_function( this, dst, pos );
- }
- /// Skip over a scanline.
- void skip( byte_t* dst, int pos )
- {
- this->_read_function( this, dst, pos );
- }
- iterator_t begin() { return iterator_t( *this ); }
- iterator_t end() { return iterator_t( *this, this->_info._height ); }
- private:
- void initialize()
- {
- io_error_if( this->_info._is_tiled
- , "scanline_reader doesn't support tiled tiff images."
- );
- if( this->_info._photometric_interpretation == PHOTOMETRIC_PALETTE )
- {
- this->_scanline_length = this->_info._width
- * num_channels< rgb16_view_t >::value
- * sizeof( channel_type<rgb16_view_t>::type );
- this->_io_dev.get_field_defaulted( this->_red
- , this->_green
- , this->_blue
- );
- _buffer = std::vector< byte_t >( this->_io_dev.get_scanline_size() );
- switch( this->_info._bits_per_sample )
- {
- case 1:
- {
- using channel_t = channel_type<get_pixel_type<gray1_image_t::view_t>::type>::type;
- int num_colors = channel_traits< channel_t >::max_value() + 1;
- this->_palette = planar_rgb_view( num_colors
- , 1
- , this->_red
- , this->_green
- , this->_blue
- , sizeof(uint16_t) * num_colors
- );
- _read_function = std::mem_fn(&this_t::read_1_bit_index_image);
- break;
- }
- case 2:
- {
- using channel_t = channel_type<get_pixel_type<gray2_image_t::view_t>::type>::type;
- int num_colors = channel_traits< channel_t >::max_value() + 1;
- this->_palette = planar_rgb_view( num_colors
- , 1
- , this->_red
- , this->_green
- , this->_blue
- , sizeof(uint16_t) * num_colors
- );
- _read_function = std::mem_fn(&this_t::read_2_bits_index_image);
- break;
- }
- case 4:
- {
- using channel_t = channel_type<get_pixel_type<gray4_image_t::view_t>::type>::type;
- int num_colors = channel_traits< channel_t >::max_value() + 1;
- this->_palette = planar_rgb_view( num_colors
- , 1
- , this->_red
- , this->_green
- , this->_blue
- , sizeof(uint16_t) * num_colors
- );
- _read_function = std::mem_fn(&this_t::read_4_bits_index_image);
- break;
- }
- case 8:
- {
- using channel_t = channel_type<get_pixel_type<gray8_image_t::view_t>::type>::type;
- int num_colors = channel_traits< channel_t >::max_value() + 1;
- this->_palette = planar_rgb_view( num_colors
- , 1
- , this->_red
- , this->_green
- , this->_blue
- , sizeof(uint16_t) * num_colors
- );
- _read_function = std::mem_fn(&this_t::read_8_bits_index_image);
- break;
- }
- case 16:
- {
- using channel_t = channel_type<get_pixel_type<gray16_image_t::view_t>::type>::type;
- int num_colors = channel_traits< channel_t >::max_value() + 1;
- this->_palette = planar_rgb_view( num_colors
- , 1
- , this->_red
- , this->_green
- , this->_blue
- , sizeof(uint16_t) * num_colors
- );
- _read_function = std::mem_fn(&this_t::read_16_bits_index_image);
- break;
- }
- case 24:
- {
- using channel_t = channel_type<get_pixel_type<gray24_image_t::view_t>::type>::type;
- int num_colors = channel_traits< channel_t >::max_value() + 1;
- this->_palette = planar_rgb_view( num_colors
- , 1
- , this->_red
- , this->_green
- , this->_blue
- , sizeof(uint16_t) * num_colors
- );
- _read_function = std::mem_fn(&this_t::read_24_bits_index_image);
- break;
- }
- case 32:
- {
- using channel_t = channel_type<get_pixel_type<gray32_image_t::view_t>::type>::type;
- int num_colors = channel_traits< channel_t >::max_value() + 1;
- this->_palette = planar_rgb_view( num_colors
- , 1
- , this->_red
- , this->_green
- , this->_blue
- , sizeof(uint16_t) * num_colors
- );
- _read_function = std::mem_fn(&this_t::read_32_bits_index_image);
- break;
- }
- default: { io_error( "Not supported palette " ); }
- }
- }
- else
- {
- this->_scanline_length = this->_io_dev.get_scanline_size();
- if( this->_info._planar_configuration == PLANARCONFIG_SEPARATE )
- {
- io_error( "scanline_reader doesn't support planar tiff images." );
- }
- else if( this->_info._planar_configuration == PLANARCONFIG_CONTIG )
- {
- // the read_data function needs to know what gil type the source image is
- // to have the default color converter function correctly
- switch( this->_info._photometric_interpretation )
- {
- case PHOTOMETRIC_MINISWHITE:
- case PHOTOMETRIC_MINISBLACK:
- {
- switch( this->_info._bits_per_sample )
- {
- case 1:
- case 2:
- case 4:
- case 6:
- case 8:
- case 10:
- case 12:
- case 14:
- case 16:
- case 24:
- case 32: { _read_function = std::mem_fn(&this_t::read_row); break; }
- default: { io_error( "Image type is not supported." ); }
- }
- break;
- }
- case PHOTOMETRIC_RGB:
- {
- switch( this->_info._samples_per_pixel )
- {
- case 3:
- {
- switch( this->_info._bits_per_sample )
- {
- case 2:
- case 4:
- case 8:
- case 10:
- case 12:
- case 14:
- case 16:
- case 24:
- case 32: { _read_function = std::mem_fn(&this_t::read_row); break; }
- default: { io_error( "Image type is not supported." ); }
- }
- break;
- }
- case 4:
- {
- switch( this->_info._bits_per_sample )
- {
- case 2:
- case 4:
- case 8:
- case 10:
- case 12:
- case 14:
- case 16:
- case 24:
- case 32: { _read_function = std::mem_fn(&this_t::read_row); break; }
- default: { io_error( "Image type is not supported." ); }
- }
- break;
- }
- default: { io_error( "Image type is not supported." ); }
- }
- break;
- }
- case PHOTOMETRIC_SEPARATED: // CYMK
- {
- switch( this->_info._bits_per_sample )
- {
- case 2:
- case 4:
- case 8:
- case 10:
- case 12:
- case 14:
- case 16:
- case 24:
- case 32: { _read_function = std::mem_fn(&this_t::read_row); break; }
- default: { io_error( "Image type is not supported." ); }
- }
- break;
- }
- default: { io_error( "Image type is not supported." ); }
- }
- }
- else
- {
- io_error( "Wrong planar configuration setting." );
- }
- }
- }
- template< typename Src_View >
- void read_n_bits_row( byte_t* dst, int pos )
- {
- using dst_view_t = rgb16_view_t;
- this->_io_dev.read_scanline( _buffer
- , pos
- , 0
- );
- Src_View src_view = interleaved_view( this->_info._width
- , 1
- , (typename Src_View::x_iterator) &_buffer.front()
- , this->_scanline_length
- );
- dst_view_t dst_view = interleaved_view( this->_info._width
- , 1
- , (typename dst_view_t::value_type*) dst
- , num_channels< dst_view_t >::value * 2 * this->_info._width
- );
- typename Src_View::x_iterator src_it = src_view.row_begin( 0 );
- typename dst_view_t::x_iterator dst_it = dst_view.row_begin( 0 );
- for( dst_view_t::x_coord_t i = 0
- ; i < this->_info._width
- ; ++i, src_it++, dst_it++
- )
- {
- auto const c = static_cast<std::uint16_t>(get_color(*src_it, gray_color_t()));
- *dst_it = this->_palette[c];
- }
- }
- void read_1_bit_index_image( byte_t* dst, int pos )
- {
- read_n_bits_row< gray1_image_t::view_t >( dst, pos );
- }
- void read_2_bits_index_image( byte_t* dst, int pos )
- {
- read_n_bits_row< gray2_image_t::view_t >( dst, pos );
- }
- void read_4_bits_index_image( byte_t* dst, int pos )
- {
- read_n_bits_row< gray4_image_t::view_t >( dst, pos );
- }
- void read_8_bits_index_image( byte_t* dst, int pos )
- {
- read_n_bits_row< gray8_image_t::view_t >( dst, pos );
- }
- void read_16_bits_index_image( byte_t* dst, int pos )
- {
- read_n_bits_row< gray16_image_t::view_t >( dst, pos );
- }
- void read_24_bits_index_image( byte_t* dst, int pos )
- {
- read_n_bits_row< gray24_image_t::view_t >( dst, pos );
- }
- void read_32_bits_index_image( byte_t* dst, int pos )
- {
- read_n_bits_row< gray32_image_t::view_t >( dst, pos );
- }
- void read_row(byte_t* dst, int pos )
- {
- this->_io_dev.read_scanline( dst
- , pos
- , 0
- );
- }
- private:
- std::vector< byte_t> _buffer;
- detail::mirror_bits<std::vector<byte_t>, std::true_type> _mirror_bites;
- std::function<void(this_t*, byte_t*, int)> _read_function;
- };
- } // namespace gil
- } // namespace boost
- #endif
|