write.hpp 5.4 KB

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