2 // Copyright 2012 Olivier Tournaire, Christian Henning
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 #ifndef BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READ_HPP
9 #define BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READ_HPP
11 #include <boost/gil/extension/io/raw/tags.hpp>
12 #include <boost/gil/extension/io/raw/detail/device.hpp>
13 #include <boost/gil/extension/io/raw/detail/is_allowed.hpp>
14 #include <boost/gil/extension/io/raw/detail/reader_backend.hpp>
16 #include <boost/gil/io/base.hpp>
17 #include <boost/gil/io/bit_operations.hpp>
18 #include <boost/gil/io/conversion_policies.hpp>
19 #include <boost/gil/io/device.hpp>
20 #include <boost/gil/io/dynamic_io_new.hpp>
21 #include <boost/gil/io/reader_base.hpp>
22 #include <boost/gil/io/row_buffer_helper.hpp>
23 #include <boost/gil/io/typedefs.hpp>
27 #include <type_traits>
30 namespace boost { namespace gil {
32 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
34 #pragma warning(disable:4512) //assignment operator could not be generated
37 #define BUILD_INTERLEAVED_VIEW(color_layout, bits_per_pixel) \
39 color_layout##bits_per_pixel##_view_t build = boost::gil::interleaved_view(processed_image->width, \
40 processed_image->height, \
41 (color_layout##bits_per_pixel##_pixel_t*)processed_image->data, \
42 processed_image->colors*processed_image->width*processed_image->bits/8); \
43 this->_cc_policy.read( build.begin(), build.end(), dst_view.begin() ); \
47 template< typename Device
48 , typename ConversionPolicy
54 : public reader_base< raw_tag
57 , public reader_backend< Device
63 using this_t = reader<Device, raw_tag, ConversionPolicy>;
64 using cc_t = typename ConversionPolicy::color_converter_type;
68 using backend_t = reader_backend<Device, raw_tag>;
73 reader( const Device& io_dev
74 , const image_read_settings< raw_tag >& settings
84 reader( const Device& io_dev
86 , const image_read_settings< raw_tag >& settings
88 : reader_base< raw_tag
96 template< typename View >
97 void apply( const View& dst_view )
99 if( this->_info._valid == false )
101 io_error( "Image header was not read." );
104 using is_read_and_convert_t = typename std::is_same
107 detail::read_and_no_convert
110 io_error_if( !detail::is_allowed< View >( this->_info
111 , is_read_and_convert_t()
113 , "Image types aren't compatible."
116 // TODO: better error handling based on return code
117 int return_code = this->_io_dev.unpack();
118 io_error_if( return_code != LIBRAW_SUCCESS, "Unable to unpack image" );
119 this->_info._unpack_function_name = this->_io_dev.get_unpack_function_name();
121 return_code = this->_io_dev.dcraw_process();
122 io_error_if( return_code != LIBRAW_SUCCESS, "Unable to emulate dcraw behavior to process image" );
124 libraw_processed_image_t* processed_image = this->_io_dev.dcraw_make_mem_image(&return_code);
125 io_error_if( return_code != LIBRAW_SUCCESS, "Unable to dcraw_make_mem_image" );
127 if(processed_image->colors!=1 && processed_image->colors!=3)
128 io_error( "Image is neither gray nor RGB" );
130 if(processed_image->bits!=8 && processed_image->bits!=16)
131 io_error( "Image is neither 8bit nor 16bit" );
133 // TODO Olivier Tournaire
134 // Here, we should use a metafunction to reduce code size and avoid a (compile time) macro
135 if(processed_image->bits==8)
137 if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 8); }
138 else { BUILD_INTERLEAVED_VIEW(rgb, 8); }
140 else if(processed_image->bits==16)
142 if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 16); }
143 else { BUILD_INTERLEAVED_VIEW(rgb, 16); }
150 struct raw_read_is_supported
152 template< typename View >
153 struct apply : public is_read_supported< typename get_pixel_type< View >::type
159 struct raw_type_format_checker
161 raw_type_format_checker( const image_read_info< raw_tag >& info )
165 template< typename Image >
168 using view_t = typename Image::view_t;
169 return is_allowed<view_t>(_info, std::true_type{});
173 ///todo: do we need this here. Should be part of reader_backend
174 const image_read_info< raw_tag >& _info;
177 } // namespace detail
180 /// RAW Dynamic Reader
182 template< typename Device >
183 class dynamic_image_reader< Device
186 : public reader< Device
188 , detail::read_and_no_convert
191 using parent_t = reader<Device, raw_tag, detail::read_and_no_convert>;
195 dynamic_image_reader( const Device& io_dev
196 , const image_read_settings< raw_tag >& settings
203 template< typename Images >
204 void apply( any_image< Images >& images )
206 detail::raw_type_format_checker format_checker( this->_info );
208 if( !construct_matched( images
212 std::ostringstream error_message;
213 error_message << "No matching image type between those of the given any_image and that of the file.\n";
214 error_message << "Image type must be {gray||rgb}{8||16} unsigned for RAW image files.";
215 io_error( error_message.str().c_str() );
219 if( !this->_info._valid )
221 this->init_image(images, this->_settings);
223 detail::dynamic_io_fnobj< detail::raw_read_is_supported
227 apply_operation( view( images )
234 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)