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++
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
|