diff options
Diffstat (limited to 'boost/gil/extension/io/tiff/detail/scanline_read.hpp')
-rw-r--r-- | boost/gil/extension/io/tiff/detail/scanline_read.hpp | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/boost/gil/extension/io/tiff/detail/scanline_read.hpp b/boost/gil/extension/io/tiff/detail/scanline_read.hpp new file mode 100644 index 0000000000..7e7e2cc8b7 --- /dev/null +++ b/boost/gil/extension/io/tiff/detail/scanline_read.hpp @@ -0,0 +1,465 @@ +/* + Copyright 2007-2012 Christian Henning, Lubomir Bourdev + Use, modification and distribution are subject to 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 + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief +/// \author Christian Henning, Lubomir Bourdev \n +/// +/// \date 2007-2012 \n +/// +//////////////////////////////////////////////////////////////////////////////////////// + +// 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 + +#include <algorithm> +#include <string> +#include <vector> + +#include <boost/function.hpp> +#include <boost/static_assert.hpp> + +#include <boost/gil/io/base.hpp> +#include <boost/gil/io/conversion_policies.hpp> +#include <boost/gil/io/bit_operations.hpp> +#include <boost/gil/io/row_buffer_helper.hpp> +#include <boost/gil/io/device.hpp> +#include <boost/gil/io/reader_base.hpp> +#include <boost/gil/io/scanline_read_iterator.hpp> + +#include <boost/gil/extension/io/tiff/detail/reader_backend.hpp> +#include <boost/gil/extension/io/tiff/detail/device.hpp> +#include <boost/gil/extension/io/tiff/detail/is_allowed.hpp> + + +namespace boost { namespace gil { + +/// +/// TIFF scanline reader +/// +template< typename Device > +class scanline_reader< Device + , tiff_tag + > + : public reader_backend< Device + , tiff_tag + > +{ +public: + + + typedef tiff_tag tag_t; + typedef reader_backend < Device, tag_t > backend_t; + typedef scanline_reader< Device, tag_t > this_t; + typedef scanline_read_iterator< this_t > iterator_t; + +public: + + 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: + { + typedef channel_type< get_pixel_type< gray1_image_t::view_t >::type >::type channel_t; + + 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 = boost::mem_fn( &this_t::read_1_bit_index_image ); + + break; + } + + case 2: + { + typedef channel_type< get_pixel_type< gray2_image_t::view_t >::type >::type channel_t; + + 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 = boost::mem_fn( &this_t::read_2_bits_index_image ); + + break; + } + case 4: + { + typedef channel_type< get_pixel_type< gray4_image_t::view_t >::type >::type channel_t; + + 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 = boost::mem_fn( &this_t::read_4_bits_index_image ); + + break; + } + + case 8: + { + typedef channel_type< get_pixel_type< gray8_image_t::view_t >::type >::type channel_t; + + 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 = boost::mem_fn( &this_t::read_8_bits_index_image ); + + break; + } + + case 16: + { + typedef channel_type< get_pixel_type< gray16_image_t::view_t >::type >::type channel_t; + + 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 = boost::mem_fn( &this_t::read_16_bits_index_image ); + + break; + } + + case 24: + { + typedef channel_type< get_pixel_type< gray24_image_t::view_t >::type >::type channel_t; + + 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 = boost::mem_fn( &this_t::read_24_bits_index_image ); + + break; + } + + case 32: + { + typedef channel_type< get_pixel_type< gray32_image_t::view_t >::type >::type channel_t; + + 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 = boost::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 = boost::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 = boost::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 = boost::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 = boost::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 ) + { + typedef rgb16_view_t dst_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 >, mpl::true_ > _mirror_bites; + + boost::function< void ( this_t*, byte_t*, int ) > _read_function; +}; + +} // namespace gil +} // namespace boost + +#endif |