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 /*----------------------------------------------------------------------------*/
430 void std::swap( claw::graphic::image& a, claw::graphic::image& b )
431 {
432  a.swap(b);
433 } // swap()