write.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. //
  2. // Copyright 2010-2012 Kenneth Riddile, 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_TARGA_DETAIL_WRITE_HPP
  9. #define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_WRITE_HPP
  10. #include <boost/gil/extension/io/targa/tags.hpp>
  11. #include <boost/gil/extension/io/targa/detail/writer_backend.hpp>
  12. #include <boost/gil/io/base.hpp>
  13. #include <boost/gil/io/device.hpp>
  14. #include <boost/gil/io/detail/dynamic.hpp>
  15. #include <vector>
  16. namespace boost { namespace gil {
  17. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  18. #pragma warning(push)
  19. #pragma warning(disable:4512) //assignment operator could not be generated
  20. #endif
  21. namespace detail {
  22. template < int N > struct get_targa_view_type {};
  23. template <> struct get_targa_view_type< 3 > { using type = bgr8_view_t; };
  24. template <> struct get_targa_view_type< 4 > { using type = bgra8_view_t; };
  25. struct targa_write_is_supported
  26. {
  27. template< typename View >
  28. struct apply
  29. : public is_write_supported< typename get_pixel_type< View >::type
  30. , targa_tag
  31. >
  32. {};
  33. };
  34. } // detail
  35. ///
  36. /// TARGA Writer
  37. ///
  38. template< typename Device >
  39. class writer< Device
  40. , targa_tag
  41. >
  42. : public writer_backend< Device
  43. , targa_tag
  44. >
  45. {
  46. private:
  47. using backend_t = writer_backend<Device, targa_tag>;
  48. public:
  49. writer( const Device& io_dev
  50. , const image_write_info< targa_tag >& info
  51. )
  52. : backend_t( io_dev
  53. , info
  54. )
  55. {}
  56. template<typename View>
  57. void apply( const View& view )
  58. {
  59. write( view );
  60. }
  61. private:
  62. template< typename View >
  63. void write( const View& view )
  64. {
  65. uint8_t bit_depth = static_cast<uint8_t>( num_channels<View>::value * 8 );
  66. // write the TGA header
  67. this->_io_dev.write_uint8( 0 ); // offset
  68. this->_io_dev.write_uint8( targa_color_map_type::_rgb );
  69. this->_io_dev.write_uint8( targa_image_type::_rgb );
  70. this->_io_dev.write_uint16( 0 ); // color map start
  71. this->_io_dev.write_uint16( 0 ); // color map length
  72. this->_io_dev.write_uint8( 0 ); // color map depth
  73. this->_io_dev.write_uint16( 0 ); // x origin
  74. this->_io_dev.write_uint16( 0 ); // y origin
  75. this->_io_dev.write_uint16( static_cast<uint16_t>( view.width() ) ); // width in pixels
  76. this->_io_dev.write_uint16( static_cast<uint16_t>( view.height() ) ); // height in pixels
  77. this->_io_dev.write_uint8( bit_depth );
  78. if( 32 == bit_depth )
  79. {
  80. this->_io_dev.write_uint8( 8 ); // 8-bit alpha channel descriptor
  81. }
  82. else
  83. {
  84. this->_io_dev.write_uint8( 0 );
  85. }
  86. write_image< View
  87. , typename detail::get_targa_view_type< num_channels< View >::value >::type
  88. >( view );
  89. }
  90. template< typename View
  91. , typename TGA_View
  92. >
  93. void write_image( const View& view )
  94. {
  95. size_t row_size = view.width() * num_channels<View>::value;
  96. byte_vector_t buffer( row_size );
  97. std::fill( buffer.begin(), buffer.end(), 0 );
  98. TGA_View row = interleaved_view( view.width()
  99. , 1
  100. , reinterpret_cast<typename TGA_View::value_type*>( &buffer.front() )
  101. , row_size
  102. );
  103. for( typename View::y_coord_t y = view.height() - 1; y > -1; --y )
  104. {
  105. copy_pixels( subimage_view( view
  106. , 0
  107. , static_cast<int>( y )
  108. , static_cast<int>( view.width() )
  109. , 1
  110. )
  111. , row
  112. );
  113. this->_io_dev.write( &buffer.front(), row_size );
  114. }
  115. }
  116. };
  117. ///
  118. /// TARGA Dynamic Image Writer
  119. ///
  120. template< typename Device >
  121. class dynamic_image_writer< Device
  122. , targa_tag
  123. >
  124. : public writer< Device
  125. , targa_tag
  126. >
  127. {
  128. using parent_t = writer<Device, targa_tag>;
  129. public:
  130. dynamic_image_writer( const Device& io_dev
  131. , const image_write_info< targa_tag >& info
  132. )
  133. : parent_t( io_dev
  134. , info
  135. )
  136. {}
  137. template< typename ...Views >
  138. void apply( const any_image_view< Views... >& views )
  139. {
  140. detail::dynamic_io_fnobj< detail::targa_write_is_supported
  141. , parent_t
  142. > op( this );
  143. variant2::visit( op, views );
  144. }
  145. };
  146. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  147. #pragma warning(pop)
  148. #endif
  149. } // gil
  150. } // boost
  151. #endif