File indexing completed on 2024-11-15 09:12:30
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITER_BACKEND_HPP
0009 #define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITER_BACKEND_HPP
0010
0011 #include <boost/gil/extension/io/png/tags.hpp>
0012 #include <boost/gil/extension/io/png/detail/base.hpp>
0013 #include <boost/gil/extension/io/png/detail/supported_types.hpp>
0014
0015 #include <boost/gil/io/base.hpp>
0016 #include <boost/gil/io/typedefs.hpp>
0017
0018 namespace boost { namespace gil {
0019
0020 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0021 #pragma warning(push)
0022 #pragma warning(disable:4512)
0023 #pragma warning(disable:4611)
0024 #endif
0025
0026
0027
0028
0029 template< typename Device >
0030 struct writer_backend< Device
0031 , png_tag
0032 >
0033 : public detail::png_struct_info_wrapper
0034 {
0035
0036 private:
0037
0038 using this_t = writer_backend<Device, png_tag>;
0039
0040 public:
0041
0042 using format_tag_t = png_tag;
0043
0044
0045
0046
0047 writer_backend( const Device& io_dev
0048 , const image_write_info< png_tag >& info
0049 )
0050 : png_struct_info_wrapper( false )
0051 , _io_dev( io_dev )
0052 , _info( info )
0053 {
0054
0055
0056
0057
0058
0059 get()->_struct = png_create_write_struct( PNG_LIBPNG_VER_STRING
0060 , nullptr
0061 , nullptr
0062 , nullptr
0063 );
0064
0065 io_error_if( get_struct() == nullptr
0066 , "png_writer: fail to call png_create_write_struct()"
0067 );
0068
0069
0070 get()->_info = png_create_info_struct( get_struct() );
0071
0072 if( get_info() == nullptr )
0073 {
0074 png_destroy_write_struct( &get()->_struct
0075 , nullptr
0076 );
0077
0078 io_error( "png_writer: fail to call png_create_info_struct()" );
0079 }
0080
0081
0082
0083 if( setjmp( png_jmpbuf( get_struct() )))
0084 {
0085
0086 png_destroy_write_struct( &get()->_struct
0087 , &get()->_info
0088 );
0089
0090 io_error( "png_writer: fail to call setjmp()" );
0091 }
0092
0093 init_io( get_struct() );
0094 }
0095
0096 protected:
0097
0098 template< typename View >
0099 void write_header( const View& view )
0100 {
0101 using png_rw_info_t = detail::png_write_support
0102 <
0103 typename channel_type<typename get_pixel_type<View>::type>::type,
0104 typename color_space_type<View>::type
0105 >;
0106
0107
0108
0109
0110
0111
0112
0113
0114 png_set_IHDR( get_struct()
0115 , get_info()
0116 , static_cast< png_image_width::type >( view.width() )
0117 , static_cast< png_image_height::type >( view.height() )
0118 , static_cast< png_bitdepth::type >( png_rw_info_t::_bit_depth )
0119 , static_cast< png_color_type::type >( png_rw_info_t::_color_type )
0120 , _info._interlace_method
0121 , _info._compression_type
0122 , _info._filter_method
0123 );
0124
0125 #ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
0126 if( _info._valid_cie_colors )
0127 {
0128 png_set_cHRM( get_struct()
0129 , get_info()
0130 , _info._white_x
0131 , _info._white_y
0132 , _info._red_x
0133 , _info._red_y
0134 , _info._green_x
0135 , _info._green_y
0136 , _info._blue_x
0137 , _info._blue_y
0138 );
0139 }
0140
0141 if( _info._valid_file_gamma )
0142 {
0143 png_set_gAMA( get_struct()
0144 , get_info()
0145 , _info._file_gamma
0146 );
0147 }
0148 #else
0149 if( _info._valid_cie_colors )
0150 {
0151 png_set_cHRM_fixed( get_struct()
0152 , get_info()
0153 , _info._white_x
0154 , _info._white_y
0155 , _info._red_x
0156 , _info._red_y
0157 , _info._green_x
0158 , _info._green_y
0159 , _info._blue_x
0160 , _info._blue_y
0161 );
0162 }
0163
0164 if( _info._valid_file_gamma )
0165 {
0166 png_set_gAMA_fixed( get_struct()
0167 , get_info()
0168 , _info._file_gamma
0169 );
0170 }
0171 #endif
0172
0173 if( _info._valid_icc_profile )
0174 {
0175 #if PNG_LIBPNG_VER_MINOR >= 5
0176 png_set_iCCP( get_struct()
0177 , get_info()
0178 , const_cast< png_charp >( _info._icc_name.c_str() )
0179 , _info._iccp_compression_type
0180 , reinterpret_cast< png_const_bytep >( & (_info._profile.front ()) )
0181 , _info._profile_length
0182 );
0183 #else
0184 png_set_iCCP( get_struct()
0185 , get_info()
0186 , const_cast< png_charp >( _info._icc_name.c_str() )
0187 , _info._iccp_compression_type
0188 , const_cast< png_charp >( & (_info._profile.front()) )
0189 , _info._profile_length
0190 );
0191 #endif
0192 }
0193
0194 if( _info._valid_intent )
0195 {
0196 png_set_sRGB( get_struct()
0197 , get_info()
0198 , _info._intent
0199 );
0200 }
0201
0202 if( _info._valid_palette )
0203 {
0204 png_set_PLTE( get_struct()
0205 , get_info()
0206 , const_cast< png_colorp >( &_info._palette.front() )
0207 , _info._num_palette
0208 );
0209 }
0210
0211 if( _info._valid_background )
0212 {
0213 png_set_bKGD( get_struct()
0214 , get_info()
0215 , const_cast< png_color_16p >( &_info._background )
0216 );
0217 }
0218
0219 if( _info._valid_histogram )
0220 {
0221 png_set_hIST( get_struct()
0222 , get_info()
0223 , const_cast< png_uint_16p >( &_info._histogram.front() )
0224 );
0225 }
0226
0227 if( _info._valid_offset )
0228 {
0229 png_set_oFFs( get_struct()
0230 , get_info()
0231 , _info._offset_x
0232 , _info._offset_y
0233 , _info._off_unit_type
0234 );
0235 }
0236
0237 if( _info._valid_pixel_calibration )
0238 {
0239 std::vector< const char* > params( _info._num_params );
0240 for( std::size_t i = 0; i < params.size(); ++i )
0241 {
0242 params[i] = _info._params[ i ].c_str();
0243 }
0244
0245 png_set_pCAL( get_struct()
0246 , get_info()
0247 , const_cast< png_charp >( _info._purpose.c_str() )
0248 , _info._X0
0249 , _info._X1
0250 , _info._cal_type
0251 , _info._num_params
0252 , const_cast< png_charp >( _info._units.c_str() )
0253 , const_cast< png_charpp >( ¶ms.front() )
0254 );
0255 }
0256
0257 if( _info._valid_resolution )
0258 {
0259 png_set_pHYs( get_struct()
0260 , get_info()
0261 , _info._res_x
0262 , _info._res_y
0263 , _info._phy_unit_type
0264 );
0265 }
0266
0267 if( _info._valid_significant_bits )
0268 {
0269 png_set_sBIT( get_struct()
0270 , get_info()
0271 , const_cast< png_color_8p >( &_info._sig_bits )
0272 );
0273 }
0274
0275 #ifndef BOOST_GIL_IO_PNG_1_4_OR_LOWER
0276
0277 #ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
0278 if( _info._valid_scale_factors )
0279 {
0280 png_set_sCAL( get_struct()
0281 , get_info()
0282 , this->_info._scale_unit
0283 , this->_info._scale_width
0284 , this->_info._scale_height
0285 );
0286 }
0287 #else
0288 #ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
0289 if( _info._valid_scale_factors )
0290 {
0291 png_set_sCAL_fixed( get_struct()
0292 , get_info()
0293 , this->_info._scale_unit
0294 , this->_info._scale_width
0295 , this->_info._scale_height
0296 );
0297 }
0298 #else
0299 if( _info._valid_scale_factors )
0300 {
0301 png_set_sCAL_s( get_struct()
0302 , get_info()
0303 , this->_info._scale_unit
0304 , const_cast< png_charp >( this->_info._scale_width.c_str() )
0305 , const_cast< png_charp >( this->_info._scale_height.c_str() )
0306 );
0307 }
0308
0309 #endif
0310 #endif
0311 #endif
0312
0313 if( _info._valid_text )
0314 {
0315 std::vector< png_text > texts( _info._num_text );
0316 for( std::size_t i = 0; i < texts.size(); ++i )
0317 {
0318 png_text pt;
0319 pt.compression = _info._text[i]._compression;
0320 pt.key = const_cast< png_charp >( this->_info._text[i]._key.c_str() );
0321 pt.text = const_cast< png_charp >( this->_info._text[i]._text.c_str() );
0322 pt.text_length = _info._text[i]._text.length();
0323
0324 texts[i] = pt;
0325 }
0326
0327 png_set_text( get_struct()
0328 , get_info()
0329 , &texts.front()
0330 , _info._num_text
0331 );
0332 }
0333
0334 if( _info._valid_modification_time )
0335 {
0336 png_set_tIME( get_struct()
0337 , get_info()
0338 , const_cast< png_timep >( &_info._mod_time )
0339 );
0340 }
0341
0342 if( _info._valid_transparency_factors )
0343 {
0344 int sample_max = ( 1u << _info._bit_depth );
0345
0346
0347 if( !( ( _info._color_type == PNG_COLOR_TYPE_GRAY
0348 && (int) _info._trans_values[0].gray > sample_max
0349 )
0350 || ( _info._color_type == PNG_COLOR_TYPE_RGB
0351 &&( (int) _info._trans_values[0].red > sample_max
0352 || (int) _info._trans_values[0].green > sample_max
0353 || (int) _info._trans_values[0].blue > sample_max
0354 )
0355 )
0356 )
0357 )
0358 {
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368 }
0369 }
0370
0371
0372 png_set_compression_level( get_struct()
0373 , _info._compression_level
0374 );
0375
0376 png_set_compression_mem_level( get_struct()
0377 , _info._compression_mem_level
0378 );
0379
0380 png_set_compression_strategy( get_struct()
0381 , _info._compression_strategy
0382 );
0383
0384 png_set_compression_window_bits( get_struct()
0385 , _info._compression_window_bits
0386 );
0387
0388 png_set_compression_method( get_struct()
0389 , _info._compression_method
0390 );
0391
0392 png_set_compression_buffer_size( get_struct()
0393 , _info._compression_buffer_size
0394 );
0395
0396 #ifdef BOOST_GIL_IO_PNG_DITHERING_SUPPORTED
0397
0398 if( _info._set_dithering )
0399 {
0400 png_set_dither( get_struct()
0401 , &_info._dithering_palette.front()
0402 , _info._dithering_num_palette
0403 , _info._dithering_maximum_colors
0404 , &_info._dithering_histogram.front()
0405 , _info._full_dither
0406 );
0407 }
0408 #endif
0409
0410
0411 if( _info._set_filter )
0412 {
0413 png_set_filter( get_struct()
0414 , 0
0415 , _info._filter
0416 );
0417 }
0418
0419
0420 if( _info._invert_mono )
0421 {
0422 png_set_invert_mono( get_struct() );
0423 }
0424
0425
0426 if( _info._set_true_bits )
0427 {
0428 png_set_sBIT( get_struct()
0429 , get_info()
0430 , &_info._true_bits.front()
0431 );
0432 }
0433
0434
0435 if( _info._set_srgb_intent )
0436 {
0437 png_set_sRGB( get_struct()
0438 , get_info()
0439 , _info._srgb_intent
0440 );
0441 }
0442
0443
0444 if( _info._strip_alpha )
0445 {
0446 png_set_strip_alpha( get_struct() );
0447 }
0448
0449
0450 if( _info._swap_alpha )
0451 {
0452 png_set_swap_alpha( get_struct() );
0453 }
0454
0455
0456 png_write_info( get_struct()
0457 , get_info()
0458 );
0459 }
0460
0461 protected:
0462
0463 static void write_data( png_structp png_ptr
0464 , png_bytep data
0465 , png_size_t length
0466 )
0467 {
0468 static_cast< Device* >( png_get_io_ptr( png_ptr ))->write( data
0469 , length );
0470 }
0471
0472 static void flush( png_structp png_ptr )
0473 {
0474 static_cast< Device* >(png_get_io_ptr(png_ptr) )->flush();
0475 }
0476
0477 private:
0478
0479 void init_io( png_structp png_ptr )
0480 {
0481 png_set_write_fn( png_ptr
0482 , static_cast< void* > ( &this->_io_dev )
0483 , static_cast< png_rw_ptr > ( &this_t::write_data )
0484 , static_cast< png_flush_ptr >( &this_t::flush )
0485 );
0486 }
0487
0488 public:
0489
0490 Device _io_dev;
0491
0492 image_write_info< png_tag > _info;
0493 };
0494
0495 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0496 #pragma warning(pop)
0497 #endif
0498
0499 }
0500 }
0501
0502 #endif