00001
00002
00003
00004 #include <iostream>
00005 #include "image.h"
00006
00008 image::image_t::image_t( unsigned int width, unsigned int height, format fmat,
00009 unsigned int depth ):
00010 m_width( width ),
00011 m_height( height ),
00012 m_format( fmat ),
00013 m_depth( depth ),
00014 m_seek_pos( 0 )
00015 {
00016
00017 if( (depth != BYTE) ) {
00018 std::cerr << "image::image( ): " << depth
00019
00020 << " is not a valid depth (BYTE)" << std::endl;
00021 abort( );
00022 }
00023
00024
00025 m_pixel_size = m_format * m_depth / 8;
00026
00027
00028 m_row_size = m_pixel_size * m_width;
00029
00030
00031 m_image_size = m_width * m_height * m_pixel_size;
00032
00033
00034 m_pixels = new unsigned char[ m_image_size ];
00035
00036
00037 m_seek_ptr = m_pixels;
00038 }
00039
00041 image::image_t::image_t( unsigned int width, unsigned int height, format fmat,
00042 unsigned int depth, const void *pixels ):
00043 m_width( width ),
00044 m_height( height ),
00045 m_format( fmat ),
00046 m_depth( depth ),
00047 m_seek_pos( 0 )
00048 {
00049
00050 if( (depth != BYTE) ) {
00051 std::cerr << "image::image( ): " << depth
00052
00053 << " is not a valid depth (BYTE)" << std::endl;
00054 abort( );
00055 }
00056
00057
00058 m_pixel_size = m_format * m_depth / 8;
00059
00060
00061 m_row_size = m_pixel_size * m_width;
00062
00063
00064 m_image_size = m_width * m_height * m_pixel_size;
00065
00066
00067 m_pixels = new unsigned char[ m_image_size ];
00068
00069
00070 memcpy( m_pixels, pixels, m_image_size );
00071
00072
00073 m_seek_ptr = m_pixels;
00074 }
00075
00077 image::image_t::~image_t( void )
00078 {
00079 delete[] m_pixels;
00080 }
00081
00083 bool
00084 image::image_t::seek( unsigned int x, unsigned int y )
00085 {
00086
00087 assert( y < m_height );
00088 assert( x < m_width );
00089
00090
00091 m_seek_pos = y * m_row_size + x * m_pixel_size;
00092 m_seek_ptr = m_pixels;
00093
00094 if( m_seek_pos < m_image_size ) {
00095 m_seek_ptr += m_seek_pos;
00096 return true;
00097 }
00098
00099
00100 return false;
00101 }
00102
00104 bool
00105 image::image_t::read( unsigned char& gray )
00106 {
00107 if( !(m_seek_pos < m_image_size) ) {
00108
00109 return false;
00110 }
00111
00112
00113 unsigned char *ptr = m_seek_ptr;
00114 m_seek_pos += m_pixel_size;
00115 m_seek_ptr += m_pixel_size;
00116
00117 float sum = 0.0;
00118
00119
00120 if( m_format == RGB ) {
00121
00122 sum += (static_cast<float>( *(ptr++) ) / 255.0) * 0.299;
00123 sum += (static_cast<float>( *(ptr++) ) / 255.0) * 0.587;
00124 sum += (static_cast<float>( *(ptr++) ) / 255.0) * 0.114;
00125 gray = static_cast<unsigned char>( sum * 255.0 );
00126 return true;
00127 } else if( m_format == RGBA ) {
00128
00129 sum += (static_cast<float>( *(ptr++) ) / 255.0) * 0.299;
00130 sum += (static_cast<float>( *(ptr++) ) / 255.0) * 0.587;
00131 sum += (static_cast<float>( *(ptr++) ) / 255.0) * 0.114;
00132 gray = static_cast<unsigned char>( sum * static_cast<float>( *ptr ) );
00133 return true;
00134 } else {
00135
00136 gray = *ptr;
00137 return true;
00138 }
00139
00140 return false;
00141 }
00142
00144 bool
00145 image::image_t::read( unsigned char &r, unsigned char &g, unsigned char &b )
00146 {
00147 if( !(m_seek_pos < m_image_size) ) {
00148
00149 return false;
00150 }
00151
00152
00153 unsigned char *ptr = m_seek_ptr;
00154 m_seek_pos += m_pixel_size;
00155 m_seek_ptr += m_pixel_size;
00156
00157
00158 if( (m_format == RGB) || (m_format == RGBA) ) {
00159
00160 r = *(ptr++);
00161 g = *(ptr++);
00162 b = *ptr;
00163 return true;
00164 } else {
00165
00166 r = *ptr;
00167 g = *ptr;
00168 b = *ptr;
00169 return true;
00170 }
00171
00172 return false;
00173 }
00174
00176 bool
00177 image::image_t::read( unsigned char &r, unsigned char &g, unsigned char &b,
00178 unsigned char &a )
00179 {
00180 if( !(m_seek_pos < m_image_size) ) {
00181
00182 return false;
00183 }
00184
00185
00186 unsigned char *ptr = m_seek_ptr;
00187 m_seek_pos += m_pixel_size;
00188 m_seek_ptr += m_pixel_size;
00189
00190
00191 if( m_format == RGB ) {
00192
00193 r = *(ptr++);
00194 g = *(ptr++);
00195 b = *(ptr++);
00196 a = 255;
00197 return true;
00198 } else if( m_format == RGBA ) {
00199
00200 r = *(ptr++);
00201 g = *(ptr++);
00202 b = *(ptr++);
00203 a = *ptr;
00204 return true;
00205 } else {
00206
00207 r = 255;
00208 g = 255;
00209 b = 255;
00210 a = *ptr;
00211 return true;
00212 }
00213
00214 return false;
00215 }
00216
00218 bool
00219 image::image_t::write( unsigned char gray )
00220 {
00221 if( !(m_seek_pos < m_image_size) ) {
00222
00223 return false;
00224 }
00225
00226
00227 unsigned char *ptr = m_seek_ptr;
00228 m_seek_pos += m_pixel_size;
00229 m_seek_ptr += m_pixel_size;
00230
00231 float sum = 0.0;
00232
00233
00234 if( m_format == RGB ) {
00235
00236 *(ptr++) = gray;
00237 *(ptr++) = gray;
00238 *ptr = gray;
00239 return true;
00240 } else if( m_format == RGBA ) {
00241
00242 *(ptr++) = 255;
00243 *(ptr++) = 255;
00244 *(ptr++) = 255;
00245 *ptr = gray;
00246 return true;
00247 } else {
00248
00249 *ptr = gray;
00250 return true;
00251 }
00252
00253 return false;
00254 }
00255
00257 bool
00258 image::image_t::write( unsigned char r, unsigned char g, unsigned char b )
00259 {
00260 if( !(m_seek_pos < m_image_size) ) {
00261
00262 return false;
00263 }
00264
00265
00266 unsigned char *ptr = m_seek_ptr;
00267 m_seek_pos += m_pixel_size;
00268 m_seek_ptr += m_pixel_size;
00269
00270
00271 if( (m_format == RGB) || (m_format == RGBA) ) {
00272
00273 *(ptr++) = r;
00274 *(ptr++) = g;
00275 *ptr = b;
00276 return true;
00277 } else {
00278
00279 float sum = 0.0;
00280 sum += (static_cast<float>( r ) / 255.0) * 0.299;
00281 sum += (static_cast<float>( g ) / 255.0) * 0.587;
00282 sum += (static_cast<float>( b ) / 255.0) * 0.114;
00283 *ptr = static_cast<unsigned char>( sum * 255.0 );
00284 return true;
00285 }
00286
00287 return false;
00288 }
00289
00291 bool
00292 image::image_t::write( unsigned char r, unsigned char g, unsigned char b,
00293 unsigned char a )
00294 {
00295 if( !(m_seek_pos < m_image_size) ) {
00296
00297 return false;
00298 }
00299
00300
00301 unsigned char *ptr = m_seek_ptr;
00302 m_seek_pos += m_pixel_size;
00303 m_seek_ptr += m_pixel_size;
00304
00305
00306 if( m_format == RGB ) {
00307
00308 *(ptr++) = r;
00309 *(ptr++) = g;
00310 *ptr = b;
00311 return true;
00312 } else if( m_format == RGBA ) {
00313
00314 *(ptr++) = r;
00315 *(ptr++) = g;
00316 *(ptr++) = b;
00317 *ptr = a;
00318 return true;
00319 } else {
00320
00321 float sum = 0.0;
00322 sum += (static_cast<float>( r ) / 255.0) * 0.299;
00323 sum += (static_cast<float>( g ) / 255.0) * 0.587;
00324 sum += (static_cast<float>( b ) / 255.0) * 0.114;
00325 *ptr = static_cast<unsigned char>( sum * static_cast<float>( a ) );
00326 return true;
00327 }
00328
00329 return false;
00330 }
00331
00333 bool
00334 image::image_t::get_pixel( unsigned char &r, unsigned char &g, unsigned char &b,
00335 unsigned int x, unsigned int y ) const
00336 {
00337
00338 if( !(y < m_height) ) return false;
00339 if( !(x < m_width) ) return false;
00340
00341
00342 unsigned char *ptr = m_pixels +
00343 (y * m_row_size) + (x * m_pixel_size);
00344
00345
00346 if( (m_format == RGB) || (m_format == RGBA) ) {
00347
00348 r = *(ptr++);
00349 g = *(ptr++);
00350 b = *ptr;
00351 return true;
00352 } else {
00353
00354 r = *ptr;
00355 g = *ptr;
00356 b = *ptr;
00357 return true;
00358 }
00359
00360 return false;
00361 }
00362
00364 bool
00365 image::image_t::get_pixel( unsigned char &r, unsigned char &g, unsigned char &b,
00366 unsigned char &a, unsigned int x, unsigned int y ) const
00367 {
00368
00369 if( !(y < m_height) ) return false;
00370 if( !(x < m_width) ) return false;
00371
00372
00373 unsigned char *ptr = m_pixels +
00374 (y * m_row_size) + (x * m_pixel_size);
00375
00376
00377 if( m_format == RGB ) {
00378
00379 r = *(ptr++);
00380 g = *(ptr++);
00381 b = *(ptr++);
00382 a = 255;
00383 return true;
00384 } else if( m_format == RGBA ) {
00385
00386 r = *(ptr++);
00387 g = *(ptr++);
00388 b = *(ptr++);
00389 a = *ptr;
00390 return true;
00391 } else {
00392
00393 r = 255;
00394 g = 255;
00395 b = 255;
00396 a = *ptr;
00397 return true;
00398 }
00399
00400 return false;
00401 }
00402
00404 bool
00405 image::image_t::set_pixel( unsigned char r, unsigned char g, unsigned char b,
00406 unsigned int x, unsigned int y )
00407 {
00408
00409 if( !(y < m_height) ) return false;
00410 if( !(x < m_width) ) return false;
00411
00412
00413 unsigned char *ptr = m_pixels +
00414 (y * m_row_size) + (x * m_pixel_size);
00415
00416
00417 if( (m_format == RGB) || (m_format == RGBA) ) {
00418
00419 *(ptr++) = r;
00420 *(ptr++) = g;
00421 *ptr = b;
00422 return true;
00423 } else {
00424
00425 float sum = 0.0;
00426 sum += (static_cast<float>( r ) / 255.0) * 0.299;
00427 sum += (static_cast<float>( g ) / 255.0) * 0.587;
00428 sum += (static_cast<float>( b ) / 255.0) * 0.114;
00429 *ptr = static_cast<unsigned char>( sum * 255.0 );
00430 return true;
00431 }
00432
00433 return false;
00434 }
00435
00437 bool
00438 image::image_t::set_pixel( unsigned char r, unsigned char g, unsigned char b,
00439 unsigned char a, unsigned int x, unsigned int y )
00440 {
00441
00442 if( !(y < m_height) ) return false;
00443 if( !(x < m_width) ) return false;
00444
00445
00446 unsigned char *ptr = m_pixels +
00447 (y * m_row_size) + (x * m_pixel_size);
00448
00449
00450 if( m_format == RGB ) {
00451
00452 *(ptr++) = r;
00453 *(ptr++) = g;
00454 *ptr = b;
00455 return true;
00456 } else if( m_format = RGBA ) {
00457
00458 *(ptr++) = r;
00459 *(ptr++) = g;
00460 *(ptr++) = b;
00461 *ptr = a;
00462 return true;
00463 } else {
00464
00465 float sum = 0.0;
00466 sum += (static_cast<float>( r ) / 255.0) * 0.299;
00467 sum += (static_cast<float>( g ) / 255.0) * 0.587;
00468 sum += (static_cast<float>( b ) / 255.0) * 0.114;
00469 *ptr = static_cast<unsigned char>( sum * static_cast<float>( a ) );
00470 return true;
00471 }
00472
00473 return false;
00474 }
00475
00477
00478 bool
00479 image::image_t::blend_pixel( unsigned char r, unsigned char g, unsigned char b,
00480 unsigned char a, unsigned int x, unsigned int y )
00481 {
00482
00483 if( !(y < m_height) ) return false;
00484 if( !(x < m_width) ) return false;
00485
00486
00487 unsigned char *pixel = m_pixels +
00488 (y * m_row_size) + (x * m_pixel_size);
00489
00490 float rd, gd, bd, ad;
00491 rd = ((float)*(pixel))/255.0;
00492 gd = ((float)*(pixel+1))/255.0;
00493 bd = ((float)*(pixel+2))/255.0;
00494
00495 if( m_format == RGBA ) {
00496 ad = ((float)*(pixel+3))/255.0;
00497 }
00498
00499 float rs, gs, bs, as;
00500 rs = ((float)(r))/255.0;
00501 gs = ((float)(g))/255.0;
00502 bs = ((float)(b))/255.0;
00503 as = ((float)(a))/255.0;
00504
00505 *(pixel++) = ((unsigned char)((rs * as + rd * (1.0 - as)) * 255.0));
00506 *(pixel++) = ((unsigned char)((gs * as + gd * (1.0 - as)) * 255.0));
00507 *(pixel++) = ((unsigned char)((bs * as + bd * (1.0 - as)) * 255.0));
00508 if( m_format == RGBA ) {
00509 *(pixel++) = ((unsigned char)((as * as + ad * (1.0 - as)) * 255.0));
00510 }
00511
00512 return true;
00513 }
00514
00515
00517 void
00518 image::image_t::flip_horizontal( void )
00519 {
00520
00521 if( m_depth != BYTE ) return;
00522
00523 unsigned int channels;
00524 if( m_format == RGB ) {
00525 channels = 3;
00526 } else if( m_format == RGBA ) {
00527 channels = 4;
00528 } else if( m_format == GREYSCALE ) {
00529 channels = 1;
00530 } else {
00531 return;
00532 }
00533
00534
00535 unsigned int chan_size = m_depth / 8;
00536
00537 for( unsigned int i = 0; i < m_height / 2; ++i ) {
00538 for( unsigned int j = 0; j < m_width; ++j ) {
00539 for( unsigned int k = 0; k < channels; ++k ) {
00540
00541 std::swap(
00542 m_pixels[ i * m_row_size + j * m_pixel_size + k * chan_size ],
00543 m_pixels[ (m_height - 1 - i) * m_row_size + j * m_pixel_size + k * chan_size ]
00544 );
00545 }
00546 }
00547 }
00548 }
00549
00551
00552 bool
00553 image::image_t::blit( const image_t& img, const recti& region )
00554 {
00555 unsigned char r, g, b, a;
00556 unsigned int writes = 0;
00557 for( unsigned int y = 0; y < img.get_height( ); ++y ) {
00558 for( unsigned int x = 0; x < img.get_width( ); ++x ) {
00559 if( img.get_pixel( r, g, b, a, x, y ) ) {
00560 if( set_pixel( r, g, b, a, region.x + x, region.y + y ) ) {
00561 ++writes;
00562 }
00563 }
00564 }
00565 }
00566 return static_cast<bool>( writes );
00567 }
00568
00570
00571 bool
00572 image::image_t::blend( const image_t& img, const recti& region )
00573 {
00574 unsigned char r, g, b, a;
00575 unsigned int writes = 0;
00576 for( unsigned int y = 0; y < img.get_height( ); ++y ) {
00577 for( unsigned int x = 0; x < img.get_width( ); ++x ) {
00578 if( img.get_pixel( r, g, b, a, x, y ) ) {
00579 if( blend_pixel( r, g, b, a, region.x + x, region.y + y ) ) {
00580 ++writes;
00581 }
00582 }
00583 }
00584 }
00585 return static_cast<bool>( writes );
00586 }