File indexing completed on 2025-01-18 09:36:58
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READ_HPP
0009 #define BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READ_HPP
0010
0011 #include <boost/gil/extension/io/raw/tags.hpp>
0012 #include <boost/gil/extension/io/raw/detail/device.hpp>
0013 #include <boost/gil/extension/io/raw/detail/is_allowed.hpp>
0014 #include <boost/gil/extension/io/raw/detail/reader_backend.hpp>
0015
0016 #include <boost/gil/io/detail/dynamic.hpp>
0017 #include <boost/gil/io/base.hpp>
0018 #include <boost/gil/io/bit_operations.hpp>
0019 #include <boost/gil/io/conversion_policies.hpp>
0020 #include <boost/gil/io/device.hpp>
0021 #include <boost/gil/io/reader_base.hpp>
0022 #include <boost/gil/io/row_buffer_helper.hpp>
0023 #include <boost/gil/io/typedefs.hpp>
0024
0025 #include <cstdio>
0026 #include <sstream>
0027 #include <type_traits>
0028 #include <vector>
0029
0030 namespace boost { namespace gil {
0031
0032 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0033 #pragma warning(push)
0034 #pragma warning(disable:4512)
0035 #endif
0036
0037 #define BUILD_INTERLEAVED_VIEW(color_layout, bits_per_pixel) \
0038 { \
0039 color_layout##bits_per_pixel##_view_t build = boost::gil::interleaved_view(processed_image->width, \
0040 processed_image->height, \
0041 (color_layout##bits_per_pixel##_pixel_t*)processed_image->data, \
0042 processed_image->colors*processed_image->width*processed_image->bits/8); \
0043 this->_cc_policy.read( build.begin(), build.end(), dst_view.begin() ); \
0044 } \
0045
0046
0047 template< typename Device
0048 , typename ConversionPolicy
0049 >
0050 class reader< Device
0051 , raw_tag
0052 , ConversionPolicy
0053 >
0054 : public reader_base< raw_tag
0055 , ConversionPolicy
0056 >
0057 , public reader_backend< Device
0058 , raw_tag
0059 >
0060 {
0061 private:
0062
0063 using this_t = reader<Device, raw_tag, ConversionPolicy>;
0064 using cc_t = typename ConversionPolicy::color_converter_type;
0065
0066 public:
0067
0068 using backend_t = reader_backend<Device, raw_tag>;
0069
0070
0071
0072
0073 reader( const Device& io_dev
0074 , const image_read_settings< raw_tag >& settings
0075 )
0076 : backend_t( io_dev
0077 , settings
0078 )
0079 {}
0080
0081
0082
0083
0084 reader( const Device& io_dev
0085 , const cc_t& cc
0086 , const image_read_settings< raw_tag >& settings
0087 )
0088 : reader_base< raw_tag
0089 , ConversionPolicy
0090 >( cc )
0091 , backend_t( io_dev
0092 , settings
0093 )
0094 {}
0095
0096 template< typename View >
0097 void apply( const View& dst_view )
0098 {
0099 if( this->_info._valid == false )
0100 {
0101 io_error( "Image header was not read." );
0102 }
0103
0104 using is_read_and_convert_t = typename std::is_same
0105 <
0106 ConversionPolicy,
0107 detail::read_and_no_convert
0108 >::type;
0109
0110 io_error_if( !detail::is_allowed< View >( this->_info
0111 , is_read_and_convert_t()
0112 )
0113 , "Image types aren't compatible."
0114 );
0115
0116
0117 int return_code = this->_io_dev.unpack();
0118 io_error_if( return_code != LIBRAW_SUCCESS, "Unable to unpack image" );
0119 this->_info._unpack_function_name = this->_io_dev.get_unpack_function_name();
0120
0121 return_code = this->_io_dev.dcraw_process();
0122 io_error_if( return_code != LIBRAW_SUCCESS, "Unable to emulate dcraw behavior to process image" );
0123
0124 libraw_processed_image_t* processed_image = this->_io_dev.dcraw_make_mem_image(&return_code);
0125 io_error_if( return_code != LIBRAW_SUCCESS, "Unable to dcraw_make_mem_image" );
0126
0127 if(processed_image->colors!=1 && processed_image->colors!=3)
0128 io_error( "Image is neither gray nor RGB" );
0129
0130 if(processed_image->bits!=8 && processed_image->bits!=16)
0131 io_error( "Image is neither 8bit nor 16bit" );
0132
0133
0134
0135 if(processed_image->bits==8)
0136 {
0137 if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 8); }
0138 else { BUILD_INTERLEAVED_VIEW(rgb, 8); }
0139 }
0140 else if(processed_image->bits==16)
0141 {
0142 if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 16); }
0143 else { BUILD_INTERLEAVED_VIEW(rgb, 16); }
0144 }
0145 }
0146 };
0147
0148 namespace detail {
0149
0150 struct raw_read_is_supported
0151 {
0152 template< typename View >
0153 struct apply : public is_read_supported< typename get_pixel_type< View >::type
0154 , raw_tag
0155 >
0156 {};
0157 };
0158
0159 struct raw_type_format_checker
0160 {
0161 raw_type_format_checker( const image_read_info< raw_tag >& info )
0162 : _info( info )
0163 {}
0164
0165 template< typename Image >
0166 bool apply()
0167 {
0168 using view_t = typename Image::view_t;
0169 return is_allowed<view_t>(_info, std::true_type{});
0170 }
0171
0172 private:
0173
0174 const image_read_info< raw_tag >& _info;
0175 };
0176
0177 }
0178
0179
0180
0181
0182 template< typename Device >
0183 class dynamic_image_reader< Device
0184 , raw_tag
0185 >
0186 : public reader< Device
0187 , raw_tag
0188 , detail::read_and_no_convert
0189 >
0190 {
0191 using parent_t = reader<Device, raw_tag, detail::read_and_no_convert>;
0192
0193 public:
0194
0195 dynamic_image_reader( const Device& io_dev
0196 , const image_read_settings< raw_tag >& settings
0197 )
0198 : parent_t( io_dev
0199 , settings
0200 )
0201 {}
0202
0203 template< typename ...Images >
0204 void apply( any_image< Images... >& images )
0205 {
0206 detail::raw_type_format_checker format_checker( this->_info );
0207
0208 if( !detail::construct_matched( images
0209 , format_checker
0210 ))
0211 {
0212 std::ostringstream error_message;
0213 error_message << "No matching image type between those of the given any_image and that of the file.\n";
0214 error_message << "Image type must be {gray||rgb}{8||16} unsigned for RAW image files.";
0215 io_error( error_message.str().c_str() );
0216 }
0217 else
0218 {
0219 if( !this->_info._valid )
0220 this->read_header();
0221 this->init_image(images, this->_settings);
0222
0223 detail::dynamic_io_fnobj< detail::raw_read_is_supported
0224 , parent_t
0225 > op( this );
0226
0227 variant2::visit( op
0228 , view( images )
0229 );
0230 }
0231 }
0232 };
0233
0234 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0235 #pragma warning(pop)
0236 #endif
0237
0238 }
0239 }
0240
0241 #endif