Claw  1.7.3
code/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()-1);
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
00243                 ( dest->components.alpha * (max_comp - src_alpha) );
00244 
00245               const double red =
00246                 (double)first->components.red * src_alpha
00247                 + (double)dest->components.red * dest_alpha;
00248               const double green =
00249                 (double)first->components.green * src_alpha
00250                 + (double)dest->components.green * dest_alpha;
00251               const double blue =
00252                 (double)first->components.blue * src_alpha
00253                 + (double)dest->components.blue * dest_alpha;
00254               const double alpha = src_alpha + dest_alpha;
00255 
00256               dest->components.red = std::min(red, max_comp);
00257               dest->components.green = std::min(green, max_comp);
00258               dest->components.blue = std::min(blue, max_comp);
00259               dest->components.alpha = std::min(alpha, max_comp);
00260             }
00261         }
00262     }
00263 } // image::merge()
00264 
00265 /*----------------------------------------------------------------------------*/
00271 void claw::graphic::image::partial_copy
00272 (const image& that, const math::coordinate_2d<int>& pos )
00273 {
00274   math::rectangle<int> my_box(0, 0, width(), height());
00275   math::rectangle<int> his_box(pos.x, pos.y, that.width(), that.height());
00276 
00277   if ( my_box.intersects( his_box ) )
00278     {
00279       math::rectangle<int> intersection;
00280       unsigned int that_y = pos.y < 0 ? -pos.y : 0;
00281       unsigned int that_x = pos.x < 0 ? -pos.x : 0;
00282 
00283       intersection = my_box.intersection( his_box );
00284 
00285       for (int y=0; y!=intersection.height; ++y)
00286         {
00287           scanline::const_iterator first = that[y + that_y].begin() + that_x;
00288           scanline::const_iterator last = first + intersection.width;
00289           scanline::iterator dest = (*this)[y + intersection.position.y].begin()
00290             + intersection.position.x;
00291 
00292           std::copy( first, last, dest );
00293         }
00294     }
00295 } // image::partial_copy()
00296 
00297 /*----------------------------------------------------------------------------*/
00301 void claw::graphic::image::flip()
00302 {
00303   for (unsigned int y=0; y!=height()/2; ++y)
00304     std::swap( m_data[y], m_data[height()-y-1] );
00305 } // image::flip()
00306 
00307 /*----------------------------------------------------------------------------*/
00313 void claw::graphic::image::fill
00314 ( const math::rectangle<int> r, const pixel_type& c )
00315 {
00316   math::rectangle<int> my_box(0, 0, width(), height());
00317 
00318   if ( my_box.intersects( r ) )
00319     {
00320       const math::rectangle<int> intersection( my_box.intersection( r ) );
00321       const double max_comp
00322         ( std::numeric_limits<rgba_pixel::component_type>::max() );
00323 
00324       for (int y=0; y!=intersection.height; ++y)
00325         {
00326           scanline::iterator first =
00327             (*this)[intersection.position.y + y].begin()
00328             + intersection.position.x;
00329           const scanline::iterator last = first + intersection.width;
00330 
00331           for( ; first!=last; ++first )
00332             {
00333               const double src_alpha(c.components.alpha);
00334 
00335               double red =
00336                 (double)first->components.red
00337                 + src_alpha * (double)c.components.red / max_comp;
00338               double green =
00339                 (double)first->components.green
00340                   + src_alpha * (double)c.components.green / max_comp;
00341               double blue =
00342                 (double)first->components.blue
00343                 + src_alpha * (double)c.components.blue / max_comp;
00344               double alpha = (double)first->components.alpha
00345                 + (max_comp - src_alpha) / max_comp;
00346 
00347               first->components.red = std::min(red, max_comp);
00348               first->components.green = std::min(green, max_comp);
00349               first->components.blue = std::min(blue, max_comp);
00350               first->components.alpha = std::min(alpha, max_comp);
00351             }
00352         }
00353     }
00354 } // image::fill()
00355 
00356 /*----------------------------------------------------------------------------*/
00363 void claw::graphic::image::set_size( unsigned int w, unsigned int h )
00364 {
00365   if (w == 0)
00366     m_data.clear();
00367   else
00368     {
00369       m_data.resize(h);
00370   
00371       for (unsigned int y=0; y!=height(); ++y)
00372         m_data[y].resize(w);
00373     }
00374 } // image::set_size()
00375 
00376 /*----------------------------------------------------------------------------*/
00381 void claw::graphic::image::load( std::istream& f )
00382 {
00383   bool ok = false;
00384 
00385 #ifdef CLAW_JPEG_SUPPORT
00386   if (!ok)
00387     try { jpeg::reader( *this, f ); ok = true; }
00388     catch( ... ) { }
00389 #endif // CLAW_JPEG_SUPPORT
00390 
00391 #ifdef CLAW_PNG_SUPPORT
00392   if (!ok)
00393     try { png::reader( *this, f ); ok = true; }
00394     catch( ... ) { }
00395 #endif // CLAW_PNG_SUPPORT
00396 
00397   if (!ok)
00398     try { bitmap::reader( *this, f ); ok = true; }
00399     catch( ... ) { }
00400 
00401   if (!ok)
00402     try { targa::reader( *this, f ); ok = true; }
00403     catch( ... ) { }
00404 
00405   if (!ok)
00406     try { gif::reader( *this, f ); ok = true; }
00407     catch( ... ) { }
00408 
00409   if (!ok)
00410     try { pcx::reader( *this, f ); ok = true; }
00411     catch( ... ) { }
00412 
00413   if (!ok)
00414     try { xbm::reader( *this, f ); ok = true; }
00415     catch( ... ) { }
00416 
00417   if (!ok)
00418     throw claw::bad_format( "image::load: file format isn't supported." );
00419 } // image::load()
00420 
00421 
00422 
00423 
00424 /*----------------------------------------------------------------------------*/
00430 void std::swap( claw::graphic::image& a, claw::graphic::image& b )
00431 {
00432   a.swap(b);
00433 } // swap()