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