write.hpp 5.0 KB

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