Claw 1.7.3
targa_reader.tpp
1/*
2 CLAW - a C++ Library Absolutely Wonderful
3
4 CLAW is a free library without any particular aim but being useful to
5 anyone.
6
7 Copyright (C) 2005-2011 Julien Jorge
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
23 contact: julien.jorge@gamned.org
24*/
25/**
26 * \file targa_reader.tpp
27 * \brief Implementation of the template methods of the targa::reader class and
28 * subclasses.
29 * \author Julien Jorge
30 */
31#include <limits>
32#include <iterator>
33
34/*----------------------------------------------------------------------------*/
35/**
36 * \brief Constructor.
37 * \param f The file to read.
38 */
39template< typename Pixel >
40claw::graphic::targa::reader::file_input_buffer<Pixel>::file_input_buffer
41( std::istream& f )
42 : buffered_istream<std::istream>(f)
43{
44
45} // targa::reader::file_input_buffer::file_input_buffer
46
47
48
49
50//*****************************************************************************/
51
52
53
54
55/*----------------------------------------------------------------------------*/
56/**
57 * \brief Constructor.
58 * \param f The file to read.
59 * \param p The color palette.
60 */
61template< typename Pixel >
62claw::graphic::targa::reader::mapped_file_input_buffer<Pixel>::
63mapped_file_input_buffer
64( std::istream& f, const color_palette32& p )
65 : buffered_istream<std::istream>(f), m_palette(p)
66{
67
68} // targa::reader::mapped_file_input_buffer::mapped_file_input_buffer
69
70
71
72
73//*****************************************************************************/
74
75
76
77
78/*----------------------------------------------------------------------------*/
79/**
80 * \brief Constructor.
81 * \param img The targa image we're loading.
82 * \param up_down Tell if the image is stored from top to bottom.
83 * \param left_right Tell if the image is stored from left to right.
84 */
85template<typename InputBuffer>
86claw::graphic::targa::reader::rle_targa_output_buffer<InputBuffer>::
87rle_targa_output_buffer( image& img, bool up_down, bool left_right )
88 : m_image(img), m_x_inc(left_right ? 1 : -1), m_y_inc(up_down ? 1 : -1)
89{
90 if (up_down)
91 m_y = 0;
92 else
93 m_y = m_image.height() - 1;
94
95 if (left_right)
96 m_x = 0;
97 else
98 m_x = m_image.width() - 1;
99} // targa::reader::rle_targa_output_buffer::rle_targa_output_buffer()
100
101/*----------------------------------------------------------------------------*/
102/**
103 * \brief Copy a pixel a certain number of times.
104 * \param n The number of pixel to write.
105 * \param pattern The pixel to copy.
106 */
107template<typename InputBuffer>
108void claw::graphic::targa::reader::rle_targa_output_buffer<InputBuffer>::fill
109( unsigned int n, rgba_pixel_8 pattern )
110{
111 assert( (int)(m_x + m_x_inc * n) >= -1 );
112 assert( m_x + m_x_inc * n <= m_image.width() );
113
114 const int bound = (int)m_x + m_x_inc * n;
115 int x = m_x;
116
117 for ( ; x != bound; x += m_x_inc )
118 m_image[m_y][x] = pattern;
119
120 adjust_position(x);
121} // targa::reader::rle_targa_output_buffer::fill()
122
123/*----------------------------------------------------------------------------*/
124/**
125 * \brief Direct copy of a certain number of pixels from the file.
126 * \param n The number of pixels to write.
127 * \param buffer The buffer from which we read.
128 */
129template<typename InputBuffer>
130void claw::graphic::targa::reader::rle_targa_output_buffer<InputBuffer>::copy
131( unsigned int n, input_buffer_type& buffer )
132{
133 assert( (int)(m_x + m_x_inc * n) >= -1 );
134 assert( m_x + m_x_inc * n <= m_image.width() );
135
136 const int bound = (int)m_x + m_x_inc * n;
137 int x = m_x;
138
139 for ( ; x != bound; x += m_x_inc )
140 m_image[m_y][x] = buffer.get_pixel();
141
142 adjust_position(x);
143} // targa::reader::rle_targa_output_buffer::copy()
144
145/*----------------------------------------------------------------------------*/
146/**
147 * \brief Tell if we have completely filled the image.
148 */
149template<typename InputBuffer>
150bool claw::graphic::targa::reader::rle_targa_output_buffer<InputBuffer>::
151completed() const
152{
153 return ( (int)m_y == -1 ) || ( m_y == m_image.height() );
154} // targa::reader::rle_targa_output_buffer::completed()
155
156/*----------------------------------------------------------------------------*/
157/**
158 * \brief Recalculate the position in the file.
159 * \param x The x-coordinate where we stopped.
160 *
161 * If \a x is lower tha zero, the position is set at the end of the previous
162 * line ; if \a is greater or equal to the width of the image, the position is
163 * set at the begining of the next line ; otherwise the position is set to \a x.
164 */
165template<typename InputBuffer>
166void
167claw::graphic::targa::reader::rle_targa_output_buffer<InputBuffer>::
168adjust_position(int x)
169{
170 if (x < 0)
171 {
172 m_x = m_image.width() - 1;
173 m_y += m_y_inc;
174 }
175 else if (x >= (int)m_image.width())
176 {
177 m_x = 0;
178 m_y += m_y_inc;
179 }
180 else
181 m_x = x;
182} // targa::reader::rle_targa_output_buffer::adjust_position()
183
184
185
186//*****************************************************************************/
187
188
189
190/*----------------------------------------------------------------------------*/
191/**
192 * \brief Get the type of the following data in the input buffer.
193 * \param input The input stream (the targa file).
194 * \param output The output stream (the targa image).
195 */
196template< typename InputBuffer, typename OutputBuffer >
197void
198claw::graphic::targa::reader::rle_targa_decoder<InputBuffer, OutputBuffer>::
199read_mode( input_buffer_type& input, output_buffer_type& output )
200{
201 this->m_mode = this->stop;
202 bool ok = !output.completed();
203
204 if ( ok && (input.remaining() < 1) )
205 ok = input.read_more(1);
206
207 if (ok)
208 {
209 char key = input.get_next();
210
211 this->m_count = (key & 0x7F) + 1;
212
213 if (key & 0x80) // compressed
214 {
215 this->m_mode = this->compressed;
216 this->m_pattern = input.get_pixel();
217 }
218 else
219 this->m_mode = this->raw;
220 }
221} // targa::reader::rle_targa_decoder::read_mode()
222
223
224
225//*****************************************************************************/
226
227
228/*----------------------------------------------------------------------------*/
229/**
230 * \brief Load an uncompressed true color targa file.
231 * \param h File's header, must have been read before call.
232 * \param f Targa file.
233 * \param palette The color palette of the image.
234 * \pre f.is_open()
235 */
236template<typename Pixel>
237void claw::graphic::targa::reader::load_color_mapped_raw
238( const header& h, std::istream& f, const color_palette32& palette )
239{
240 /* We use a part of the rle framework but there isn't any compressed data
241 here. We only use the direct copy of the rle algorithm. */
242
243 typedef mapped_file_input_buffer<Pixel> input_buffer_type;
244
245 rle_targa_output_buffer<input_buffer_type> output
246 ( m_image, h.image_specification.up_down_oriented(),
247 h.image_specification.left_right_oriented() );
248 input_buffer_type input(f, palette);
249
250 for ( unsigned int i=0; i!=m_image.height(); ++i )
251 output.copy( m_image.width(), input );
252} // targa::reader::load_true_color_raw()
253
254/*----------------------------------------------------------------------------*/
255/**
256 * \brief Load a RLE color mapped targa file.
257 * \param h File's header, must have been read before call.
258 * \param f Targa file.
259 * \param palette The color palette of the image.
260 * \pre f.is_open()
261 */
262template<typename Decoder>
263void claw::graphic::targa::reader::decompress_rle_color_mapped
264( const header& h, std::istream& f, const color_palette32& palette )
265{
266 Decoder decoder;
267 typename Decoder::output_buffer_type output_buffer
268 (m_image, h.image_specification.up_down_oriented(),
269 h.image_specification.left_right_oriented() );
270 typename Decoder::input_buffer_type input_buffer(f, palette);
271
272 decoder.decode(input_buffer, output_buffer);
273} // targa::reader::decompress_rle_color_mapped()
274
275/*----------------------------------------------------------------------------*/
276/**
277 * \brief Load an uncompressed true color targa file.
278 * \param h File's header, must have been read before call.
279 * \param f Targa file.
280 * \pre f.is_open() && !h.color_map
281 */
282template<typename Pixel>
283void claw::graphic::targa::reader::load_true_color_raw
284( const header& h, std::istream& f )
285{
286 assert(!h.color_map);
287
288 /* We use a part of the rle framework but there isn't any compressed data
289 here. We only use the direct copy of the rle algorithm. */
290
291 typedef file_input_buffer<Pixel> input_buffer_type;
292
293 rle_targa_output_buffer<input_buffer_type> output
294 ( m_image, h.image_specification.up_down_oriented(),
295 h.image_specification.left_right_oriented() );
296 input_buffer_type input(f);
297
298 for ( unsigned int i=0; i!=m_image.height(); ++i )
299 output.copy( m_image.width(), input );
300} // targa::reader::load_true_color_raw()
301
302/*----------------------------------------------------------------------------*/
303/**
304 * \brief Load a true color RLE targa file.
305 * \param h File's header, must have been read before call.
306 * \param f Targa file.
307 * \pre f.is_open() && !h.color_map
308 */
309template<typename Decoder>
310void claw::graphic::targa::reader::decompress_rle_true_color
311( const header& h, std::istream& f )
312{
313 assert(!h.color_map);
314
315 Decoder decoder;
316 typename Decoder::output_buffer_type output_buffer
317 (m_image, h.image_specification.up_down_oriented(),
318 h.image_specification.left_right_oriented() );
319 typename Decoder::input_buffer_type input_buffer(f);
320
321 decoder.decode(input_buffer, output_buffer);
322} // targa::reader::decompress_rle_true_color()
323
324/*----------------------------------------------------------------------------*/
325/**
326 * \brief Load the content of the color palette.
327 * \param f Targa file.
328 * \param palette (out) The color palette.
329 */
330template<typename Pixel>
331void claw::graphic::targa::reader::load_palette_content
332( std::istream& f, color_palette32& palette ) const
333{
334 file_input_buffer<Pixel> input(f);
335
336 for (unsigned int i=0; i!=palette.size(); ++i)
337 palette[i] = input.get_pixel();
338} // targa::reader::load_palette_content()