summaryrefslogtreecommitdiff
path: root/boost/gil/extension/io/targa/detail/write.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/gil/extension/io/targa/detail/write.hpp')
-rw-r--r--boost/gil/extension/io/targa/detail/write.hpp197
1 files changed, 197 insertions, 0 deletions
diff --git a/boost/gil/extension/io/targa/detail/write.hpp b/boost/gil/extension/io/targa/detail/write.hpp
new file mode 100644
index 0000000000..223c1b2161
--- /dev/null
+++ b/boost/gil/extension/io/targa/detail/write.hpp
@@ -0,0 +1,197 @@
+/*
+ Copyright 2010-2012 Kenneth Riddile, Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile, Christian Henning \n
+///
+/// \date 2010-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/device.hpp>
+
+#include <boost/gil/extension/io/targa/tags.hpp>
+
+#include <boost/gil/extension/io/targa/detail/writer_backend.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+namespace detail {
+
+template < int N > struct get_targa_view_type {};
+template <> struct get_targa_view_type< 3 > { typedef bgr8_view_t type; };
+template <> struct get_targa_view_type< 4 > { typedef bgra8_view_t type; };
+
+struct targa_write_is_supported
+{
+ template< typename View >
+ struct apply
+ : public is_write_supported< typename get_pixel_type< View >::type
+ , targa_tag
+ >
+ {};
+};
+
+} // detail
+
+///
+/// TARGA Writer
+///
+template< typename Device >
+class writer< Device
+ , targa_tag
+ >
+ : public writer_backend< Device
+ , targa_tag
+ >
+{
+private:
+ typedef writer_backend< Device, targa_tag > backend_t;
+
+public:
+
+ writer( const Device& io_dev
+ , const image_write_info< targa_tag >& info
+ )
+ : backend_t( io_dev
+ , info
+ )
+ {}
+
+ template<typename View>
+ void apply( const View& view )
+ {
+ write( view );
+ }
+
+private:
+
+ template< typename View >
+ void write( const View& view )
+ {
+ uint8_t bit_depth = static_cast<uint8_t>( num_channels<View>::value * 8 );
+
+ // write the TGA header
+ this->_io_dev.write_uint8( 0 ); // offset
+ this->_io_dev.write_uint8( targa_color_map_type::_rgb );
+ this->_io_dev.write_uint8( targa_image_type::_rgb );
+ this->_io_dev.write_uint16( 0 ); // color map start
+ this->_io_dev.write_uint16( 0 ); // color map length
+ this->_io_dev.write_uint8( 0 ); // color map depth
+ this->_io_dev.write_uint16( 0 ); // x origin
+ this->_io_dev.write_uint16( 0 ); // y origin
+ this->_io_dev.write_uint16( static_cast<uint16_t>( view.width() ) ); // width in pixels
+ this->_io_dev.write_uint16( static_cast<uint16_t>( view.height() ) ); // height in pixels
+ this->_io_dev.write_uint8( bit_depth );
+
+ if( 32 == bit_depth )
+ {
+ this->_io_dev.write_uint8( 8 ); // 8-bit alpha channel descriptor
+ }
+ else
+ {
+ this->_io_dev.write_uint8( 0 );
+ }
+
+ write_image< View
+ , typename detail::get_targa_view_type< num_channels< View >::value >::type
+ >( view );
+ }
+
+
+ template< typename View
+ , typename TGA_View
+ >
+ void write_image( const View& view )
+ {
+ size_t row_size = view.width() * num_channels<View>::value;
+ byte_vector_t buffer( row_size );
+ std::fill( buffer.begin(), buffer.end(), 0 );
+
+
+ TGA_View row = interleaved_view( view.width()
+ , 1
+ , reinterpret_cast<typename TGA_View::value_type*>( &buffer.front() )
+ , row_size
+ );
+
+ for( typename View::y_coord_t y = view.height() - 1; y > -1; --y )
+ {
+ copy_pixels( subimage_view( view
+ , 0
+ , static_cast<int>( y )
+ , static_cast<int>( view.width() )
+ , 1
+ )
+ , row
+ );
+
+ this->_io_dev.write( &buffer.front(), row_size );
+ }
+
+ }
+};
+
+///
+/// TARGA Dynamic Image Writer
+///
+template< typename Device >
+class dynamic_image_writer< Device
+ , targa_tag
+ >
+ : public writer< Device
+ , targa_tag
+ >
+{
+ typedef writer< Device
+ , targa_tag
+ > parent_t;
+
+public:
+
+ dynamic_image_writer( const Device& io_dev
+ , const image_write_info< targa_tag >& info
+ )
+ : parent_t( io_dev
+ , info
+ )
+ {}
+
+ template< typename Views >
+ void apply( const any_image_view< Views >& views )
+ {
+ detail::dynamic_io_fnobj< detail::targa_write_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( views, op );
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // gil
+} // boost
+
+#endif