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  */
39 template< typename Pixel >
40 claw::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  */
61 template< typename Pixel >
62 claw::graphic::targa::reader::mapped_file_input_buffer<Pixel>::
63 mapped_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  */
85 template<typename InputBuffer>
86 claw::graphic::targa::reader::rle_targa_output_buffer<InputBuffer>::
87 rle_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  */
107 template<typename InputBuffer>
108 void 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  */
129 template<typename InputBuffer>
130 void 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  */
149 template<typename InputBuffer>
150 bool claw::graphic::targa::reader::rle_targa_output_buffer<InputBuffer>::
151 completed() 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  */
165 template<typename InputBuffer>
166 void
167 claw::graphic::targa::reader::rle_targa_output_buffer<InputBuffer>::
168 adjust_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  */
196 template< typename InputBuffer, typename OutputBuffer >
197 void
198 claw::graphic::targa::reader::rle_targa_decoder<InputBuffer, OutputBuffer>::
199 read_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  */
236 template<typename Pixel>
237 void 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  */
262 template<typename Decoder>
263 void 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  */
282 template<typename Pixel>
283 void 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  */
309 template<typename Decoder>
310 void 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  */
330 template<typename Pixel>
331 void 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()