Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

image.cpp

00001 //FILE:         image.cpp
00002 //AUTHOR:       Nathan Cournia <nathan@cournia.com>
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         //make sure the depth is sane
00017         if( (depth != BYTE) ) { //XXX || (depth != WORD) || (depth != DWORD) ) {
00018                 std::cerr << "image::image( ): " << depth 
00019                         //<< " is not a valid depth (BYTE, WORD, DWORD)" << std::endl;
00020                         << " is not a valid depth (BYTE)" << std::endl;
00021                 abort( ); //annoying
00022         }
00023 
00024         //compute pixel size
00025         m_pixel_size = m_format * m_depth / 8;
00026 
00027         //compute row size
00028         m_row_size = m_pixel_size * m_width;
00029 
00030         //compute image size
00031         m_image_size = m_width * m_height * m_pixel_size;
00032 
00033         //allocate memory for image
00034         m_pixels = new unsigned char[ m_image_size ];
00035 
00036         //set seek pointer
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         //make sure the depth is sane
00050         if( (depth != BYTE) ) { //XXX || (depth != WORD) || (depth != DWORD) ) {
00051                 std::cerr << "image::image( ): " << depth 
00052                         //<< " is not a valid depth (BYTE, WORD, DWORD)" << std::endl;
00053                         << " is not a valid depth (BYTE)" << std::endl;
00054                 abort( ); //annoying
00055         }
00056         
00057         //compute pixel size
00058         m_pixel_size = m_format * m_depth / 8;
00059 
00060         //compute row size
00061         m_row_size = m_pixel_size * m_width;
00062 
00063         //compute image size
00064         m_image_size = m_width * m_height * m_pixel_size;
00065         
00066         //allocate memory for image
00067         m_pixels = new unsigned char[ m_image_size ];
00068 
00069         //copy pixel data
00070         memcpy( m_pixels, pixels, m_image_size );
00071 
00072         //set seek pointer
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         //make sure row and col are sane
00087         assert( y < m_height );
00088         assert( x < m_width );
00089         
00090         //set pointers
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         //row and col beyond image boundries
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                 //seek pos is not valid
00109                 return false;
00110         }
00111 
00112         //setup pointers
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         //figure out format
00120         if( m_format == RGB ) {
00121                 //RGB unsigned char
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                 //RGBA unsigned char
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                 //greyscale unsigned char
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                 //seek pos is not valid
00149                 return false;
00150         }
00151 
00152         //setup pointers
00153         unsigned char *ptr = m_seek_ptr;
00154         m_seek_pos += m_pixel_size;
00155         m_seek_ptr += m_pixel_size;
00156         
00157         //figure out format
00158         if( (m_format == RGB) || (m_format == RGBA) ) {
00159                 //RGB(A) unsigned char
00160                 r = *(ptr++);
00161                 g = *(ptr++);
00162                 b = *ptr;
00163                 return true;
00164         } else {
00165                 //greyscale unsigned char
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                 //seek pos is not valid
00182                 return false;
00183         }
00184 
00185         //setup pointers
00186         unsigned char *ptr = m_seek_ptr;
00187         m_seek_pos += m_pixel_size;
00188         m_seek_ptr += m_pixel_size;
00189         
00190         //figure out format
00191         if( m_format == RGB ) {
00192                 //RGB unsigned char
00193                 r = *(ptr++);
00194                 g = *(ptr++);
00195                 b = *(ptr++);
00196                 a = 255;
00197                 return true;
00198         } else if( m_format == RGBA ) {
00199                 //RGB unsigned char
00200                 r = *(ptr++);
00201                 g = *(ptr++);
00202                 b = *(ptr++);
00203                 a = *ptr;
00204                 return true;
00205         } else {
00206                 //greyscale unsigned char
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                 //seek pos is not valid
00223                 return false;
00224         }
00225 
00226         //setup pointers
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         //figure out format
00234         if( m_format == RGB ) {
00235                 //RGB unsigned char
00236                 *(ptr++) = gray;
00237                 *(ptr++) = gray;
00238                 *ptr = gray;
00239                 return true;
00240         } else if( m_format == RGBA ) {
00241                 //RGBA unsigned char
00242                 *(ptr++) = 255;
00243                 *(ptr++) = 255;
00244                 *(ptr++) = 255;
00245                 *ptr = gray;
00246                 return true;
00247         } else {
00248                 //greyscale unsigned char
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                 //seek pos is not valid
00262                 return false;
00263         }
00264 
00265         //setup pointers
00266         unsigned char *ptr = m_seek_ptr;
00267         m_seek_pos += m_pixel_size;
00268         m_seek_ptr += m_pixel_size;
00269 
00270         //figure out format
00271         if( (m_format == RGB) || (m_format == RGBA) ) {
00272                 //RGB(A) unsigned char
00273                 *(ptr++) = r;
00274                 *(ptr++) = g;
00275                 *ptr = b;
00276                 return true;
00277         } else {
00278                 //greyscale unsigned char
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                 //seek pos is not valid
00297                 return false;
00298         }
00299 
00300         //setup pointers
00301         unsigned char *ptr = m_seek_ptr;
00302         m_seek_pos += m_pixel_size;
00303         m_seek_ptr += m_pixel_size;
00304 
00305         //figure out format
00306         if( m_format == RGB ) {
00307                 //RGB unsigned char
00308                 *(ptr++) = r;
00309                 *(ptr++) = g;
00310                 *ptr = b;
00311                 return true;
00312         } else if( m_format == RGBA ) {
00313                 //RGBA unsigned char
00314                 *(ptr++) = r;
00315                 *(ptr++) = g;
00316                 *(ptr++) = b;
00317                 *ptr = a;
00318                 return true;
00319         } else {
00320                 //greyscale unsigned char
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         //make sure y and xumn values are sane
00338         if( !(y < m_height) ) return false;
00339         if( !(x < m_width) ) return false;
00340 
00341         //get pointer to start of pixel
00342         unsigned char *ptr = m_pixels +  
00343                 (y * m_row_size) + (x * m_pixel_size);
00344 
00345         //figure out format
00346         if( (m_format == RGB) || (m_format == RGBA) ) {
00347                 //RGB(A) unsigned char
00348                 r = *(ptr++);
00349                 g = *(ptr++);
00350                 b = *ptr;
00351                 return true;
00352         } else {
00353                 //greyscale unsigned char
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         //make sure y and xumn values are sane
00369         if( !(y < m_height) ) return false;
00370         if( !(x < m_width) ) return false;
00371 
00372         //get pointer to start of pixel
00373         unsigned char *ptr = m_pixels +  
00374                 (y * m_row_size) + (x * m_pixel_size);
00375 
00376         //figure out format
00377         if( m_format == RGB ) {
00378                 //RGB unsigned char
00379                 r = *(ptr++);
00380                 g = *(ptr++);
00381                 b = *(ptr++);
00382                 a = 255;
00383                 return true;
00384         } else if( m_format == RGBA ) {
00385                 //RGBA unsigned char
00386                 r = *(ptr++);
00387                 g = *(ptr++);
00388                 b = *(ptr++);
00389                 a = *ptr;
00390                 return true;
00391         } else {
00392                 //greyscale unsigned char
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         //make sure y and xumn values are sane
00409         if( !(y < m_height) ) return false;
00410         if( !(x < m_width) ) return false;
00411 
00412         //get pointer to start of pixel
00413         unsigned char *ptr = m_pixels +  
00414                 (y * m_row_size) + (x * m_pixel_size);
00415 
00416         //figure out format
00417         if( (m_format == RGB) || (m_format == RGBA) ) {
00418                 //RGB(A) unsigned char
00419                 *(ptr++) = r;
00420                 *(ptr++) = g;
00421                 *ptr = b;
00422                 return true;
00423         } else {
00424                 //greyscale unsigned char
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         //make sure y and x values are sane
00442         if( !(y < m_height) ) return false;
00443         if( !(x < m_width) ) return false;
00444 
00445         //get pointer to start of pixel
00446         unsigned char *ptr = m_pixels +  
00447                 (y * m_row_size) + (x * m_pixel_size);
00448 
00449         //figure out format
00450         if( m_format == RGB ) {
00451                 //RGB unsigned char
00452                 *(ptr++) = r;
00453                 *(ptr++) = g;
00454                 *ptr = b;
00455                 return true;
00456         } else if( m_format = RGBA ) {
00457                 //RGBA unsigned char
00458                 *(ptr++) = r;
00459                 *(ptr++) = g;
00460                 *(ptr++) = b;
00461                 *ptr = a;
00462                 return true;
00463         } else {
00464                 //greyscale unsigned char
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 //TODO add support for greyscale 
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         //make sure y and x values are sane
00483         if( !(y < m_height) ) return false;
00484         if( !(x < m_width) ) return false;
00485 
00486         //get pointer to start of pixel
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         //TODO add support for WORD and DWORD
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         //channel size
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                                 //TODO there should be a cast here based on BYTE, WORD, or DWORD
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 //\todo It shouldn't be too hard to optimize this method.
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 //\todo It shouldn't be too hard to optimize this method.
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 }

Generated on Tue Feb 11 18:49:41 2003 for uber by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002