diff options
Diffstat (limited to 'boost/gil/extension/io/jpeg/detail/write.hpp')
-rw-r--r-- | boost/gil/extension/io/jpeg/detail/write.hpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/boost/gil/extension/io/jpeg/detail/write.hpp b/boost/gil/extension/io/jpeg/detail/write.hpp new file mode 100644 index 0000000000..f9d2abfb57 --- /dev/null +++ b/boost/gil/extension/io/jpeg/detail/write.hpp @@ -0,0 +1,194 @@ +/* + Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev + Use, modification and distribution are subject to 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_WRITE_HPP +#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITE_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief +/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n +/// +/// \date 2007-2008 \n +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include <vector> + +#include <boost/gil/io/base.hpp> +#include <boost/gil/io/device.hpp> + +#include <boost/gil/extension/io/jpeg/tags.hpp> + +#include <boost/gil/extension/io/jpeg/detail/supported_types.hpp> +#include <boost/gil/extension/io/jpeg/detail/writer_backend.hpp> + +namespace boost { namespace gil { + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(push) +#pragma warning(disable:4512) //assignment operator could not be generated +#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable +#endif + +namespace detail { + +struct jpeg_write_is_supported +{ + template< typename View > + struct apply + : public is_write_supported< typename get_pixel_type< View >::type + , jpeg_tag + > + {}; +}; + +} // detail + +/// +/// JPEG Writer +/// +template< typename Device > +class writer< Device + , jpeg_tag + > + : public writer_backend< Device + , jpeg_tag + > +{ +public: + + typedef writer_backend< Device + , jpeg_tag + > backend_t; + +public: + + writer( const Device& io_dev + , const image_write_info< jpeg_tag >& info + ) + : backend_t( io_dev + , info + ) + {} + + template<typename View> + void apply( const View& view ) + { + write_rows( view ); + } + +private: + + template<typename View> + void write_rows( const View& view ) + { + std::vector< pixel< typename channel_type< View >::type + , layout<typename color_space_type< View >::type > + > + > row_buffer( view.width() ); + + // In case of an error we'll jump back to here and fire an exception. + // @todo Is the buffer above cleaned up when the exception is thrown? + // The strategy right now is to allocate necessary memory before + // the setjmp. + if( setjmp( this->_mark )) { this->raise_error(); } + + typedef typename channel_type< typename View::value_type >::type channel_t; + + this->get()->image_width = JDIMENSION( view.width() ); + this->get()->image_height = JDIMENSION( view.height() ); + this->get()->input_components = num_channels<View>::value; + this->get()->in_color_space = detail::jpeg_write_support< channel_t + , typename color_space_type< View >::type + >::_color_space; + + jpeg_set_defaults( this->get() ); + + jpeg_set_quality( this->get() + , this->_info._quality + , TRUE + ); + + // Needs to be done after jpeg_set_defaults() since it's overridding this value back to slow. + this->get()->dct_method = this->_info._dct_method; + + + // set the pixel dimensions + this->get()->density_unit = this->_info._density_unit; + this->get()->X_density = this->_info._x_density; + this->get()->Y_density = this->_info._y_density; + + // done reading header information + + jpeg_start_compress( this->get() + , TRUE + ); + + JSAMPLE* row_addr = reinterpret_cast< JSAMPLE* >( &row_buffer[0] ); + + for( int y =0; y != view.height(); ++ y ) + { + std::copy( view.row_begin( y ) + , view.row_end ( y ) + , row_buffer.begin() + ); + + jpeg_write_scanlines( this->get() + , &row_addr + , 1 + ); + } + } +}; + +/// +/// JPEG Dyamic Image Writer +/// +template< typename Device > +class dynamic_image_writer< Device + , jpeg_tag + > + : public writer< Device + , jpeg_tag + > +{ + typedef writer< Device + , jpeg_tag + > parent_t; + +public: + + dynamic_image_writer( const Device& io_dev + , const image_write_info< jpeg_tag >& info + ) + : parent_t( io_dev + , info + ) + {} + + template< typename Views > + void apply( const any_image_view< Views >& views ) + { + detail::dynamic_io_fnobj< detail::jpeg_write_is_supported + , parent_t + > op( this ); + + apply_operation( views, op ); + } +}; + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(pop) +#endif + +} // gil +} // boost + +#endif |