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());
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(dest->components.alpha);
243 
244  double red =
245  (double)first->components.red
246  + dest_alpha * (double)dest->components.red / max_comp;
247  double green =
248  (double)first->components.green
249  + dest_alpha * (double)dest->components.green / max_comp;
250  double blue =
251  (double)first->components.blue
252  + dest_alpha * (double)dest->components.blue / max_comp;
253  double alpha = src_alpha + (max_comp - dest_alpha) / max_comp;
254 
255  dest->components.red = std::min(red, max_comp);
256  dest->components.green = std::min(green, max_comp);
257  dest->components.blue = std::min(blue, max_comp);
258  dest->components.alpha = std::min(alpha, max_comp);
259  }
260  }
261  }
262 } // image::merge()
263 
264 /*----------------------------------------------------------------------------*/
271 (const image& that, const math::coordinate_2d<int>& pos )
272 {
273  math::rectangle<int> my_box(0, 0, width(), height());
274  math::rectangle<int> his_box(pos.x, pos.y, that.width(), that.height());
275 
276  if ( my_box.intersects( his_box ) )
277  {
278  math::rectangle<int> intersection;
279  unsigned int that_y = pos.y < 0 ? -pos.y : 0;
280  unsigned int that_x = pos.x < 0 ? -pos.x : 0;
281 
282  intersection = my_box.intersection( his_box );
283 
284  for (int y=0; y!=intersection.height; ++y)
285  {
286  scanline::const_iterator first = that[y + that_y].begin() + that_x;
287  scanline::const_iterator last = first + intersection.width;
288  scanline::iterator dest = (*this)[y + intersection.position.y].begin()
289  + intersection.position.x;
290 
291  std::copy( first, last, dest );
292  }
293  }
294 } // image::partial_copy()
295 
296 /*----------------------------------------------------------------------------*/
301 {
302  for (unsigned int y=0; y!=height()/2; ++y)
303  std::swap( m_data[y], m_data[height()-y-1] );
304 } // image::flip()
305 
306 /*----------------------------------------------------------------------------*/
313 ( const math::rectangle<int> r, const pixel_type& c )
314 {
315  math::rectangle<int> my_box(0, 0, width(), height());
316 
317  if ( my_box.intersects( r ) )
318  {
319  const math::rectangle<int> intersection( my_box.intersection( r ) );
320  const double max_comp
321  ( std::numeric_limits<rgba_pixel::component_type>::max() );
322 
323  for (int y=0; y!=intersection.height; ++y)
324  {
326  (*this)[intersection.position.y + y].begin()
327  + intersection.position.x;
328  const scanline::iterator last = first + intersection.width;
329 
330  for( ; first!=last; ++first )
331  {
332  const double src_alpha(c.components.alpha);
333 
334  double red =
335  (double)first->components.red
336  + src_alpha * (double)c.components.red / max_comp;
337  double green =
338  (double)first->components.green
339  + src_alpha * (double)c.components.green / max_comp;
340  double blue =
341  (double)first->components.blue
342  + src_alpha * (double)c.components.blue / max_comp;
343  double alpha = (double)first->components.alpha
344  + (max_comp - src_alpha) / max_comp;
345 
346  first->components.red = std::min(red, max_comp);
347  first->components.green = std::min(green, max_comp);
348  first->components.blue = std::min(blue, max_comp);
349  first->components.alpha = std::min(alpha, max_comp);
350  }
351  }
352  }
353 } // image::fill()
354 
355 /*----------------------------------------------------------------------------*/
362 void claw::graphic::image::set_size( unsigned int w, unsigned int h )
363 {
364  if (w == 0)
365  m_data.clear();
366  else
367  {
368  m_data.resize(h);
369 
370  for (unsigned int y=0; y!=height(); ++y)
371  m_data[y].resize(w);
372  }
373 } // image::set_size()
374 
375 /*----------------------------------------------------------------------------*/
380 void claw::graphic::image::load( std::istream& f )
381 {
382  bool ok = false;
383 
384 #ifdef CLAW_JPEG_SUPPORT
385  if (!ok)
386  try { jpeg::reader( *this, f ); ok = true; }
387  catch( ... ) { }
388 #endif // CLAW_JPEG_SUPPORT
389 
390 #ifdef CLAW_PNG_SUPPORT
391  if (!ok)
392  try { png::reader( *this, f ); ok = true; }
393  catch( ... ) { }
394 #endif // CLAW_PNG_SUPPORT
395 
396  if (!ok)
397  try { bitmap::reader( *this, f ); ok = true; }
398  catch( ... ) { }
399 
400  if (!ok)
401  try { targa::reader( *this, f ); ok = true; }
402  catch( ... ) { }
403 
404  if (!ok)
405  try { gif::reader( *this, f ); ok = true; }
406  catch( ... ) { }
407 
408  if (!ok)
409  try { pcx::reader( *this, f ); ok = true; }
410  catch( ... ) { }
411 
412  if (!ok)
413  try { xbm::reader( *this, f ); ok = true; }
414  catch( ... ) { }
415 
416  if (!ok)
417  throw claw::bad_format( "image::load: file format isn't supported." );
418 } // image::load()
419 
420 
421 
422 
423 /*----------------------------------------------------------------------------*/
430 {
431  a.swap(b);
432 } // swap()