2 // Copyright 2012 Christian Henning
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
8 #ifndef BOOST_GIL_EXTENSION_IO_PNM_DETAIL_WRITE_HPP
9 #define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_WRITE_HPP
11 #include <boost/gil/extension/io/pnm/tags.hpp>
12 #include <boost/gil/extension/io/pnm/detail/writer_backend.hpp>
14 #include <boost/gil/io/base.hpp>
15 #include <boost/gil/io/bit_operations.hpp>
16 #include <boost/gil/io/device.hpp>
17 #include <boost/gil/io/dynamic_io_new.hpp>
18 #include <boost/gil/detail/mp11.hpp>
22 #include <type_traits>
24 namespace boost { namespace gil {
26 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
28 #pragma warning(disable:4512) //assignment operator could not be generated
33 struct pnm_write_is_supported
35 template< typename View >
37 : public is_write_supported< typename get_pixel_type< View >::type
48 template< typename Device >
52 : public writer_backend< Device
57 using backend_t = writer_backend<Device, pnm_tag>;
61 writer( const Device& io_dev
62 , const image_write_info< pnm_tag >& info
69 template< typename View >
70 void apply( const View& view )
72 using pixel_t = typename get_pixel_type<View>::type;
74 std::size_t width = view.width();
75 std::size_t height = view.height();
77 std::size_t chn = num_channels< View >::value;
78 std::size_t pitch = chn * width;
80 unsigned int type = get_type< num_channels< View >::value >( is_bit_aligned< pixel_t >() );
84 // Add a white space at each string so read_int() can decide when a numbers ends.
86 std::string str( "P" );
87 str += std::to_string( type ) + std::string( " " );
88 this->_io_dev.print_line( str );
91 str += std::to_string( width ) + std::string( " " );
92 this->_io_dev.print_line( str );
95 str += std::to_string( height ) + std::string( " " );
96 this->_io_dev.print_line( str );
98 if( type != pnm_image_type::mono_bin_t::value )
100 this->_io_dev.print_line( "255 ");
106 , typename is_bit_aligned< pixel_t >::type()
112 template< int Channels >
113 unsigned int get_type( std::true_type /* is_bit_aligned */ )
118 pnm_image_type::mono_bin_t,
119 pnm_image_type::color_bin_t
123 template< int Channels >
124 unsigned int get_type( std::false_type /* is_bit_aligned */ )
129 pnm_image_type::gray_bin_t,
130 pnm_image_type::color_bin_t
134 template< typename View >
135 void write_data( const View& src
137 , const std::true_type& // bit_aligned
140 static_assert(std::is_same<View, typename gray1_image_t::view_t>::value, "");
142 byte_vector_t row( pitch / 8 );
144 using x_it_t = typename View::x_iterator;
145 x_it_t row_it = x_it_t( &( *row.begin() ));
147 detail::negate_bits<byte_vector_t, std::true_type> negate;
148 detail::mirror_bits<byte_vector_t, std::true_type> mirror;
149 for (typename View::y_coord_t y = 0; y < src.height(); ++y)
151 std::copy(src.row_begin(y), src.row_end(y), row_it);
156 this->_io_dev.write(&row.front(), pitch / 8);
160 template< typename View >
161 void write_data( const View& src
163 , const std::false_type& // bit_aligned
166 std::vector< pixel< typename channel_type< View >::type
167 , layout<typename color_space_type< View >::type >
169 > buf( src.width() );
171 // using pixel_t = typename View::value_type;
172 // using view_t = typename view_type_from_pixel< pixel_t >::type;
174 //view_t row = interleaved_view( src.width()
176 // , reinterpret_cast< pixel_t* >( &buf.front() )
180 byte_t* row_addr = reinterpret_cast< byte_t* >( &buf.front() );
182 for( typename View::y_coord_t y = 0
187 //copy_pixels( subimage_view( src
190 // , (int) src.width()
196 std::copy( src.row_begin( y )
201 this->_io_dev.write( row_addr, pitch );
209 template< typename Device >
210 class dynamic_image_writer< Device
213 : public writer< Device
217 using parent_t = writer<Device, pnm_tag>;
221 dynamic_image_writer( const Device& io_dev
222 , const image_write_info< pnm_tag >& info
229 template< typename Views >
230 void apply( const any_image_view< Views >& views )
232 detail::dynamic_io_fnobj< detail::pnm_write_is_supported
236 apply_operation( views, op );
240 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)