00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00040
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 }
00058
00059
00063 claw::graphic::image::scanline::iterator claw::graphic::image::scanline::end()
00064 {
00065 return super::end();
00066 }
00067
00068
00072 claw::graphic::image::scanline::const_iterator
00073 claw::graphic::image::scanline::begin() const
00074 {
00075 return super::begin();
00076 }
00077
00078
00082 claw::graphic::image::scanline::const_iterator
00083 claw::graphic::image::scanline::end() const
00084 {
00085 return super::end();
00086 }
00087
00088
00092 claw::graphic::image::scanline::size_type
00093 claw::graphic::image::scanline::size() const
00094 {
00095 return super::size();
00096 }
00097
00098
00099
00100
00101
00106 claw::graphic::image::image()
00107 {
00108
00109 }
00110
00111
00116 claw::graphic::image::image( std::istream& f )
00117 {
00118 load(f);
00119 }
00120
00121
00128 claw::graphic::image::image( unsigned int w, unsigned int h )
00129 {
00130 set_size(w, h);
00131 }
00132
00133
00138 void claw::graphic::image::swap( image& that )
00139 {
00140 std::swap(m_data, that.m_data);
00141 }
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 }
00154
00155
00159 unsigned int claw::graphic::image::height() const
00160 {
00161 return m_data.size();
00162 }
00163
00164
00168 claw::graphic::image::iterator claw::graphic::image::begin()
00169 {
00170 return iterator(*this);
00171 }
00172
00173
00177 claw::graphic::image::iterator claw::graphic::image::end()
00178 {
00179 return iterator(*this, width(), height()-1);
00180 }
00181
00182
00186 claw::graphic::image::const_iterator claw::graphic::image::begin() const
00187 {
00188 return const_iterator(*this);
00189 }
00190
00191
00195 claw::graphic::image::const_iterator claw::graphic::image::end() const
00196 {
00197 return const_iterator(*this, width(), height());
00198 }
00199
00200
00205 void claw::graphic::image::merge( const image& that )
00206 {
00207 merge( that, math::coordinate_2d<int>(0, 0) );
00208 }
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 }
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 }
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 }
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 }
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 }
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 }
00419
00420
00421
00422
00423
00429 void std::swap( claw::graphic::image& a, claw::graphic::image& b )
00430 {
00431 a.swap(b);
00432 }