write.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. Copyright 2012 Christian Henning
  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_PNM_DETAIL_WRITE_HPP
  9. #define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_WRITE_HPP
  10. ////////////////////////////////////////////////////////////////////////////////////////
  11. /// \file
  12. /// \brief
  13. /// \author Christian Henning \n
  14. ///
  15. /// \date 2012 \n
  16. ///
  17. ////////////////////////////////////////////////////////////////////////////////////////
  18. #include <cstdlib>
  19. #include <string>
  20. #include <boost/gil/extension/io/pnm/tags.hpp>
  21. #include <boost/gil/io/base.hpp>
  22. #include <boost/gil/io/device.hpp>
  23. #include <boost/gil/extension/io/pnm/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. #endif
  29. namespace detail {
  30. struct pnm_write_is_supported
  31. {
  32. template< typename View >
  33. struct apply
  34. : public is_write_supported< typename get_pixel_type< View >::type
  35. , pnm_tag
  36. >
  37. {};
  38. };
  39. } // namespace detail
  40. ///
  41. /// PNM Writer
  42. ///
  43. template< typename Device >
  44. class writer< Device
  45. , pnm_tag
  46. >
  47. : public writer_backend< Device
  48. , pnm_tag
  49. >
  50. {
  51. private:
  52. typedef writer_backend< Device, pnm_tag > backend_t;
  53. public:
  54. writer( const Device& io_dev
  55. , const image_write_info< pnm_tag >& info
  56. )
  57. : backend_t( io_dev
  58. , info
  59. )
  60. {}
  61. template< typename View >
  62. void apply( const View& view )
  63. {
  64. typedef typename get_pixel_type< View >::type pixel_t;
  65. std::size_t width = view.width();
  66. std::size_t height = view.height();
  67. std::size_t chn = num_channels< View >::value;
  68. std::size_t pitch = chn * width;
  69. unsigned int type = get_type< num_channels< View >::value >( is_bit_aligned< pixel_t >() );
  70. // write header
  71. // Add a white space at each string so read_int() can decide when a numbers ends.
  72. std::string str( "P" );
  73. str += std::to_string( type ) + std::string( " " );
  74. this->_io_dev.print_line( str );
  75. str.clear();
  76. str += std::to_string( width ) + std::string( " " );
  77. this->_io_dev.print_line( str );
  78. str.clear();
  79. str += std::to_string( height ) + std::string( " " );
  80. this->_io_dev.print_line( str );
  81. if( type != pnm_image_type::mono_bin_t::value )
  82. {
  83. this->_io_dev.print_line( "255 ");
  84. }
  85. // write data
  86. write_data( view
  87. , pitch
  88. , typename is_bit_aligned< pixel_t >::type()
  89. );
  90. }
  91. private:
  92. template< int Channels >
  93. unsigned int get_type( mpl::true_ /* is_bit_aligned */ )
  94. {
  95. return boost::mpl::if_c< Channels == 1
  96. , pnm_image_type::mono_bin_t
  97. , pnm_image_type::color_bin_t
  98. >::type::value;
  99. }
  100. template< int Channels >
  101. unsigned int get_type( mpl::false_ /* is_bit_aligned */ )
  102. {
  103. return boost::mpl::if_c< Channels == 1
  104. , pnm_image_type::gray_bin_t
  105. , pnm_image_type::color_bin_t
  106. >::type::value;
  107. }
  108. template< typename View >
  109. void write_data( const View& src
  110. , std::size_t pitch
  111. , const mpl::true_& // bit_aligned
  112. )
  113. {
  114. BOOST_STATIC_ASSERT(( is_same< View
  115. , typename gray1_image_t::view_t
  116. >::value
  117. ));
  118. byte_vector_t row( pitch / 8 );
  119. typedef typename View::x_iterator x_it_t;
  120. x_it_t row_it = x_it_t( &( *row.begin() ));
  121. detail::negate_bits< byte_vector_t
  122. , mpl::true_
  123. > neg;
  124. detail::mirror_bits< byte_vector_t
  125. , mpl::true_
  126. > mirror;
  127. for( typename View::y_coord_t y = 0; y < src.height(); ++y )
  128. {
  129. std::copy( src.row_begin( y )
  130. , src.row_end( y )
  131. , row_it
  132. );
  133. mirror( row );
  134. neg ( row );
  135. this->_io_dev.write( &row.front()
  136. , pitch / 8
  137. );
  138. }
  139. }
  140. template< typename View >
  141. void write_data( const View& src
  142. , std::size_t pitch
  143. , const mpl::false_& // bit_aligned
  144. )
  145. {
  146. std::vector< pixel< typename channel_type< View >::type
  147. , layout<typename color_space_type< View >::type >
  148. >
  149. > buf( src.width() );
  150. // typedef typename View::value_type pixel_t;
  151. // typedef typename view_type_from_pixel< pixel_t >::type view_t;
  152. //view_t row = interleaved_view( src.width()
  153. // , 1
  154. // , reinterpret_cast< pixel_t* >( &buf.front() )
  155. // , pitch
  156. // );
  157. byte_t* row_addr = reinterpret_cast< byte_t* >( &buf.front() );
  158. for( typename View::y_coord_t y = 0
  159. ; y < src.height()
  160. ; ++y
  161. )
  162. {
  163. //copy_pixels( subimage_view( src
  164. // , 0
  165. // , (int) y
  166. // , (int) src.width()
  167. // , 1
  168. // )
  169. // , row
  170. // );
  171. std::copy( src.row_begin( y )
  172. , src.row_end ( y )
  173. , buf.begin()
  174. );
  175. this->_io_dev.write( row_addr, pitch );
  176. }
  177. }
  178. };
  179. ///
  180. /// PNM Writer
  181. ///
  182. template< typename Device >
  183. class dynamic_image_writer< Device
  184. , pnm_tag
  185. >
  186. : public writer< Device
  187. , pnm_tag
  188. >
  189. {
  190. typedef writer< Device
  191. , pnm_tag
  192. > parent_t;
  193. public:
  194. dynamic_image_writer( const Device& io_dev
  195. , const image_write_info< pnm_tag >& info
  196. )
  197. : parent_t( io_dev
  198. , info
  199. )
  200. {}
  201. template< typename Views >
  202. void apply( const any_image_view< Views >& views )
  203. {
  204. detail::dynamic_io_fnobj< detail::pnm_write_is_supported
  205. , parent_t
  206. > op( this );
  207. apply_operation( views, op );
  208. }
  209. };
  210. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  211. #pragma warning(pop)
  212. #endif
  213. } // gil
  214. } // boost
  215. #endif