write.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. */
  7. /*************************************************************************************************/
  8. #ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITE_HPP
  9. #define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITE_HPP
  10. ////////////////////////////////////////////////////////////////////////////////////////
  11. /// \file
  12. /// \brief
  13. /// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
  14. ///
  15. /// \date 2007-2008 \n
  16. ///
  17. ////////////////////////////////////////////////////////////////////////////////////////
  18. #include <vector>
  19. #include <boost/gil/io/base.hpp>
  20. #include <boost/gil/io/device.hpp>
  21. #include <boost/gil/extension/io/jpeg/tags.hpp>
  22. #include <boost/gil/extension/io/jpeg/detail/supported_types.hpp>
  23. #include <boost/gil/extension/io/jpeg/detail/writer_backend.hpp>
  24. namespace boost { namespace gil {
  25. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  26. #pragma warning(push)
  27. #pragma warning(disable:4512) //assignment operator could not be generated
  28. #pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
  29. #endif
  30. namespace detail {
  31. struct jpeg_write_is_supported
  32. {
  33. template< typename View >
  34. struct apply
  35. : public is_write_supported< typename get_pixel_type< View >::type
  36. , jpeg_tag
  37. >
  38. {};
  39. };
  40. } // detail
  41. ///
  42. /// JPEG Writer
  43. ///
  44. template< typename Device >
  45. class writer< Device
  46. , jpeg_tag
  47. >
  48. : public writer_backend< Device
  49. , jpeg_tag
  50. >
  51. {
  52. public:
  53. typedef writer_backend< Device
  54. , jpeg_tag
  55. > backend_t;
  56. public:
  57. writer( const Device& io_dev
  58. , const image_write_info< jpeg_tag >& info
  59. )
  60. : backend_t( io_dev
  61. , info
  62. )
  63. {}
  64. template<typename View>
  65. void apply( const View& view )
  66. {
  67. write_rows( view );
  68. }
  69. private:
  70. template<typename View>
  71. void write_rows( const View& view )
  72. {
  73. std::vector< pixel< typename channel_type< View >::type
  74. , layout<typename color_space_type< View >::type >
  75. >
  76. > row_buffer( view.width() );
  77. // In case of an error we'll jump back to here and fire an exception.
  78. // @todo Is the buffer above cleaned up when the exception is thrown?
  79. // The strategy right now is to allocate necessary memory before
  80. // the setjmp.
  81. if( setjmp( this->_mark )) { this->raise_error(); }
  82. typedef typename channel_type< typename View::value_type >::type channel_t;
  83. this->get()->image_width = JDIMENSION( view.width() );
  84. this->get()->image_height = JDIMENSION( view.height() );
  85. this->get()->input_components = num_channels<View>::value;
  86. this->get()->in_color_space = detail::jpeg_write_support< channel_t
  87. , typename color_space_type< View >::type
  88. >::_color_space;
  89. jpeg_set_defaults( this->get() );
  90. jpeg_set_quality( this->get()
  91. , this->_info._quality
  92. , TRUE
  93. );
  94. // Needs to be done after jpeg_set_defaults() since it's overridding this value back to slow.
  95. this->get()->dct_method = this->_info._dct_method;
  96. // set the pixel dimensions
  97. this->get()->density_unit = this->_info._density_unit;
  98. this->get()->X_density = this->_info._x_density;
  99. this->get()->Y_density = this->_info._y_density;
  100. // done reading header information
  101. jpeg_start_compress( this->get()
  102. , TRUE
  103. );
  104. JSAMPLE* row_addr = reinterpret_cast< JSAMPLE* >( &row_buffer[0] );
  105. for( int y =0; y != view.height(); ++ y )
  106. {
  107. std::copy( view.row_begin( y )
  108. , view.row_end ( y )
  109. , row_buffer.begin()
  110. );
  111. jpeg_write_scanlines( this->get()
  112. , &row_addr
  113. , 1
  114. );
  115. }
  116. }
  117. };
  118. ///
  119. /// JPEG Dyamic Image Writer
  120. ///
  121. template< typename Device >
  122. class dynamic_image_writer< Device
  123. , jpeg_tag
  124. >
  125. : public writer< Device
  126. , jpeg_tag
  127. >
  128. {
  129. typedef writer< Device
  130. , jpeg_tag
  131. > parent_t;
  132. public:
  133. dynamic_image_writer( const Device& io_dev
  134. , const image_write_info< jpeg_tag >& info
  135. )
  136. : parent_t( io_dev
  137. , info
  138. )
  139. {}
  140. template< typename Views >
  141. void apply( const any_image_view< Views >& views )
  142. {
  143. detail::dynamic_io_fnobj< detail::jpeg_write_is_supported
  144. , parent_t
  145. > op( this );
  146. apply_operation( views, op );
  147. }
  148. };
  149. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  150. #pragma warning(pop)
  151. #endif
  152. } // gil
  153. } // boost
  154. #endif