• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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