1 // 2 // Copyright 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_SCANLINE_READ_HPP 9 #define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_SCANLINE_READ_HPP 10 11 #include <boost/gil/extension/io/targa/detail/is_allowed.hpp> 12 #include <boost/gil/extension/io/targa/detail/reader_backend.hpp> 13 14 #include <boost/gil/io/base.hpp> 15 #include <boost/gil/io/bit_operations.hpp> 16 #include <boost/gil/io/conversion_policies.hpp> 17 #include <boost/gil/io/device.hpp> 18 #include <boost/gil/io/reader_base.hpp> 19 #include <boost/gil/io/row_buffer_helper.hpp> 20 #include <boost/gil/io/scanline_read_iterator.hpp> 21 #include <boost/gil/io/typedefs.hpp> 22 23 #include <vector> 24 25 namespace boost { namespace gil { 26 27 /// 28 /// Targa Scanline Reader 29 /// 30 template< typename Device > 31 class scanline_reader< Device 32 , targa_tag 33 > 34 : public reader_backend< Device 35 , targa_tag 36 > 37 { 38 public: 39 40 using tag_t = targa_tag; 41 using backend_t = reader_backend<Device, tag_t>; 42 using this_t = scanline_reader<Device, tag_t>; 43 using iterator_t = scanline_read_iterator<this_t>; 44 45 // 46 // Constructor 47 // scanline_reader(Device & device,const image_read_settings<targa_tag> & settings)48 scanline_reader( Device& device 49 , const image_read_settings< targa_tag >& settings 50 ) 51 : backend_t( device 52 , settings 53 ) 54 { 55 initialize(); 56 } 57 58 /// Read part of image defined by View and return the data. read(byte_t * dst,int pos)59 void read( byte_t* dst, int pos ) 60 { 61 // jump to scanline 62 long offset = this->_info._offset 63 + ( this->_info._height - 1 - pos ) * static_cast< long >( this->_scanline_length ); 64 65 this->_io_dev.seek( offset ); 66 67 68 read_row( dst ); 69 } 70 71 /// Skip over a scanline. skip(byte_t *,int)72 void skip( byte_t*, int ) 73 { 74 this->_io_dev.seek( static_cast<long>( this->_scanline_length ) 75 , SEEK_CUR 76 ); 77 } 78 begin()79 iterator_t begin() { return iterator_t( *this ); } end()80 iterator_t end() { return iterator_t( *this, this->_info._height ); } 81 82 private: 83 initialize()84 void initialize() 85 { 86 if( this->_info._color_map_type != targa_color_map_type::_rgb ) 87 { 88 io_error( "scanline reader cannot read indexed targa files." ); 89 } 90 91 if( this->_info._image_type != targa_image_type::_rgb ) 92 { 93 io_error( "scanline reader cannot read this targa image type." ); 94 } 95 96 switch( this->_info._image_type ) 97 { 98 case targa_image_type::_rgb: 99 { 100 if( this->_info._color_map_type != targa_color_map_type::_rgb ) 101 { 102 io_error( "Inconsistent color map type and image type in targa file." ); 103 } 104 105 if( this->_info._color_map_length != 0 ) 106 { 107 io_error( "Non-indexed targa files containing a palette are not supported." ); 108 } 109 110 if( this->_info._screen_origin_bit ) 111 { 112 io_error( "scanline reader cannot read targa files which have screen origin bit set." ); 113 } 114 115 switch( this->_info._bits_per_pixel ) 116 { 117 case 24: 118 case 32: 119 { 120 this->_scanline_length = this->_info._width * ( this->_info._bits_per_pixel / 8 ); 121 122 // jump to first scanline 123 this->_io_dev.seek( static_cast< long >( this->_info._offset )); 124 125 break; 126 } 127 default: 128 { 129 io_error( "Unsupported bit depth in targa file." ); 130 break; 131 } 132 } 133 134 break; 135 } 136 default: 137 { 138 io_error( "Unsupported image type in targa file." ); 139 break; 140 } 141 } 142 } 143 read_row(byte_t * dst)144 void read_row( byte_t* dst ) 145 { 146 this->_io_dev.read( dst, this->_scanline_length ); 147 } 148 }; 149 150 } // namespace gil 151 } // namespace boost 152 153 #endif 154