write.hpp 6.5 KB

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