2 // Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 #ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITE_HPP
9 #define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITE_HPP
11 #include <boost/gil/extension/io/jpeg/tags.hpp>
12 #include <boost/gil/extension/io/jpeg/detail/supported_types.hpp>
13 #include <boost/gil/extension/io/jpeg/detail/writer_backend.hpp>
15 #include <boost/gil/io/base.hpp>
16 #include <boost/gil/io/device.hpp>
17 #include <boost/gil/io/dynamic_io_new.hpp>
21 namespace boost { namespace gil {
23 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
25 #pragma warning(disable:4512) //assignment operator could not be generated
26 #pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
31 struct jpeg_write_is_supported
33 template< typename View >
35 : public is_write_supported< typename get_pixel_type< View >::type
46 template< typename Device >
50 : public writer_backend< Device
56 using backend_t = writer_backend<Device, jpeg_tag>;
60 writer( const Device& io_dev
61 , const image_write_info< jpeg_tag >& info
68 template<typename View>
69 void apply( const View& view )
76 template<typename View>
77 void write_rows( const View& view )
79 std::vector< pixel< typename channel_type< View >::type
80 , layout<typename color_space_type< View >::type >
82 > row_buffer( view.width() );
84 // In case of an error we'll jump back to here and fire an exception.
85 // @todo Is the buffer above cleaned up when the exception is thrown?
86 // The strategy right now is to allocate necessary memory before
88 if( setjmp( this->_mark )) { this->raise_error(); }
90 using channel_t = typename channel_type<typename View::value_type>::type;
92 this->get()->image_width = JDIMENSION( view.width() );
93 this->get()->image_height = JDIMENSION( view.height() );
94 this->get()->input_components = num_channels<View>::value;
95 this->get()->in_color_space = detail::jpeg_write_support< channel_t
96 , typename color_space_type< View >::type
99 jpeg_set_defaults( this->get() );
101 jpeg_set_quality( this->get()
102 , this->_info._quality
106 // Needs to be done after jpeg_set_defaults() since it's overridding this value back to slow.
107 this->get()->dct_method = this->_info._dct_method;
110 // set the pixel dimensions
111 this->get()->density_unit = this->_info._density_unit;
112 this->get()->X_density = this->_info._x_density;
113 this->get()->Y_density = this->_info._y_density;
115 // done reading header information
117 jpeg_start_compress( this->get()
121 JSAMPLE* row_addr = reinterpret_cast< JSAMPLE* >( &row_buffer[0] );
123 for( int y =0; y != view.height(); ++ y )
125 std::copy( view.row_begin( y )
130 jpeg_write_scanlines( this->get()
136 jpeg_finish_compress ( this->get() );
141 /// JPEG Dyamic Image Writer
143 template< typename Device >
144 class dynamic_image_writer< Device
147 : public writer< Device
151 using parent_t = writer<Device, jpeg_tag>;
155 dynamic_image_writer( const Device& io_dev
156 , const image_write_info< jpeg_tag >& info
163 template< typename ...Views >
164 void apply( const any_image_view< Views... >& views )
166 detail::dynamic_io_fnobj< detail::jpeg_write_is_supported
170 apply_operation( views, op );
174 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)