TuttleOFX
1
|
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