write.hpp 6.6 KB

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