Claw
1.7.3
|
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()