File indexing completed on 2025-01-18 09:36:56
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READ_HPP
0009 #define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READ_HPP
0010
0011 #include <boost/gil/extension/io/jpeg/tags.hpp>
0012 #include <boost/gil/extension/io/jpeg/detail/base.hpp>
0013 #include <boost/gil/extension/io/jpeg/detail/is_allowed.hpp>
0014
0015 #include <boost/gil/io/detail/dynamic.hpp>
0016 #include <boost/gil/io/base.hpp>
0017 #include <boost/gil/io/conversion_policies.hpp>
0018 #include <boost/gil/io/device.hpp>
0019 #include <boost/gil/io/reader_base.hpp>
0020 #include <boost/gil/io/typedefs.hpp>
0021
0022 #include <csetjmp>
0023 #include <type_traits>
0024 #include <vector>
0025
0026 namespace boost { namespace gil {
0027
0028 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0029 #pragma warning(push)
0030 #pragma warning(disable:4512)
0031 #pragma warning(disable:4611)
0032 #endif
0033
0034
0035
0036
0037 template< typename Device
0038 , typename ConversionPolicy
0039 >
0040 class reader< Device
0041 , jpeg_tag
0042 , ConversionPolicy
0043 >
0044 : public reader_base< jpeg_tag
0045 , ConversionPolicy
0046 >
0047 , public reader_backend< Device
0048 , jpeg_tag
0049 >
0050 {
0051 private:
0052
0053 using this_t = reader<Device, jpeg_tag, ConversionPolicy>;
0054 using cc_t = typename ConversionPolicy::color_converter_type;
0055
0056 public:
0057
0058 using backend_t = reader_backend<Device, jpeg_tag>;
0059
0060 public:
0061
0062
0063
0064
0065 reader( const Device& io_dev
0066 , const image_read_settings< jpeg_tag >& settings
0067 )
0068 : reader_base< jpeg_tag
0069 , ConversionPolicy
0070 >()
0071
0072 , backend_t( io_dev
0073 , settings
0074 )
0075 {}
0076
0077
0078
0079
0080 reader( const Device& io_dev
0081 , const typename ConversionPolicy::color_converter_type& cc
0082 , const image_read_settings< jpeg_tag >& settings
0083 )
0084 : reader_base< jpeg_tag
0085 , ConversionPolicy
0086 >( cc )
0087 , backend_t( io_dev
0088 , settings
0089 )
0090 {}
0091
0092 template<typename View>
0093 void apply( const View& view )
0094 {
0095
0096 if( setjmp( this->_mark ))
0097 {
0098 this->raise_error();
0099 }
0100
0101 this->get()->dct_method = this->_settings._dct_method;
0102
0103 using is_read_and_convert_t = typename std::is_same
0104 <
0105 ConversionPolicy,
0106 detail::read_and_no_convert
0107 >::type;
0108
0109 io_error_if( !detail::is_allowed< View >( this->_info
0110 , is_read_and_convert_t()
0111 )
0112 , "Image types aren't compatible."
0113 );
0114
0115 if( jpeg_start_decompress( this->get() ) == false )
0116 {
0117 io_error( "Cannot start decompression." );
0118 }
0119
0120 switch( this->_info._color_space )
0121 {
0122 case JCS_GRAYSCALE:
0123 {
0124 this->_scanline_length = this->_info._width;
0125 read_rows< gray8_pixel_t >( view );
0126
0127 break;
0128 }
0129
0130 case JCS_RGB:
0131
0132 case JCS_YCbCr:
0133 {
0134 this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
0135
0136 read_rows< rgb8_pixel_t >( view );
0137 break;
0138 }
0139
0140 case JCS_CMYK:
0141
0142 case JCS_YCCK:
0143 {
0144 this->get()->out_color_space = JCS_CMYK;
0145 this->_scanline_length = this->_info._width * num_channels< cmyk8_view_t >::value;
0146
0147 read_rows< cmyk8_pixel_t >( view );
0148
0149 break;
0150 }
0151 default: { io_error( "Unsupported jpeg color space." ); }
0152 }
0153
0154 jpeg_finish_decompress ( this->get() );
0155 }
0156
0157 private:
0158
0159 template< typename ImagePixel
0160 , typename View
0161 >
0162 void read_rows( const View& view )
0163 {
0164 using buffer_t = std::vector<ImagePixel>;
0165 buffer_t buffer( this->_info._width );
0166
0167
0168
0169
0170
0171 if( setjmp( this->_mark ))
0172 {
0173 this->raise_error();
0174 }
0175
0176
0177 JSAMPLE *row_adr = reinterpret_cast< JSAMPLE* >( &buffer[0] );
0178
0179
0180 for( int y = 0; y < this->_settings._top_left.y; ++y )
0181 {
0182 io_error_if( jpeg_read_scanlines( this->get()
0183 , &row_adr
0184 , 1
0185 ) !=1
0186 , "jpeg_read_scanlines: fail to read JPEG file"
0187 );
0188 }
0189
0190
0191 for( int y = 0; y < view.height(); ++y )
0192 {
0193 io_error_if( jpeg_read_scanlines( this->get()
0194 , &row_adr
0195 , 1
0196 ) != 1
0197 , "jpeg_read_scanlines: fail to read JPEG file"
0198 );
0199
0200 typename buffer_t::iterator beg = buffer.begin() + this->_settings._top_left.x;
0201 typename buffer_t::iterator end = beg + this->_settings._dim.x;
0202
0203 this->_cc_policy.read( beg
0204 , end
0205 , view.row_begin( y )
0206 );
0207 }
0208
0209
0210 while( this->get()->output_scanline < this->get()->image_height )
0211 {
0212 io_error_if( jpeg_read_scanlines( this->get()
0213 , &row_adr
0214 , 1
0215 ) !=1
0216 , "jpeg_read_scanlines: fail to read JPEG file"
0217 );
0218 }
0219
0220 }
0221 };
0222
0223 namespace detail {
0224
0225 struct jpeg_type_format_checker
0226 {
0227 jpeg_type_format_checker( jpeg_color_space::type color_space )
0228 : _color_space( color_space )
0229 {}
0230
0231 template< typename Image >
0232 bool apply()
0233 {
0234 return is_read_supported< typename get_pixel_type< typename Image::view_t >::type
0235 , jpeg_tag
0236 >::_color_space == _color_space;
0237 }
0238
0239 private:
0240
0241 jpeg_color_space::type _color_space;
0242 };
0243
0244 struct jpeg_read_is_supported
0245 {
0246 template< typename View >
0247 struct apply : public is_read_supported< typename get_pixel_type< View >::type
0248 , jpeg_tag
0249 >
0250 {};
0251 };
0252
0253 }
0254
0255
0256
0257
0258 template< typename Device >
0259 class dynamic_image_reader< Device
0260 , jpeg_tag
0261 >
0262 : public reader< Device
0263 , jpeg_tag
0264 , detail::read_and_no_convert
0265 >
0266 {
0267 using parent_t = reader<Device, jpeg_tag, detail::read_and_no_convert>;
0268
0269 public:
0270
0271 dynamic_image_reader( const Device& io_dev
0272 , const image_read_settings< jpeg_tag >& settings
0273 )
0274 : parent_t( io_dev
0275 , settings
0276 )
0277 {}
0278
0279 template< typename ...Images >
0280 void apply( any_image< Images... >& images )
0281 {
0282 detail::jpeg_type_format_checker format_checker( this->_info._color_space != JCS_YCbCr
0283 ? this->_info._color_space
0284 : JCS_RGB
0285 );
0286
0287 if( !detail::construct_matched( images
0288 , format_checker
0289 ))
0290 {
0291 io_error( "No matching image type between those of the given any_image and that of the file" );
0292 }
0293 else
0294 {
0295 this->init_image( images
0296 , this->_settings
0297 );
0298
0299 detail::dynamic_io_fnobj< detail::jpeg_read_is_supported
0300 , parent_t
0301 > op( this );
0302
0303 variant2::visit( op
0304 , view( images )
0305 );
0306 }
0307 }
0308 };
0309
0310 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0311 #pragma warning(pop)
0312 #endif
0313
0314 }
0315 }
0316
0317 #endif