123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- //
- // Copyright 2012 Olivier Tournaire, Christian Henning
- //
- // 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_RAW_DETAIL_READ_HPP
- #define BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READ_HPP
- #include <boost/gil/extension/io/raw/tags.hpp>
- #include <boost/gil/extension/io/raw/detail/device.hpp>
- #include <boost/gil/extension/io/raw/detail/is_allowed.hpp>
- #include <boost/gil/extension/io/raw/detail/reader_backend.hpp>
- #include <boost/gil/io/detail/dynamic.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/typedefs.hpp>
- #include <cstdio>
- #include <sstream>
- #include <type_traits>
- #include <vector>
- namespace boost { namespace gil {
- #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
- #pragma warning(push)
- #pragma warning(disable:4512) //assignment operator could not be generated
- #endif
- #define BUILD_INTERLEAVED_VIEW(color_layout, bits_per_pixel) \
- { \
- color_layout##bits_per_pixel##_view_t build = boost::gil::interleaved_view(processed_image->width, \
- processed_image->height, \
- (color_layout##bits_per_pixel##_pixel_t*)processed_image->data, \
- processed_image->colors*processed_image->width*processed_image->bits/8); \
- this->_cc_policy.read( build.begin(), build.end(), dst_view.begin() ); \
- } \
- template< typename Device
- , typename ConversionPolicy
- >
- class reader< Device
- , raw_tag
- , ConversionPolicy
- >
- : public reader_base< raw_tag
- , ConversionPolicy
- >
- , public reader_backend< Device
- , raw_tag
- >
- {
- private:
- using this_t = reader<Device, raw_tag, ConversionPolicy>;
- using cc_t = typename ConversionPolicy::color_converter_type;
- public:
- using backend_t = reader_backend<Device, raw_tag>;
- //
- // Constructor
- //
- reader( const Device& io_dev
- , const image_read_settings< raw_tag >& settings
- )
- : backend_t( io_dev
- , settings
- )
- {}
- //
- // Constructor
- //
- reader( const Device& io_dev
- , const cc_t& cc
- , const image_read_settings< raw_tag >& settings
- )
- : reader_base< raw_tag
- , ConversionPolicy
- >( cc )
- , backend_t( io_dev
- , settings
- )
- {}
- template< typename View >
- void apply( const View& dst_view )
- {
- if( this->_info._valid == false )
- {
- io_error( "Image header was not read." );
- }
- using is_read_and_convert_t = typename std::is_same
- <
- ConversionPolicy,
- detail::read_and_no_convert
- >::type;
- io_error_if( !detail::is_allowed< View >( this->_info
- , is_read_and_convert_t()
- )
- , "Image types aren't compatible."
- );
- // TODO: better error handling based on return code
- int return_code = this->_io_dev.unpack();
- io_error_if( return_code != LIBRAW_SUCCESS, "Unable to unpack image" );
- this->_info._unpack_function_name = this->_io_dev.get_unpack_function_name();
- return_code = this->_io_dev.dcraw_process();
- io_error_if( return_code != LIBRAW_SUCCESS, "Unable to emulate dcraw behavior to process image" );
- libraw_processed_image_t* processed_image = this->_io_dev.dcraw_make_mem_image(&return_code);
- io_error_if( return_code != LIBRAW_SUCCESS, "Unable to dcraw_make_mem_image" );
- if(processed_image->colors!=1 && processed_image->colors!=3)
- io_error( "Image is neither gray nor RGB" );
- if(processed_image->bits!=8 && processed_image->bits!=16)
- io_error( "Image is neither 8bit nor 16bit" );
- // TODO Olivier Tournaire
- // Here, we should use a metafunction to reduce code size and avoid a (compile time) macro
- if(processed_image->bits==8)
- {
- if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 8); }
- else { BUILD_INTERLEAVED_VIEW(rgb, 8); }
- }
- else if(processed_image->bits==16)
- {
- if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 16); }
- else { BUILD_INTERLEAVED_VIEW(rgb, 16); }
- }
- }
- };
- namespace detail {
- struct raw_read_is_supported
- {
- template< typename View >
- struct apply : public is_read_supported< typename get_pixel_type< View >::type
- , raw_tag
- >
- {};
- };
- struct raw_type_format_checker
- {
- raw_type_format_checker( const image_read_info< raw_tag >& info )
- : _info( info )
- {}
- template< typename Image >
- bool apply()
- {
- using view_t = typename Image::view_t;
- return is_allowed<view_t>(_info, std::true_type{});
- }
- private:
- ///todo: do we need this here. Should be part of reader_backend
- const image_read_info< raw_tag >& _info;
- };
- } // namespace detail
- ///
- /// RAW Dynamic Reader
- ///
- template< typename Device >
- class dynamic_image_reader< Device
- , raw_tag
- >
- : public reader< Device
- , raw_tag
- , detail::read_and_no_convert
- >
- {
- using parent_t = reader<Device, raw_tag, detail::read_and_no_convert>;
- public:
- dynamic_image_reader( const Device& io_dev
- , const image_read_settings< raw_tag >& settings
- )
- : parent_t( io_dev
- , settings
- )
- {}
- template< typename ...Images >
- void apply( any_image< Images... >& images )
- {
- detail::raw_type_format_checker format_checker( this->_info );
- if( !detail::construct_matched( images
- , format_checker
- ))
- {
- std::ostringstream error_message;
- error_message << "No matching image type between those of the given any_image and that of the file.\n";
- error_message << "Image type must be {gray||rgb}{8||16} unsigned for RAW image files.";
- io_error( error_message.str().c_str() );
- }
- else
- {
- if( !this->_info._valid )
- this->read_header();
- this->init_image(images, this->_settings);
- detail::dynamic_io_fnobj< detail::raw_read_is_supported
- , parent_t
- > op( this );
- variant2::visit( op
- , view( images )
- );
- }
- }
- };
- #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
- #pragma warning(pop)
- #endif
- } // gil
- } // boost
- #endif
|