write.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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/dynamic_io_new.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. }
  108. };
  109. ///
  110. /// JPEG Dyamic Image Writer
  111. ///
  112. template< typename Device >
  113. class dynamic_image_writer< Device
  114. , jpeg_tag
  115. >
  116. : public writer< Device
  117. , jpeg_tag
  118. >
  119. {
  120. using parent_t = writer<Device, jpeg_tag>;
  121. public:
  122. dynamic_image_writer( const Device& io_dev
  123. , const image_write_info< jpeg_tag >& info
  124. )
  125. : parent_t( io_dev
  126. , info
  127. )
  128. {}
  129. template< typename Views >
  130. void apply( const any_image_view< Views >& views )
  131. {
  132. detail::dynamic_io_fnobj< detail::jpeg_write_is_supported
  133. , parent_t
  134. > op( this );
  135. apply_operation( views, op );
  136. }
  137. };
  138. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  139. #pragma warning(pop)
  140. #endif
  141. } // gil
  142. } // boost
  143. #endif