TuttleOFX  1
ViewerAlgorithm.hpp
Go to the documentation of this file.
00001 #ifndef _TUTTLE_PLUGIN_VIEWER_ALGORITHM_HPP_
00002 #define _TUTTLE_PLUGIN_VIEWER_ALGORITHM_HPP_
00003 
00004 #include <terry/channel.hpp>
00005 
00006 #include <tuttle/plugin/opengl/gl.h>
00007 #ifdef __APPLE__
00008 #   include <GLUT/glut.h>
00009 #else
00010 #   include <GL/glut.h>
00011 #   include <GL/freeglut.h>
00012 #endif
00013 
00014 #include <string.h>
00015 #include <stdlib.h>
00016 #include <stdio.h>
00017 
00018 
00019 #define SPACEBAR 32
00020 
00021 namespace tuttle {
00022 namespace plugin {
00023 namespace viewer {
00024 
00025 char *argv[2] = { (char*)"", NULL };
00026 int   argc    = 1;
00027 
00028 // image properties
00029 struct ImgProperties
00030 {
00031         const char* data;
00032         GLint  internalFormat;
00033         size_t width;
00034         size_t height;
00035         GLenum format;
00036         GLenum type;
00037         size_t component;
00038 };
00039 
00040 ImgProperties img;
00041 
00042 // opengl properties
00043 int windowID;
00044 
00045 // viewing properties
00046 int angle_cam = 60;
00047 
00048 // viewing properties - viewport
00049 int w_out, h_out;
00050 float scale = 1.0;
00051 int xMinViewport, yMinViewport;
00052 
00053 // viewing properties - zoom
00054 float factorZoom = 1.25;
00055 float currentZoom = 1.0;
00056 
00057 // viewing properties - transformations
00058 float x1Quad, x2Quad, y1Quad, y2Quad;
00059 bool flip = false;
00060 bool flop = false;
00061 
00062 // mouse moves properties
00063 int x_mouse_ref, y_mouse_ref;
00064 
00065 // channel properties
00066 bool showRedChannel = false;
00067 bool showGreenChannel = false;
00068 bool showBlueChannel = false;
00069 bool showAlphaChannel = false;
00070 
00071 void reshape(int width, int height)
00072 {
00073         float w, h, xPos, yPos;
00074 
00075         if( (float)w_out/h_out > (float)width/height )
00076         {
00077                 w = width;
00078                 h = 1.0f * h_out / w_out * (float)width;
00079                 xPos = 0.0;
00080                 yPos = 0.5f * (height - h);
00081         }
00082         else
00083         {
00084                 w = 1.0f * w_out / h_out * (float)height;
00085                 h = height;
00086                 xPos = 0.5f * (width - w);
00087                 yPos = 0.0;
00088         }
00089 
00090         xMinViewport = xPos;
00091         yMinViewport = yPos;
00092 
00093         scale = w/w_out;
00094         
00095         glViewport((GLsizei)xPos, (GLsizei)yPos, (GLsizei)w, (GLsizei)h);
00096         glutReshapeWindow(width, height);
00097 }
00098 
00099 void loadNewTexture( const ImgProperties& properties )
00100 {
00101         // loading texture
00102         glTexImage2D( GL_TEXTURE_2D, 0, properties.internalFormat, properties.width, properties.height, 0, properties.format, properties.type, properties.data );
00103         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00104         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00105 
00106         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00107         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00108 
00109         glEnable(GL_TEXTURE_2D);
00110 }
00111 
00112 void loadNewTexture( const char* data, GLint internalFormat, size_t width, size_t height, GLenum format, GLenum type )
00113 {
00114         img.data = data;
00115         img.internalFormat = internalFormat;
00116         img.width = width;
00117         img.height = height;
00118         img.format = format;
00119         img.type = type;
00120 
00121         switch( img.format )
00122         {
00123                 case GL_LUMINANCE : img.component = 1; break;
00124                 case GL_RGB       : img.component = 3; break;
00125                 case GL_RGBA      : img.component = 4; break;
00126         }
00127 
00128         loadNewTexture( img );
00129 }
00130 
00131 
00132 void reloadTexture( )
00133 {
00134         loadNewTexture( img );
00135 }
00136 
00137 void loadAlphaTexture( )
00138 {
00139         // @TODO find howto pass alpha at luminance
00140         glTexImage2D( GL_TEXTURE_2D, 0, img.internalFormat, img.width, img.height, 0, img.format, img.type, img.data );
00141         
00142         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00143         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00144         
00145         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00146         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00147         
00148         glEnable(GL_TEXTURE_2D);
00149 }
00150 
00151 void setTransfert( float red, float green, float blue, float alpha=1.f )
00152 {
00153         switch( img.format )
00154         {
00155                 case GL_LUMINANCE :
00156                         return;
00157                 case GL_RGB :
00158                         glPixelTransferf( GL_RED_SCALE,   red );
00159                         glPixelTransferf( GL_GREEN_SCALE, green );
00160                         glPixelTransferf( GL_BLUE_SCALE,  blue );
00161                         break;
00162                 case GL_RGBA :
00163                         glPixelTransferf( GL_RED_SCALE,   red );
00164                         glPixelTransferf( GL_GREEN_SCALE, green );
00165                         glPixelTransferf( GL_BLUE_SCALE,  blue );
00166                         glPixelTransferf( GL_ALPHA_SCALE, alpha );
00167                         break;
00168         }
00169 }
00170 
00171 void displayChannelTexture( bool& channel, const float red, const float green, const float blue )
00172 {
00173         ImgProperties p = img;
00174         if( ! channel )
00175         {
00176                 setTransfert( red, green, blue );
00177                 showRedChannel   = false;
00178                 showGreenChannel = false;
00179                 showBlueChannel  = false;
00180                 showAlphaChannel = false;
00181                 channel = true;
00182         }
00183         else
00184         {
00185                 setTransfert( 1.f, 1.f, 1.f );
00186                 channel = false;
00187         }
00188         loadNewTexture( p );
00189 
00190         glutPostRedisplay();
00191 }
00192 
00193 void showRedChannelTexture( )
00194 {
00195         displayChannelTexture( showRedChannel, 1.f, 0.f, 0.f );
00196 }
00197 
00198 void showGreenChannelTexture( )
00199 {
00200         displayChannelTexture( showGreenChannel, 0.f, 1.f, 0.f );
00201 }
00202 
00203 void showBlueChannelTexture( )
00204 {
00205         displayChannelTexture( showBlueChannel, 0.f, 0.f, 1.f );
00206 }
00207 
00208 void showAlphaChannelTexture( )
00209 {
00210         if( ! showAlphaChannel )
00211         {
00212                 loadAlphaTexture( );
00213                 showRedChannel   = false;
00214                 showGreenChannel = false;
00215                 showBlueChannel  = false;
00216                 showAlphaChannel = true;
00217         }
00218         else
00219         {
00220                 setTransfert( 1.f, 1.f, 1.f, 1.f );
00221                 showAlphaChannel = false;
00222         }
00223         glutPostRedisplay ();
00224 }
00225 
00226 void display()
00227 {
00228         if( glutGetWindow() == 0 ) return;
00229         glClearColor(0.0f, 0.0f, 0.0f, 0.0f );
00230         glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
00231         
00232         glBegin (GL_QUADS);
00233         
00234         float x1 = x1Quad;
00235         float x2 = x2Quad;
00236         
00237         float y1 = y1Quad;
00238         float y2 = y2Quad;
00239         
00240         if( flip )
00241         {
00242                 y1 = -y1;
00243                 y2 = -y2;
00244         }
00245         if( flop )
00246         {
00247                 x1 = -x1;
00248                 x2 = -x2;
00249         }
00250         
00251         glTexCoord2f( 0 , 0 );
00252         glVertex2f  ( x1, y1 );
00253         
00254         glTexCoord2f( 0, 1 );
00255         glVertex2f  ( x1, y2 );
00256         
00257         glTexCoord2f( 1, 1 );
00258         glVertex2f  ( x2, y2 );
00259         
00260         glTexCoord2f( 1, 0 );
00261         glVertex2f  ( x2, y1 );
00262         
00263         glEnd();
00264         glutSwapBuffers();
00265 }
00266 
00267 void idle()
00268 {
00269 }
00270 
00271 void displayInformations()
00272 {
00273         std::string textureType;
00274         switch( img.format )
00275         {
00276                 case GL_LUMINANCE : textureType = "Gray "; break;
00277                 case GL_RGB       : textureType = "RGB  "; break;
00278                 case GL_RGBA      : textureType = "RGBA "; break;
00279         }
00280         switch( img.type )
00281         {
00282                 case GL_UNSIGNED_BYTE  : textureType += "8 bits"; break;
00283                 case GL_UNSIGNED_SHORT : textureType += "16 bits"; break;
00284                 case GL_FLOAT          : textureType += "32 float"; break;
00285         }
00286         std::cout << textureType << " " << w_out << "x" << h_out << std::endl;
00287 }
00288 
00289 void displayHelp()
00290 {
00291         std::cout << kViewerHelp << std::endl;
00292 }
00293 
00294 void move(float x, float y)
00295 {
00296         x1Quad += x;
00297         x2Quad += x;
00298         y1Quad += y;
00299         y2Quad += y;
00300 }
00301 
00302 void zoom(float factor)
00303 {
00304         x1Quad *= factor;
00305         x2Quad *= factor;
00306         y1Quad *= factor;
00307         y2Quad *= factor;
00308 }    
00309 
00310 void mapToImage(int x, int y, int &iX, int &iY)
00311 {
00312         int mapX, mapY;
00313         float mx, my;
00314 
00315         mapX = (x - xMinViewport)/scale;
00316         mapY = (y - yMinViewport)/scale;
00317 
00318         if( !flip )
00319         {
00320                 mapY = img.height - mapY;
00321         }
00322         
00323         if( flop )
00324         {
00325                 mapX = img.width - mapX;
00326         }
00327 
00328         mx = (float)mapX / (float)img.width * 2.0 - 1.0;
00329         iX = ((x1Quad - mx) / (currentZoom * 2.0) * (float)img.width * -1.0) + 0.5;
00330 
00331         my = (float)mapY / (float)img.height * 2.0 - 1.0;
00332         iY = ((y1Quad - my) / (currentZoom * 2.0) * (float)img.height * -1.0) + 0.5;    
00333 }
00334 
00335 void keyboard(unsigned char k, int x, int y)
00336 {
00337         bool shift= false;
00338         if( glutGetModifiers() == GLUT_ACTIVE_SHIFT )
00339         {
00340                 shift = true;
00341         }
00342         
00343         switch( k )
00344         {
00345                 case '\r':
00346                         glutDestroyWindow(windowID);
00347                         break;
00348                 case 27: // ESCAPE key
00349                         glutDestroyWindow(windowID);
00350                         break;
00351                 case 'i':
00352                         displayInformations();
00353                         break;
00354                 case 'z':
00355                         glutReshapeWindow( w_out, h_out );
00356                         currentZoom = 1.0;
00357                         x1Quad = -1.0;
00358                         x2Quad = 1.0;
00359                         y1Quad = -1.0;
00360                         y2Quad = 1.0;
00361                         glutPostRedisplay();
00362                         break;
00363                 case 'h':
00364                         displayHelp();
00365                         break;
00366                 case SPACEBAR:
00367                         glutDestroyWindow(windowID);
00368                         break;
00369                         
00370                 case 'r':
00371                         showRedChannelTexture( ); 
00372                         break;
00373                 case 'g':
00374                         showGreenChannelTexture( ); 
00375                         break;
00376                 case 'b':
00377                         showBlueChannelTexture( ); 
00378                         break;
00379                 case 'a':
00380                         showAlphaChannelTexture();
00381                         break;
00382                         
00383                 case 'H':
00384                         if( shift )
00385                         {
00386                                 flop = !flop;
00387                                 glutPostRedisplay();
00388                         }
00389                         break;
00390                 case 'V':
00391                         if( shift )
00392                         {
00393                                 flip = !flip;
00394                                 glutPostRedisplay();
00395                         }
00396                         break;
00397 
00398         }
00399 }
00400 
00401 void specialKeyboard( int k, int x, int y)
00402 {       
00403         switch (k)
00404         {
00405                 case GLUT_KEY_UP:
00406                         // cursor move
00407                         break;
00408                 case GLUT_KEY_DOWN:
00409                         // cursor move
00410                         break;
00411                 case GLUT_KEY_LEFT:
00412                         // cursor move
00413                         break;
00414                 case GLUT_KEY_RIGHT:
00415                         // cursor move
00416                         break;
00417                 case GLUT_KEY_F1:
00418                         displayHelp();
00419                         break;
00420         }               
00421 }
00422 
00423 void mouse ( int button, int state, int x, int y )
00424 {
00425         using namespace boost::gil;
00426         if( state == 0 && button == 0 )
00427         {
00428                 int iX, iY;
00429 
00430                 mapToImage(x, y, iX, iY);
00431                 
00432                 if( iX < 0 || iY < 0 || iX >= (int)img.width || iY >= (int)img.height )
00433                         return;
00434                 
00435                 std::cout << "at " << std::setw(4) << iX << "," << std::setw(4) << (int)img.height - iY << ": ";
00436 
00437                 for( size_t i = 0; i < img.component; i++ )
00438                 {
00439                         size_t idx = ( iX + iY * img.width ) * img.component + i;
00440                         switch( img.type )
00441                         {
00442                                 case GL_UNSIGNED_BYTE:
00443                                 {
00444                                         const unsigned char* d = (const unsigned char*) img.data;
00445                                         std::cout << std::setw(5) << (unsigned int) d[idx] ;
00446                                         break;
00447                                 }
00448                                 case GL_UNSIGNED_SHORT:
00449                                 {
00450                                         const unsigned short* d = (const unsigned short*) img.data;
00451                                         std::cout << std::setw(7) << d[idx] ;
00452                                         break;
00453                                 }
00454                                 case GL_FLOAT:
00455                                 {
00456                                         const float* d = (const float*) img.data;
00457                                         std::cout << std::setw(10) << d[idx] ;
00458                                         break;
00459                                 }
00460                         }
00461                 }
00462                 std::cout << std::endl;
00463         }
00464         if( state == 0 && ( button == 3 || button == 4 ) )
00465         {
00466                 int iX, iY, iX2, iY2;
00467 
00468                 mapToImage(x, y, iX, iY);
00469 
00470                 if(button == 3)
00471                 {
00472                         currentZoom *= factorZoom;
00473                         zoom(factorZoom);
00474                 }
00475                 else
00476                 {
00477                         currentZoom /= factorZoom;
00478                         zoom(1.0/factorZoom);
00479                 }
00480 
00481                 mapToImage(x, y, iX2, iY2);
00482                 
00483                 move((currentZoom / img.width * 2) * (iX2 - iX),
00484                      (currentZoom / img.height * 2) * (iY2 - iY));
00485         
00486                 glutPostRedisplay ();
00487         }
00488 
00489         x_mouse_ref = x;
00490         y_mouse_ref = y;
00491 }
00492 
00493 void motion ( int x, int y )
00494 {
00495         float x_diff, y_diff;
00496 
00497         x_diff = (x - x_mouse_ref) / currentZoom;
00498         y_diff = (y_mouse_ref - y) / currentZoom;
00499 
00500         
00501         if( flip )
00502         {
00503                 y_diff *= -1.0;
00504         }
00505         
00506         if( flop )
00507         {
00508                 x_diff *= -1.0;
00509         }
00510 
00511         move(currentZoom / img.width * 2 * x_diff,
00512              currentZoom / img.height * 2 * y_diff);
00513                         
00514         x_mouse_ref = x;
00515         y_mouse_ref = y;
00516 
00517         glutPostRedisplay ();
00518 }
00519 
00520 void openGLWindow( const size_t& width, const size_t& height )
00521 {
00522         glutInit( &argc, argv );
00523         glutInitDisplayMode ( GLUT_DOUBLE | GLUT_RGB | GLUT_RGBA | GLUT_MULTISAMPLE );
00524         glutInitWindowSize ( width, height );
00525         glutInitWindowPosition (0,0);
00526 #ifdef GLUT_ACTION_ON_WINDOW_CLOSE
00527         glutSetOption( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION );
00528 #endif
00529         
00530         windowID = glutCreateWindow("TuttleOFX Viewer");
00531         glClearColor(0.0f, 0.0f, 0.0f, 0.0f );
00532         glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
00533         
00534         w_out = width;
00535         h_out = height;
00536 
00537         x1Quad = -1.0;
00538         x2Quad = 1.0;
00539         y1Quad = -1.0;
00540         y2Quad = 1.0;
00541         
00542         glutDisplayFunc (display);
00543         
00544         glutKeyboardFunc( keyboard );
00545         glutSpecialFunc ( specialKeyboard );
00546         glutMouseFunc   ( mouse );
00547         glutMotionFunc  ( motion );
00548         
00549         glutReshapeFunc(reshape);
00550 }
00551 
00552 
00553 
00554 }
00555 }
00556 }
00557 
00558 #endif