Claw  1.7.0
image.cpp
Go to the documentation of this file.
00001 /*
00002   CLAW - a C++ Library Absolutely Wonderful
00003 
00004   CLAW is a free library without any particular aim but being useful to 
00005   anyone.
00006 
00007   Copyright (C) 2005-2011 Julien Jorge
00008 
00009   This library is free software; you can redistribute it and/or
00010   modify it under the terms of the GNU Lesser General Public
00011   License as published by the Free Software Foundation; either
00012   version 2.1 of the License, or (at your option) any later version.
00013 
00014   This library is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017   Lesser General Public License for more details.
00018 
00019   You should have received a copy of the GNU Lesser General Public
00020   License along with this library; if not, write to the Free Software
00021   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023   contact: julien.jorge@gamned.org
00024 */
00030 #include <claw/image.hpp>
00031 #include <claw/exception.hpp>
00032 #include <claw/bitmap.hpp>
00033 #include <claw/gif.hpp>
00034 #include <claw/pcx.hpp>
00035 #include <claw/targa.hpp>
00036 #include <claw/xbm.hpp>
00037 
00038 #ifdef CLAW_PNG_SUPPORT
00039 /* The png.h file must be included before any other file that includes setjmp.h
00040    (as jpeg.hpp). */
00041 #include <claw/png.hpp>
00042 #endif // CLAW_PNG_SUPPORT
00043 
00044 #ifdef CLAW_JPEG_SUPPORT
00045 #include <claw/jpeg.hpp>
00046 #endif // CLAW_JPEG_SUPPORT
00047 
00048 #include <algorithm>
00049 
00050 /*----------------------------------------------------------------------------*/
00054 claw::graphic::image::scanline::iterator claw::graphic::image::scanline::begin()
00055 {
00056   return super::begin();
00057 } // image::scanline::begin()
00058 
00059 /*----------------------------------------------------------------------------*/
00063 claw::graphic::image::scanline::iterator claw::graphic::image::scanline::end()
00064 {
00065   return super::end();
00066 } // image::scanline::end()
00067 
00068 /*----------------------------------------------------------------------------*/
00072 claw::graphic::image::scanline::const_iterator
00073 claw::graphic::image::scanline::begin() const
00074 {
00075   return super::begin();
00076 } // image::scanline::begin()
00077 
00078 /*----------------------------------------------------------------------------*/
00082 claw::graphic::image::scanline::const_iterator
00083 claw::graphic::image::scanline::end() const
00084 {
00085   return super::end();
00086 } // image::scanline::end()
00087 
00088 /*----------------------------------------------------------------------------*/
00092 claw::graphic::image::scanline::size_type
00093 claw::graphic::image::scanline::size() const
00094 {
00095   return super::size();
00096 } // image::scanline::size()
00097 
00098 
00099 
00100 
00101 /*----------------------------------------------------------------------------*/
00106 claw::graphic::image::image()
00107 {
00108 
00109 } // image::image() [default constructor]
00110 
00111 /*----------------------------------------------------------------------------*/
00116 claw::graphic::image::image( std::istream& f )
00117 {
00118   load(f);
00119 } // image::image() [constructor]
00120 
00121 /*----------------------------------------------------------------------------*/
00128 claw::graphic::image::image( unsigned int w, unsigned int h )
00129 {
00130   set_size(w, h);
00131 } // image::image() [constructor]
00132 
00133 /*----------------------------------------------------------------------------*/
00138 void claw::graphic::image::swap( image& that )
00139 {
00140   std::swap(m_data, that.m_data);
00141 } // image::swap()
00142 
00143 /*----------------------------------------------------------------------------*/
00147 unsigned int claw::graphic::image::width() const
00148 {
00149   if ( m_data.empty() )
00150     return 0;
00151   else
00152     return m_data[0].size(); 
00153 } // image::width()
00154 
00155 /*----------------------------------------------------------------------------*/
00159 unsigned int claw::graphic::image::height() const
00160 {
00161   return m_data.size();
00162 } // image::height()
00163 
00164 /*----------------------------------------------------------------------------*/
00168 claw::graphic::image::iterator claw::graphic::image::begin()
00169 {
00170   return iterator(*this);
00171 } // image::begin()
00172 
00173 /*----------------------------------------------------------------------------*/
00177 claw::graphic::image::iterator claw::graphic::image::end()
00178 {
00179   return iterator(*this, width(), height()-1);
00180 } // image::end()
00181 
00182 /*----------------------------------------------------------------------------*/
00186 claw::graphic::image::const_iterator claw::graphic::image::begin() const
00187 {
00188   return const_iterator(*this);
00189 } // image::begin()
00190 
00191 /*----------------------------------------------------------------------------*/
00195 claw::graphic::image::const_iterator claw::graphic::image::end() const
00196 {
00197   return const_iterator(*this, width(), height());
00198 } // image::end()
00199 
00200 /*----------------------------------------------------------------------------*/
00205 void claw::graphic::image::merge( const image& that )
00206 {
00207   merge( that, math::coordinate_2d<int>(0, 0) );
00208 } // image::merge()
00209 
00210 /*----------------------------------------------------------------------------*/
00216 void claw::graphic::image::merge
00217 ( const image& that, const math::coordinate_2d<int>& pos )
00218 {
00219   math::rectangle<int> my_box(0, 0, width(), height());
00220   math::rectangle<int> his_box(pos.x, pos.y, that.width(), that.height());
00221 
00222   if ( my_box.intersects( his_box ) )
00223     {
00224       math::rectangle<int> intersection;
00225       unsigned int that_y = pos.y < 0 ? -pos.y : 0;
00226       unsigned int that_x = pos.x < 0 ? -pos.x : 0;
00227       const double max_comp
00228         ( std::numeric_limits<rgba_pixel::component_type>::max() );
00229 
00230       intersection = my_box.intersection( his_box );
00231 
00232       for (int y=0; y!=intersection.height; ++y)
00233         {
00234           scanline::const_iterator first = that[y + that_y].begin() + that_x;
00235           scanline::const_iterator last = first + intersection.width;
00236           scanline::iterator dest = (*this)[y + intersection.position.y].begin()
00237             + intersection.position.x;
00238 
00239           for( ; first!=last; ++first, ++dest )
00240             {
00241               const double src_alpha(first->components.alpha);
00242               const double dest_alpha(dest->components.alpha);
00243 
00244               double red =
00245                 (double)first->components.red
00246                 + dest_alpha * (double)dest->components.red / max_comp;
00247               double green =
00248                 (double)first->components.green
00249                 + dest_alpha * (double)dest->components.green / max_comp;
00250               double blue =
00251                 (double)first->components.blue
00252                   + dest_alpha * (double)dest->components.blue / max_comp;
00253               double alpha = src_alpha + (max_comp - dest_alpha) / max_comp;
00254 
00255               dest->components.red = std::min(red, max_comp);
00256               dest->components.green = std::min(green, max_comp);
00257               dest->components.blue = std::min(blue, max_comp);
00258               dest->components.alpha = std::min(alpha, max_comp);
00259             }
00260         }
00261     }
00262 } // image::merge()
00263 
00264 /*----------------------------------------------------------------------------*/
00270 void claw::graphic::image::partial_copy
00271 (const image& that, const math::coordinate_2d<int>& pos )
00272 {
00273   math::rectangle<int> my_box(0, 0, width(), height());
00274   math::rectangle<int> his_box(pos.x, pos.y, that.width(), that.height());
00275 
00276   if ( my_box.intersects( his_box ) )
00277     {
00278       math::rectangle<int> intersection;
00279       unsigned int that_y = pos.y < 0 ? -pos.y : 0;
00280       unsigned int that_x = pos.x < 0 ? -pos.x : 0;
00281 
00282       intersection = my_box.intersection( his_box );
00283 
00284       for (int y=0; y!=intersection.height; ++y)
00285         {
00286           scanline::const_iterator first = that[y + that_y].begin() + that_x;
00287           scanline::const_iterator last = first + intersection.width;
00288           scanline::iterator dest = (*this)[y + intersection.position.y].begin()
00289             + intersection.position.x;
00290 
00291           std::copy( first, last, dest );
00292         }
00293     }
00294 } // image::partial_copy()
00295 
00296 /*----------------------------------------------------------------------------*/
00300 void claw::graphic::image::flip()
00301 {
00302   for (unsigned int y=0; y!=height()/2; ++y)
00303     std::swap( m_data[y], m_data[height()-y-1] );
00304 } // image::flip()
00305 
00306 /*----------------------------------------------------------------------------*/
00312 void claw::graphic::image::fill
00313 ( const math::rectangle<int> r, const pixel_type& c )
00314 {
00315   math::rectangle<int> my_box(0, 0, width(), height());
00316 
00317   if ( my_box.intersects( r ) )
00318     {
00319       const math::rectangle<int> intersection( my_box.intersection( r ) );
00320       const double max_comp
00321         ( std::numeric_limits<rgba_pixel::component_type>::max() );
00322 
00323       for (int y=0; y!=intersection.height; ++y)
00324         {
00325           scanline::iterator first =
00326             (*this)[intersection.position.y + y].begin()
00327             + intersection.position.x;
00328           const scanline::iterator last = first + intersection.width;
00329 
00330           for( ; first!=last; ++first )
00331             {
00332               const double src_alpha(c.components.alpha);
00333 
00334               double red =
00335                 (double)first->components.red
00336                 + src_alpha * (double)c.components.red / max_comp;
00337               double green =
00338                 (double)first->components.green
00339                   + src_alpha * (double)c.components.green / max_comp;
00340               double blue =
00341                 (double)first->components.blue
00342                 + src_alpha * (double)c.components.blue / max_comp;
00343               double alpha = (double)first->components.alpha
00344                 + (max_comp - src_alpha) / max_comp;
00345 
00346               first->components.red = std::min(red, max_comp);
00347               first->components.green = std::min(green, max_comp);
00348               first->components.blue = std::min(blue, max_comp);
00349               first->components.alpha = std::min(alpha, max_comp);
00350             }
00351         }
00352     }
00353 } // image::fill()
00354 
00355 /*----------------------------------------------------------------------------*/
00362 void claw::graphic::image::set_size( unsigned int w, unsigned int h )
00363 {
00364   if (w == 0)
00365     m_data.clear();
00366   else
00367     {
00368       m_data.resize(h);
00369   
00370       for (unsigned int y=0; y!=height(); ++y)
00371         m_data[y].resize(w);
00372     }
00373 } // image::set_size()
00374 
00375 /*----------------------------------------------------------------------------*/
00380 void claw::graphic::image::load( std::istream& f )
00381 {
00382   bool ok = false;
00383 
00384 #ifdef CLAW_JPEG_SUPPORT
00385   if (!ok)
00386     try { jpeg::reader( *this, f ); ok = true; }
00387     catch( ... ) { }
00388 #endif // CLAW_JPEG_SUPPORT
00389 
00390 #ifdef CLAW_PNG_SUPPORT
00391   if (!ok)
00392     try { png::reader( *this, f ); ok = true; }
00393     catch( ... ) { }
00394 #endif // CLAW_PNG_SUPPORT
00395 
00396   if (!ok)
00397     try { bitmap::reader( *this, f ); ok = true; }
00398     catch( ... ) { }
00399 
00400   if (!ok)
00401     try { targa::reader( *this, f ); ok = true; }
00402     catch( ... ) { }
00403 
00404   if (!ok)
00405     try { gif::reader( *this, f ); ok = true; }
00406     catch( ... ) { }
00407 
00408   if (!ok)
00409     try { pcx::reader( *this, f ); ok = true; }
00410     catch( ... ) { }
00411 
00412   if (!ok)
00413     try { xbm::reader( *this, f ); ok = true; }
00414     catch( ... ) { }
00415 
00416   if (!ok)
00417     throw claw::bad_format( "image::load: file format isn't supported." );
00418 } // image::load()
00419 
00420 
00421 
00422 
00423 /*----------------------------------------------------------------------------*/
00429 void std::swap( claw::graphic::image& a, claw::graphic::image& b )
00430 {
00431   a.swap(b);
00432 } // swap()