You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
5.1 KiB
C++

//
// Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_SCANLINE_READ_HPP
#define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_SCANLINE_READ_HPP
#include <boost/gil/extension/io/png/detail/is_allowed.hpp>
#include <boost/gil/extension/io/png/detail/reader_backend.hpp>
#include <boost/gil.hpp> // FIXME: Include what you use!
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/conversion_policies.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/reader_base.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>
#include <boost/gil/io/scanline_read_iterator.hpp>
#include <boost/gil/io/typedefs.hpp>
namespace boost { namespace gil {
///
/// PNG Reader
///
template< typename Device >
class scanline_reader< Device
, png_tag
>
: public reader_backend< Device
, png_tag
>
{
public:
using tag_t = png_tag;
using backend_t = reader_backend<Device, tag_t>;
using this_t = scanline_reader<Device, tag_t>;
using iterator_t = scanline_read_iterator<this_t>;
//
// Constructor
//
scanline_reader( const Device& io_dev
, const image_read_settings< png_tag >& settings
)
: reader_backend< Device
, png_tag
>( io_dev
, settings
)
{
initialize();
}
void read( byte_t* dst
, int
)
{
read_scanline( dst );
}
/// Skip over a scanline.
void skip( byte_t* dst, int )
{
read_scanline( dst );
}
iterator_t begin() { return iterator_t( *this ); }
iterator_t end() { return iterator_t( *this, this->_info._height ); }
private:
void initialize()
{
// Now it's time for some transformations.
if( little_endian() )
{
if( this->_info._bit_depth == 16 )
{
// Swap bytes of 16 bit files to least significant byte first.
png_set_swap( this->get()->_struct );
}
if( this->_info._bit_depth < 8 )
{
// swap bits of 1, 2, 4 bit packed pixel formats
png_set_packswap( this->get()->_struct );
}
}
if( this->_info._color_type == PNG_COLOR_TYPE_PALETTE )
{
png_set_palette_to_rgb( this->get()->_struct );
}
if( this->_info._num_trans > 0 )
{
png_set_tRNS_to_alpha( this->get()->_struct );
}
// Tell libpng to handle the gamma conversion for you. The final call
// is a good guess for PC generated images, but it should be configurable
// by the user at run time by the user. It is strongly suggested that
// your application support gamma correction.
if( this->_settings._apply_screen_gamma )
{
// png_set_gamma will change the image data!
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
png_set_gamma( this->get()->_struct
, this->_settings._screen_gamma
, this->_info._file_gamma
);
#else
png_set_gamma( this->get()->_struct
, this->_settings._screen_gamma
, this->_info._file_gamma
);
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
}
// Interlaced images are not supported.
this->_number_passes = png_set_interlace_handling( this->get()->_struct );
io_error_if( this->_number_passes != 1
, "scanline_read_iterator cannot read interlaced png images."
);
// The above transformation might have changed the bit_depth and color type.
png_read_update_info( this->get()->_struct
, this->get()->_info
);
this->_info._bit_depth = png_get_bit_depth( this->get()->_struct
, this->get()->_info
);
this->_info._num_channels = png_get_channels( this->get()->_struct
, this->get()->_info
);
this->_info._color_type = png_get_color_type( this->get()->_struct
, this->get()->_info
);
this->_scanline_length = png_get_rowbytes( this->get()->_struct
, this->get()->_info
);
}
void read_scanline( byte_t* dst )
{
png_read_row( this->get()->_struct
, dst
, NULL
);
}
};
} // namespace gil
} // namespace boost
#endif