--- io_new/formats/png/is_allowed.hpp 2009-01-27 18:06:14.000000000 -0600 +++ io_new/formats/png/is_allowed.hpp 2009-05-13 12:57:39.000000000 -0500 @@ -19,8 +19,130 @@ /// //////////////////////////////////////////////////////////////////////////////////////// +#include + namespace boost { namespace gil { namespace detail { +namespace png { + +// The following two functions look the same but are different since one is using +// a pixel_t as template parameter whereas the other is using reference_t. +template< typename View > +bool compare_channel_sizes( const std::vector< unsigned int >& channel_sizes // in bits + , mpl::false_ // is_bit_aligned + , mpl::true_ // is_homogeneous + ) +{ + typedef typename View::value_type pixel_t; + typedef typename channel_traits< + typename element_type< pixel_t >::type >::value_type channel_t; + + unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value; + + return ( s == channel_sizes[0] ); +} + + +template< typename View > +bool compare_channel_sizes( const std::vector< unsigned int >& channel_sizes // in bits + , mpl::true_ // is_bit_aligned + , mpl::true_ // is_homogeneous + ) +{ + typedef typename View::reference ref_t; + + typedef typename channel_traits< typename element_type< ref_t >::type >::value_type channel_t; + channel_t c; + + unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value; + + return ( s == channel_sizes[0] ); +} + +struct compare_channel_sizes_fn +{ + compare_channel_sizes_fn( unsigned int* a ) + : _a( a ) + , _b( true ) + {} + + template< typename ChannelSize > + void operator()( ChannelSize x) + { + if( x != *_a++ ) + { + _b = false; + } + } + + unsigned int* _a; + bool _b; +}; + +template< typename T > +struct channel_sizes_type {}; + +template< typename B, typename C, typename L, bool M > +struct channel_sizes_type< bit_aligned_pixel_reference< B, C, L, M > > { typedef C type; }; + +template< typename B, typename C, typename L, bool M > +struct channel_sizes_type< const bit_aligned_pixel_reference< B, C, L, M > > { typedef C type; }; + +template< typename View > +bool compare_channel_sizes( std::vector< unsigned int >& channel_sizes // in bits + , mpl::true_ // is_bit_aligned + , mpl::false_ // is_homogeneous + ) +{ + // loop through all channels and compare + + typedef typename View::reference ref_t; + typedef typename channel_sizes_type< ref_t >::type cs_t; + + compare_channel_sizes_fn fn( &channel_sizes.front() ); + mpl::for_each< cs_t >( fn ); + + return fn._b; +} + +} // namespace png + +template< typename View > +bool is_allowed( const std::vector< unsigned int >& src_s // array of channel sizes + , bool paletted // whether this is a palleted PNG + , mpl::true_ // is read_and_no_convert + ) +{ + if( paletted ) + return false; + + typedef typename View::value_type pixel_t; + typedef typename View::reference ref_t; + typedef typename channel_traits< + typename element_type< pixel_t >::type >::value_type channel_t; + + const typename num_channels< pixel_t >::value_type dst_n = num_channels< pixel_t >::value; + + const bool s( png::compare_channel_sizes< View >( src_s + , typename is_bit_aligned< ref_t >::type() + , typename is_homogeneous< ref_t >::type() + ) + ); + + return ( static_cast< unsigned int >( dst_n ) == src_s.size() + && s + ); +} + +template< typename View > +bool is_allowed( const std::vector< unsigned int >& src_s // array of channel sizes + , bool paletted // whether this is a palleted PNG + , mpl::false_ // is read_and_convert + ) +{ + return true; +} + } // namespace detail } // namespace gil } // namespace boost --- io_new/formats/png/read.hpp 2009-04-16 16:33:20.000000000 -0500 +++ io_new/formats/png/read.hpp 2009-05-13 13:38:57.000000000 -0500 @@ -85,12 +85,15 @@ &ret._interlace_method, &ret._compression_method, &ret._filter_method ); + ret._num_channels = png_get_channels( _png_ptr, _info_ptr ); + int res_unit = PNG_RESOLUTION_METER; png_get_pHYs(_png_ptr, _info_ptr, &ret._x_res, &ret._y_res, &res_unit); png_get_sBIT(_png_ptr, _info_ptr, &ret._sbits ); #ifdef PNG_FLOATING_POINT_SUPPORTED - png_get_gAMA(_png_ptr, _info_ptr, &ret._gamma ); + if ( !png_get_gAMA(_png_ptr, _info_ptr, &ret._gamma ) ) + ret._gamma = 1.0; #else png_get_gAMA_fixed(_png_ptr, _info_ptr, &ret._gamma ); #endif @@ -118,25 +121,37 @@ png_set_palette_to_rgb(_png_ptr); } - if(png_get_valid(_png_ptr, _info_ptr,PNG_INFO_tRNS)) + if(png_get_valid(_png_ptr, _info_ptr, PNG_INFO_tRNS)) { if( color_type == PNG_COLOR_TYPE_RGB ) + { color_type = PNG_COLOR_TYPE_RGBA; + this->_info._num_channels = 4; + } else if( color_type== PNG_COLOR_TYPE_GRAY ) + { color_type = PNG_COLOR_TYPE_GA; + this->_info._num_channels = 2; + } png_set_tRNS_to_alpha(_png_ptr); } +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_gamma( _png_ptr, this->_settings._gamma, this->_info._gamma ); +#endif + switch( color_type ) { case PNG_COLOR_TYPE_GRAY: { + if (bit_depth < 8) + png_set_gray_1_2_4_to_8(_png_ptr); switch( bit_depth ) { - case 1: read_rows< gray1_image_t::view_t::reference >( view ); break; - case 2: read_rows< gray2_image_t::view_t::reference >( view ); break; - case 4: read_rows< gray4_image_t::view_t::reference >( view ); break; + case 1: + case 2: + case 4: case 8: read_rows< gray8_pixel_t > ( view ); break; case 16:read_rows< gray16_pixel_t >( view ); break; default: io_error("png_reader::read_data(): unknown combination of color type and bit depth"); @@ -197,30 +212,57 @@ > void read_rows( const View& view ) { -/* - /// @todo - if( !is_allowed< View >( is_same< ConversionPolicy + std::vector< unsigned int > channel_sizes( this->_info._num_channels + , this->_info._bit_depth + ); + typedef typename is_same< ConversionPolicy , read_and_no_convert - >::type() + >::type is_read_and_convert_t; + bool paletted = this->_info._color_type == PNG_COLOR_TYPE_PALETTE; + if( !is_allowed< View >( channel_sizes + , paletted + , is_read_and_convert_t() )) { - throw std::runtime_error( "Image type aren't compatible." ); + io_error( "Image types aren't compatible." ); } -*/ + typedef row_buffer_helper_view< ImagePixel > row_buffer_helper_t; typedef typename row_buffer_helper_t::buffer_t buffer_t; typedef typename row_buffer_helper_t::iterator_t it_t; - row_buffer_helper_t buffer( static_cast( this->_info._width ) + bool interlaced = this->_info._interlace_method != PNG_INTERLACE_NONE; + + std::ptrdiff_t width = this->_info._width; + std::ptrdiff_t height = this->_info._height; + row_buffer_helper_t buffer( + static_cast( interlaced ? width * height : width ) , false ); - it_t begin = buffer.begin(); + if( interlaced ) { + std::vector< png_bytep > row_ptrs( height ); + for( int y = 0; y < height; ++y ) { + row_ptrs[y] = reinterpret_cast< png_bytep >( buffer.data() + y * width ); + } + png_read_image( _png_ptr, &row_ptrs.front() ); + for( int y = 0; y < view.height(); ++y ) + { + it_t begin = buffer.begin() + y * width; it_t first = begin + this->_settings._top_left.x; it_t last = begin + this->_settings._dim.x; // one after last element + this->_cc_policy.read( first + , last + , view.row_begin( y )); + } + } else { + it_t begin = buffer.begin(); + + it_t first = begin + this->_settings._top_left.x; + it_t last = begin + this->_settings._dim.x; // one after last element // skip rows for( int y = 0; y < this->_settings._top_left.y; ++y ) @@ -243,6 +285,7 @@ , view.row_begin( y )); } } + } void init_reader() { --- io_new/formats/tiff/is_allowed.hpp 2009-04-28 14:42:06.000000000 -0500 +++ io_new/formats/tiff/is_allowed.hpp 2009-05-13 12:49:33.000000000 -0500 @@ -23,6 +23,8 @@ namespace boost { namespace gil { namespace detail { +namespace jpeg { + template< typename Channel > int format_value( mpl::true_ ) // is_bit_aligned { @@ -130,6 +132,8 @@ return fn._b; } +} // namespace jpeg + template< typename View > bool is_allowed( unsigned int src_n // num channels , const std::vector< unsigned int >& src_s // array of channel sizes @@ -143,19 +147,19 @@ typename element_type< pixel_t >::type >::value_type channel_t; const typename num_channels< pixel_t >::value_type dst_n = num_channels< pixel_t >::value; - const typename num_channels< pixel_t >::value_type dst_f = format_value< channel_t >( typename is_bit_aligned< pixel_t >::type() ); + const typename num_channels< pixel_t >::value_type dst_f = jpeg::format_value< channel_t >( typename is_bit_aligned< pixel_t >::type() ); - const bool s( compare_channel_sizes< View >( src_s + const bool s( jpeg::compare_channel_sizes< View >( src_s , typename is_bit_aligned< ref_t >::type() , typename is_homogeneous< ref_t >::type() ) ); - return ( dst_n == src_n + return ( static_cast< unsigned int >( dst_n ) == src_n && s - && dst_f == src_f + && static_cast< unsigned int >( dst_f ) == src_f ); } --- io_new/png_tags.hpp 2009-04-12 16:21:20.000000000 -0500 +++ io_new/png_tags.hpp 2009-05-13 09:21:03.000000000 -0500 @@ -85,16 +85,28 @@ { image_read_settings< png_tag >() : image_read_settings_base() +#ifdef PNG_FLOATING_POINT_SUPPORTED + , _gamma( 1.0 ) +#endif {} image_read_settings( const point_t& top_left , const point_t& dim +#ifdef PNG_FLOATING_POINT_SUPPORTED + , double gamma = 1.0 +#endif ) : image_read_settings_base( top_left , dim ) +#ifdef PNG_FLOATING_POINT_SUPPORTED + , _gamma( gamma ) +#endif {} +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_gamma::type _gamma; +#endif }; template<>