// // 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_JPEG_DETAIL_SCANLINE_READ_HPP #define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SCANLINE_READ_HPP #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace gil { #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) #pragma warning(push) #pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable #endif /// /// JPEG Scanline Reader /// template< typename Device > class scanline_reader< Device , jpeg_tag > : public reader_backend< Device , jpeg_tag > { public: using tag_t = jpeg_tag; using backend_t = reader_backend; using this_t = scanline_reader; using iterator_t = scanline_read_iterator; public: scanline_reader( Device& device , const image_read_settings< jpeg_tag >& settings ) : reader_backend< Device , jpeg_tag >( device , settings ) { initialize(); } void read( byte_t* dst , int ) { // Fire exception in case of error. if( setjmp( this->_mark )) { this->raise_error(); } // read data read_scanline( dst ); } /// Skip over a scanline. void skip( byte_t* dst, int ) { // Fire exception in case of error. if( setjmp( this->_mark )) { this->raise_error(); } // read data read_scanline( dst ); } iterator_t begin() { return iterator_t( *this ); } iterator_t end() { return iterator_t( *this, this->_info._height ); } private: void initialize() { this->get()->dct_method = this->_settings._dct_method; io_error_if( jpeg_start_decompress( this->get() ) == false , "Cannot start decompression." ); switch( this->_info._color_space ) { case JCS_GRAYSCALE: { this->_scanline_length = this->_info._width; break; } case JCS_RGB: //!\todo add Y'CbCr? We loose image quality when reading JCS_YCbCr as JCS_RGB case JCS_YCbCr: { this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value; break; } case JCS_CMYK: //!\todo add Y'CbCrK? We loose image quality when reading JCS_YCCK as JCS_CMYK case JCS_YCCK: { this->get()->out_color_space = JCS_CMYK; this->_scanline_length = this->_info._width * num_channels< cmyk8_view_t >::value; break; } default: { io_error( "Unsupported jpeg color space." ); } } } void read_scanline( byte_t* dst ) { JSAMPLE *row_adr = reinterpret_cast< JSAMPLE* >( dst ); // Read data. io_error_if( jpeg_read_scanlines( this->get() , &row_adr , 1 ) != 1 , "jpeg_read_scanlines: fail to read JPEG file" ); } }; #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) #pragma warning(pop) #endif } // namespace gil } // namespace boost #endif