1 // 2 // Copyright 2012 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_READER_BACKEND_HPP 9 #define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_READER_BACKEND_HPP 10 11 #include <boost/gil/extension/io/targa/tags.hpp> 12 13 namespace boost { namespace gil { 14 15 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) 16 #pragma warning(push) 17 #pragma warning(disable:4512) //assignment operator could not be generated 18 #endif 19 20 /// 21 /// Targa Backend 22 /// 23 template< typename Device > 24 struct reader_backend< Device 25 , targa_tag 26 > 27 { 28 public: 29 30 typedef targa_tag format_tag_t; 31 32 public: 33 reader_backendboost::gil::reader_backend34 reader_backend( const Device& io_dev 35 , const image_read_settings< targa_tag >& settings 36 ) 37 : _io_dev ( io_dev ) 38 , _scanline_length(0) 39 , _settings( settings ) 40 , _info() 41 { 42 read_header(); 43 44 if( _settings._dim.x == 0 ) 45 { 46 _settings._dim.x = _info._width; 47 } 48 49 if( _settings._dim.y == 0 ) 50 { 51 _settings._dim.y = _info._height; 52 } 53 } 54 read_headerboost::gil::reader_backend55 void read_header() 56 { 57 _info._header_size = targa_header_size::_size; 58 59 _info._offset = _io_dev.read_uint8() + _info._header_size; 60 61 _info._color_map_type = _io_dev.read_uint8(); 62 _info._image_type = _io_dev.read_uint8(); 63 64 _info._color_map_start = _io_dev.read_uint16(); 65 _info._color_map_length = _io_dev.read_uint16(); 66 _info._color_map_depth = _io_dev.read_uint8(); 67 68 _info._x_origin = _io_dev.read_uint16(); 69 _info._y_origin = _io_dev.read_uint16(); 70 71 _info._width = _io_dev.read_uint16(); 72 _info._height = _io_dev.read_uint16(); 73 74 if( _info._width < 1 || _info._height < 1 ) 75 { 76 io_error( "Invalid dimension for targa file" ); 77 } 78 79 _info._bits_per_pixel = _io_dev.read_uint8(); 80 if( _info._bits_per_pixel != 24 && _info._bits_per_pixel != 32 ) 81 { 82 io_error( "Unsupported bit depth for targa file" ); 83 } 84 85 _info._descriptor = _io_dev.read_uint8(); 86 87 // According to TGA specs, http://www.gamers.org/dEngine/quake3/TGA.txt, 88 // the image descriptor byte is: 89 // 90 // For Data Type 1, This entire byte should be set to 0. 91 if (_info._image_type == 1 && _info._descriptor != 0) 92 { 93 io_error("Unsupported descriptor for targa file"); 94 } 95 else if (_info._bits_per_pixel == 24) 96 { 97 // Bits 3-0 - For the Targa 24, it should be 0. 98 if ((_info._descriptor & 0x0FU) != 0) 99 { 100 io_error("Unsupported descriptor for targa file"); 101 } 102 } 103 else if (_info._bits_per_pixel == 32) 104 { 105 // Bits 3-0 - For Targa 32, it should be 8. 106 if (_info._descriptor != 8 && _info._descriptor != 40) 107 { 108 io_error("Unsupported descriptor for targa file"); 109 } 110 } 111 else 112 { 113 io_error("Unsupported descriptor for targa file"); 114 } 115 116 if (_info._descriptor & 32) 117 { 118 _info._screen_origin_bit = true; 119 } 120 121 _info._valid = true; 122 } 123 124 /// Check if image is large enough. check_image_sizeboost::gil::reader_backend125 void check_image_size( const point_t& img_dim ) 126 { 127 if( _settings._dim.x > 0 ) 128 { 129 if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); } 130 } 131 else 132 { 133 if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); } 134 } 135 136 137 if( _settings._dim.y > 0 ) 138 { 139 if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); } 140 } 141 else 142 { 143 if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); } 144 } 145 } 146 147 public: 148 149 Device _io_dev; 150 151 std::size_t _scanline_length; 152 153 image_read_settings< targa_tag > _settings; 154 image_read_info< targa_tag > _info; 155 }; 156 157 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) 158 #pragma warning(pop) 159 #endif 160 161 } // namespace gil 162 } // namespace boost 163 164 #endif 165