Claw  1.7.3
image.cpp
Go to the documentation of this file.
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 */
30 #include <claw/image.hpp>
31 #include <claw/exception.hpp>
32 #include <claw/bitmap.hpp>
33 #include <claw/gif.hpp>
34 #include <claw/pcx.hpp>
35 #include <claw/targa.hpp>
36 #include <claw/xbm.hpp>
37 
38 #ifdef CLAW_PNG_SUPPORT
39 /* The png.h file must be included before any other file that includes setjmp.h
40  (as jpeg.hpp). */
41 #include <claw/png.hpp>
42 #endif // CLAW_PNG_SUPPORT
43 
44 #ifdef CLAW_JPEG_SUPPORT
45 #include <claw/jpeg.hpp>
46 #endif // CLAW_JPEG_SUPPORT
47 
48 #include <algorithm>
49 
50 /*----------------------------------------------------------------------------*/
55 {
56  return super::begin();
57 } // image::scanline::begin()
58 
59 /*----------------------------------------------------------------------------*/
64 {
65  return super::end();
66 } // image::scanline::end()
67 
68 /*----------------------------------------------------------------------------*/
74 {
75  return super::begin();
76 } // image::scanline::begin()
77 
78 /*----------------------------------------------------------------------------*/
84 {
85  return super::end();
86 } // image::scanline::end()
87 
88 /*----------------------------------------------------------------------------*/
94 {
95  return super::size();
96 } // image::scanline::size()
97 
98 
99 
100 
101 /*----------------------------------------------------------------------------*/
107 {
108 
109 } // image::image() [default constructor]
110 
111 /*----------------------------------------------------------------------------*/
116 claw::graphic::image::image( std::istream& f )
117 {
118  load(f);
119 } // image::image() [constructor]
120 
121 /*----------------------------------------------------------------------------*/
128 claw::graphic::image::image( unsigned int w, unsigned int h )
129 {
130  set_size(w, h);
131 } // image::image() [constructor]
132 
133 /*----------------------------------------------------------------------------*/
139 {
140  std::swap(m_data, that.m_data);
141 } // image::swap()
142 
143 /*----------------------------------------------------------------------------*/
147 unsigned int claw::graphic::image::width() const
148 {
149  if ( m_data.empty() )
150  return 0;
151  else
152  return m_data[0].size();
153 } // image::width()
154 
155 /*----------------------------------------------------------------------------*/
159 unsigned int claw::graphic::image::height() const
160 {
161  return m_data.size();
162 } // image::height()
163 
164 /*----------------------------------------------------------------------------*/
169 {
170  return iterator(*this);
171 } // image::begin()
172 
173 /*----------------------------------------------------------------------------*/
178 {
179  return iterator(*this, width(), height()-1);
180 } // image::end()
181 
182 /*----------------------------------------------------------------------------*/
187 {
188  return const_iterator(*this);
189 } // image::begin()
190 
191 /*----------------------------------------------------------------------------*/
196 {
197  return const_iterator(*this, width(), height()-1);
198 } // image::end()
199 
200 /*----------------------------------------------------------------------------*/
206 {
207  merge( that, math::coordinate_2d<int>(0, 0) );
208 } // image::merge()
209 
210 /*----------------------------------------------------------------------------*/
217 ( const image& that, const math::coordinate_2d<int>& pos )
218 {
219  math::rectangle<int> my_box(0, 0, width(), height());
220  math::rectangle<int> his_box(pos.x, pos.y, that.width(), that.height());
221 
222  if ( my_box.intersects( his_box ) )
223  {
224  math::rectangle<int> intersection;
225  unsigned int that_y = pos.y < 0 ? -pos.y : 0;
226  unsigned int that_x = pos.x < 0 ? -pos.x : 0;
227  const double max_comp
228  ( std::numeric_limits<rgba_pixel::component_type>::max() );
229 
230  intersection = my_box.intersection( his_box );
231 
232  for (int y=0; y!=intersection.height; ++y)
233  {
234  scanline::const_iterator first = that[y + that_y].begin() + that_x;
235  scanline::const_iterator last = first + intersection.width;
236  scanline::iterator dest = (*this)[y + intersection.position.y].begin()
237  + intersection.position.x;
238 
239  for( ; first!=last; ++first, ++dest )
240  {
241  const double src_alpha( first->components.alpha );
242  const double dest_alpha
243  ( dest->components.alpha * (max_comp - src_alpha) );
244 
245  const double red =
246  (double)first->components.red * src_alpha
247  + (double)dest->components.red * dest_alpha;
248  const double green =
249  (double)first->components.green * src_alpha
250  + (double)dest->components.green * dest_alpha;
251  const double blue =
252  (double)first->components.blue * src_alpha
253  + (double)dest->components.blue * dest_alpha;
254  const double alpha = src_alpha + dest_alpha;
255 
256  dest->components.red = std::min(red, max_comp);
257  dest->components.green = std::min(green, max_comp);
258  dest->components.blue = std::min(blue, max_comp);
259  dest->components.alpha = std::min(alpha, max_comp);
260  }
261  }
262  }
263 } // image::merge()
264 
265 /*----------------------------------------------------------------------------*/
272 (const image& that, const math::coordinate_2d<int>& pos )
273 {
274  math::rectangle<int> my_box(0, 0, width(), height());
275  math::rectangle<int> his_box(pos.x, pos.y, that.width(), that.height());
276 
277  if ( my_box.intersects( his_box ) )
278  {
279  math::rectangle<int> intersection;
280  unsigned int that_y = pos.y < 0 ? -pos.y : 0;
281  unsigned int that_x = pos.x < 0 ? -pos.x : 0;
282 
283  intersection = my_box.intersection( his_box );
284 
285  for (int y=0; y!=intersection.height; ++y)
286  {
287  scanline::const_iterator first = that[y + that_y].begin() + that_x;
288  scanline::const_iterator last = first + intersection.width;
289  scanline::iterator dest = (*this)[y + intersection.position.y].begin()
290  + intersection.position.x;
291 
292  std::copy( first, last, dest );
293  }
294  }
295 } // image::partial_copy()
296 
297 /*----------------------------------------------------------------------------*/
302 {
303  for (unsigned int y=0; y!=height()/2; ++y)
304  std::swap( m_data[y], m_data[height()-y-1] );
305 } // image::flip()
306 
307 /*----------------------------------------------------------------------------*/
314 ( const math::rectangle<int> r, const pixel_type& c )
315 {
316  math::rectangle<int> my_box(0, 0, width(), height());
317 
318  if ( my_box.intersects( r ) )
319  {
320  const math::rectangle<int> intersection( my_box.intersection( r ) );
321  const double max_comp
322  ( std::numeric_limits<rgba_pixel::component_type>::max() );
323 
324  for (int y=0; y!=intersection.height; ++y)
325  {
327  (*this)[intersection.position.y + y].begin()
328  + intersection.position.x;
329  const scanline::iterator last = first + intersection.width;
330 
331  for( ; first!=last; ++first )
332  {
333  const double src_alpha(c.components.alpha);
334 
335  double red =
336  (double)first->components.red
337  + src_alpha * (double)c.components.red / max_comp;
338  double green =
339  (double)first->components.green
340  + src_alpha * (double)c.components.green / max_comp;
341  double blue =
342  (double)first->components.blue
343  + src_alpha * (double)c.components.blue / max_comp;
344  double alpha = (double)first->components.alpha
345  + (max_comp - src_alpha) / max_comp;
346 
347  first->components.red = std::min(red, max_comp);
348  first->components.green = std::min(green, max_comp);
349  first->components.blue = std::min(blue, max_comp);
350  first->components.alpha = std::min(alpha, max_comp);
351  }
352  }
353  }
354 } // image::fill()
355 
356 /*----------------------------------------------------------------------------*/
363 void claw::graphic::image::set_size( unsigned int w, unsigned int h )
364 {
365  if (w == 0)
366  m_data.clear();
367  else
368  {
369  m_data.resize(h);
370 
371  for (unsigned int y=0; y!=height(); ++y)
372  m_data[y].resize(w);
373  }
374 } // image::set_size()
375 
376 /*----------------------------------------------------------------------------*/
381 void claw::graphic::image::load( std::istream& f )
382 {
383  bool ok = false;
384 
385 #ifdef CLAW_JPEG_SUPPORT
386  if (!ok)
387  try { jpeg::reader( *this, f ); ok = true; }
388  catch( ... ) { }
389 #endif // CLAW_JPEG_SUPPORT
390 
391 #ifdef CLAW_PNG_SUPPORT
392  if (!ok)
393  try { png::reader( *this, f ); ok = true; }
394  catch( ... ) { }
395 #endif // CLAW_PNG_SUPPORT
396 
397  if (!ok)
398  try { bitmap::reader( *this, f ); ok = true; }
399  catch( ... ) { }
400 
401  if (!ok)
402  try { targa::reader( *this, f ); ok = true; }
403  catch( ... ) { }
404 
405  if (!ok)
406  try { gif::reader( *this, f ); ok = true; }
407  catch( ... ) { }
408 
409  if (!ok)
410  try { pcx::reader( *this, f ); ok = true; }
411  catch( ... ) { }
412 
413  if (!ok)
414  try { xbm::reader( *this, f ); ok = true; }
415  catch( ... ) { }
416 
417  if (!ok)
418  throw claw::bad_format( "image::load: file format isn't supported." );
419 } // image::load()
420 
421 
422 
423 
424 /*----------------------------------------------------------------------------*/
431 {
432  a.swap(b);
433 } // swap()
This class read data from a pcx file and store it in an image.
Definition: pcx.hpp:158
This class read data from a png file and store it in an image.
Definition: png.hpp:56
This class reads data from a gif file. The image is resized to the size of the screen (as defined in ...
Definition: gif.hpp:279
coordinate_2d< value_type > position
value_typeop left coordinates.
Definition: rectangle.hpp:108
This class read data from a bitmap file and store it in an image.
Definition: bitmap.hpp:134
void partial_copy(const image &that, const math::coordinate_2d< int > &pos)
Copy an image on the current image.
Definition: image.cpp:272
A class for jpeg pictures.
super::const_iterator const_iterator
Const iterator in the line.
Definition: image.hpp:81
iterator end()
Get an iterator pointing just past the last pixel.
Definition: image.cpp:177
size_type size() const
Get the length of the line.
Definition: image.cpp:93
unsigned int height() const
Gets image&#39;s height.
Definition: image.cpp:159
struct claw::graphic::rgba_pixel::@15::@17 components
Component by component representation.
This class read data from a targa file and store it in an image.
Definition: targa.hpp:216
super::size_type size_type
An unsigned integral type.
Definition: image.hpp:84
void flip()
Set the image upside down.
Definition: image.cpp:301
void swap(image &that)
Swap the content of two images.
Definition: image.cpp:138
void fill(const math::rectangle< int > r, const pixel_type &c)
Fill an area of the image with a given color.
Definition: image.cpp:314
Fuction object to get the first element of a std::pair.
Definition: functional.hpp:44
A class for png pictures.
Base class for iterators on an image.
Definition: image.hpp:106
iterator end()
Get en iterator past the last pixel.
Definition: image.cpp:63
void load(std::istream &f)
Read the image from a stream.
Definition: image.cpp:381
A class representing a rectangle by his x,y coordinates, width and height.
Definition: box_2d.hpp:39
A class for bitmap pictures.
This class read data from a xbm file and store it in an image.
Definition: xbm.hpp:53
Image class for gif files.
value_type height
Height.
Definition: rectangle.hpp:114
This class read data from a jpeg file and store it in an image.
Definition: jpeg.hpp:80
image()
Constructor. Creates an image without datas.
Definition: image.cpp:106
void swap(claw::tween::tweener &a, claw::tween::tweener &b)
Swap two tweeners.
Definition: tweener.cpp:138
value_type y
Y-coordinate.
super::iterator iterator
Iterator in the line.
Definition: image.hpp:78
A class for pcx pictures.
unsigned int width() const
Gets image&#39;s width.
Definition: image.cpp:147
A simple class to use as exception with string message.
void merge(const image &that)
Merge an image on the current image.
Definition: image.cpp:205
iterator begin()
Get an iterator on the first pixel.
Definition: image.cpp:54
iterator begin()
Get an iterator pointing on the first pixel.
Definition: image.cpp:168
A class to deal with images.
Definition: image.hpp:49
A class for targa pictures.
A class for xbm pictures.
value_type width
Width.
Definition: rectangle.hpp:111
void set_size(unsigned int w, unsigned int h)
Set a new size to the image.
Definition: image.cpp:363
Exception thrown when accessing bad formated data.
Definition: exception.hpp:70
value_type x
X-coordinate.
A class to deal with images.