00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "GLImageWidget.h"
00010
00011
00012 #include "../../Workers/Puma2/ThermalToColorOperator.h"
00013 #include "../../Workers/Puma2/Y8UV8ToRGB8Operator.h"
00014
00015
00016 #include <sstream>
00017 #include <QMouseEvent>
00018
00019 using namespace puma2;
00020
00021 #define THIS GLImageWidget
00022
00023 const float ZOOM_STEP = sqrt(sqrt(2));
00024
00025 THIS::THIS(QGLWidget *parent) : QGLWidget(parent) {
00026
00027 setCursor(Qt::SizeAllCursor);
00028
00029 m_Zoom=1.0;
00030 m_PosX=0.0;
00031 m_PosY=0.0;
00032
00033 m_ImageWidth=1;
00034 m_ImageHeight=1;
00035 m_ViewportWidth=1;
00036 m_ViewportHeight=1;
00037
00038 setPixelAspectRatio(1.0);
00039
00040 m_TextureId=-1;
00041 m_TextureData=0;
00042 m_TextureResolution=0;
00043 m_TextureFormat=ImageGrabber::GRAY8;
00044 m_TextureByteSize=0;
00045
00046 setMinimumSize(40,40);
00047
00048 }
00049
00050 THIS::~THIS() {
00051 if( m_TextureData ) {
00052
00053 delete[] m_TextureData;
00054 }
00055 if ( int(m_TextureId) != -1 ) {
00056
00057 glDeleteTextures(1,&m_TextureId);
00058 }
00059 }
00060
00061 void THIS::initializeGL() {
00062
00063 glClearColor(1.0, 1.0, 1.0, 0.0);
00064
00065 QSize s = size();
00066 int w = s.width();
00067 int h = s.height();
00068 m_ViewportWidth=w;
00069 m_ViewportHeight=h;
00070 glViewport(0, 0, m_ViewportWidth, m_ViewportHeight);
00071 glDisable( GL_DEPTH_TEST );
00072 }
00073
00074 void THIS::resizeGL(int w, int h)
00075 {
00076 m_ViewportWidth=w;
00077 m_ViewportHeight=h;
00078 glViewport(0, 0, m_ViewportWidth, m_ViewportHeight);
00079 updateGL();
00080 }
00081
00082 void THIS::paintGL() {
00083
00084
00085 if (isVisible())
00086 {
00087 glClear( GL_COLOR_BUFFER_BIT );
00088 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00089
00090 glMatrixMode(GL_PROJECTION);
00091 glLoadIdentity();
00092
00093
00094 glOrtho( -0.5, 0.5, 0.5, -0.5, -1.0, 1.0);
00095 glMatrixMode(GL_MODELVIEW);
00096 glLoadIdentity();
00097
00098
00099 float viewPortAspect=float(m_ViewportWidth) / float(m_ViewportHeight);
00100 float imageAspect=float(m_ImageWidth) / float(m_ImageHeight) * m_PixelAspectRatio;
00101 float scaleX,scaleY;
00102
00103 if (viewPortAspect > imageAspect) {
00104 scaleX=imageAspect/viewPortAspect;
00105 scaleY=1.0;
00106 } else {
00107 scaleX=1.0;
00108 scaleY=viewPortAspect/imageAspect;
00109 }
00110
00111
00112 float relativeImageWidth=scaleX*m_Zoom;
00113 float relativeImageHeight=scaleY*m_Zoom;
00114 float maxX;
00115 float maxY;
00116
00117 if ( relativeImageWidth < 1.0 ) {
00118 maxX=(0.5/relativeImageWidth)-0.5;
00119 } else {
00120 maxX=(0.5*relativeImageWidth)-0.5;
00121 }
00122 if ( relativeImageHeight < 1.0 ) {
00123 maxY=(0.5/relativeImageHeight)-0.5;
00124 } else {
00125 maxY=(0.5*relativeImageHeight)-0.5;
00126 }
00127
00128 if ( m_PosY > maxY ) { m_PosY= maxY; }
00129 if ( m_PosY < -maxY ) { m_PosY=-maxY; }
00130 if ( m_PosX > maxX ) { m_PosX= maxX; }
00131 if ( m_PosX < -maxX ) { m_PosX=-maxX; }
00132
00133 glTranslatef(m_PosX,m_PosY,0.0);
00134 glScalef(m_Zoom,m_Zoom,0.0);
00135 glScalef( scaleX, scaleY, 1.0 );
00136
00137 if (m_TextureData)
00138 {
00139 paintImage();
00140 paintVectorObjects();
00141 }
00142 }
00143 }
00144
00145 void THIS::paintImage(){
00146
00147 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00148 glColor3f(1.0, 1.0, 1.0);
00149
00150 if (m_TextureData) {
00151
00152 if ( int ( m_TextureId ) == -1 )
00153 {
00154 glGenTextures ( 1, &m_TextureId );
00155 std::ostringstream stream;
00156 stream << "Using OpenGL texture # " << m_TextureId;
00157
00158 }
00159 else
00160 {
00161
00162
00163 }
00164
00165 std::ostringstream stream;
00166 stream << "Loading texture data to texture ID " << m_TextureId;
00167
00168
00169 glEnable(GL_TEXTURE_2D);
00170 glBindTexture(GL_TEXTURE_2D, m_TextureId);
00171
00172 if (m_TextureFormat==ImageGrabber::RGB8) {
00173 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_TextureResolution, m_TextureResolution, 0, GL_RGB, GL_UNSIGNED_BYTE, m_TextureData );
00174 } else {
00175 glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, m_TextureResolution, m_TextureResolution, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_TextureData );
00176 }
00177 }
00178
00179 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00180 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
00181 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
00182
00183 float usedTextureY=float(m_ImageHeight) / float(m_TextureResolution);
00184 float usedTextureX=float(m_ImageWidth) / float(m_TextureResolution);
00185
00186
00187 glColor3f(0.0, 1.0, 0.0);
00188 glBegin(GL_POLYGON);
00189 glTexCoord2f( 0.0, 0.0 );
00190 glVertex3f( -0.5, -0.5, 0.0 );
00191 glTexCoord2f( 0.0, usedTextureY );
00192 glVertex3f( -0.5, 0.5, 0.0 );
00193 glTexCoord2f( usedTextureX, usedTextureY );
00194 glVertex3f( 0.5, 0.5, 0.0 );
00195 glTexCoord2f( usedTextureX, 0.0 );
00196 glVertex3f( 0.5, -0.5, 0.0 );
00197 glEnd();
00198
00199 glDisable(GL_TEXTURE_2D);
00200 }
00201
00202
00203 void THIS::paintVectorObjects()
00204 {
00205 glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
00206 glColor3f(1.0, 1.0, 1.0);
00207 glPushMatrix();
00208
00209 glTranslatef( -0.5, -0.5, 0.0 );
00210
00211 glScalef( 1.0/m_ImageWidth, 1.0/m_ImageHeight, 1.0 );
00212
00213 glTranslatef( 0.5, 0.5, 0.0 );
00214
00215 std::list< VectorObject2D >::iterator vectorObjectIt;
00216 vectorObjectIt = m_VectorObjects.begin();
00217 while( vectorObjectIt != m_VectorObjects.end() )
00218 {
00219 vectorObjectIt->paintGl();
00220 vectorObjectIt++;
00221 }
00222
00223 glPopMatrix();
00224 }
00225
00226 void THIS::setColorImage(const unsigned char *image, unsigned width, unsigned height, float aspect)
00227 {
00228 if (!image) {
00229
00230 return;
00231 }
00232 setPixelAspectRatio( aspect );
00233
00234
00235
00236
00237
00238
00239 updateTexture( (unsigned char*)(const_cast<unsigned char*>(image)), width, height, ImageGrabber::RGB8 );
00240 }
00241
00242 void THIS::setColorImage(const ColorImageRGB8* image, float aspect )
00243 {
00244 if (!image) {
00245
00246 return;
00247 }
00248 setPixelAspectRatio( aspect );
00249 updateTexture( (unsigned char*)(const_cast<ColorImageRGB8*>(image)->unsafeRowPointerArray()[0][0]), image->getWidth(), image->getHeight(), ImageGrabber::RGB8 );
00250 }
00251
00252 void THIS::setColorImage(const GrayLevelImage8* imageY, const ColorImageUV8* imageUV, float aspect )
00253 {
00254 if ((!imageY) || (!imageUV)) {
00255
00256 return;
00257 }
00258
00259 ColorImageRGB8 imageRGB;
00260 Y8UV8ToRGB8Operator o( *imageY, *imageUV, imageRGB );
00261 setPixelAspectRatio( aspect );
00262 updateTexture( (unsigned char*)( imageRGB.unsafeRowPointerArray()[0][0]), imageRGB.getWidth(), imageRGB.getHeight(), ImageGrabber::RGB8 );
00263 }
00264
00265 void THIS::setGrayLevelImage(const puma2::GrayLevelImage8* image, float aspect )
00266 {
00267 if (!image) {
00268
00269 return;
00270 }
00271
00272 setPixelAspectRatio( aspect );
00273 updateTexture( (unsigned char*)(const_cast<GrayLevelImage8*>(image)->unsafeRowPointerArray()[0]), image->getWidth(), image->getHeight(), ImageGrabber::GRAY8 );
00274 }
00275
00276 void THIS::setThermalImage(const puma2::GrayLevelImage8* image, float roomTemp )
00277 {
00278 if (!image) {
00279
00280 return;
00281 }
00282
00283
00284 ColorImageRGB8 coloredThermalImage;
00285 ThermalToColorOperator( *image, coloredThermalImage, roomTemp-20, roomTemp+100 );
00286
00287
00288 float width=image->getWidth();
00289 float height=image->getHeight();
00290 float correctAspect= 4.0 / 3.0;
00291 float imageAspect=float(width) / float(height);
00292 setColorImage( &coloredThermalImage, correctAspect / imageAspect );
00293 }
00294
00295 void THIS::setAnaglyphImage( const puma2::GrayLevelImage8* leftYImage, const puma2::GrayLevelImage8* rightYImage, float aspect )
00296 {
00297 if ( !leftYImage || !rightYImage ) {
00298
00299 return;
00300 }
00301
00302 int w=leftYImage->getWidth();
00303 int h=leftYImage->getHeight();
00304
00305 setPixelAspectRatio( aspect );
00306
00307 unsigned char* tempImage=new unsigned char[w*h*3];
00308 unsigned char* left=(unsigned char*)(const_cast<GrayLevelImage8*>(leftYImage)->unsafeRowPointerArray()[0]);
00309 unsigned char* right=(unsigned char*)(const_cast<GrayLevelImage8*>(rightYImage)->unsafeRowPointerArray()[0]);
00310
00311
00312 int anaglyphOffset=1;
00313
00314
00315
00316
00317 for ( int y=0; y<h; y++ )
00318 {
00319 int i=y*w;
00320 int j=i*3;
00321 for ( int x=0; x<w-anaglyphOffset; x++ )
00322 {
00323 tempImage[j]=left[i+anaglyphOffset];
00324 i++;
00325 j+=3;
00326 }
00327 for ( int x=w-anaglyphOffset; x<w; x++ )
00328 {
00329 tempImage[j]=0;
00330 j+=3;
00331 }
00332 }
00333 for ( int y=0; y<h; y++ )
00334 {
00335 int i=y*w;
00336 int j=i*3;
00337 for ( int x=0; x<anaglyphOffset; x++ )
00338 {
00339 tempImage[j+1]=0;
00340 tempImage[j+2]=0;
00341 j+=3;
00342 i++;
00343 }
00344 for ( int x=anaglyphOffset; x<w; x++ )
00345 {
00346 tempImage[j+1]=right[i-anaglyphOffset];
00347 tempImage[j+2]=right[i-anaglyphOffset];
00348 j+=3;
00349 i++;
00350 }
00351 }
00352
00353 updateTexture( tempImage, w, h, ImageGrabber::RGB8 );
00354
00355 delete tempImage;
00356 }
00357
00358
00359 void THIS::addVectorObject( VectorObject2D vectorObject )
00360 {
00361 m_VectorObjects.push_back( vectorObject );
00362 }
00363
00364
00365 void THIS::clearForms()
00366 {
00367 m_VectorObjects.clear();
00368 }
00369
00370
00371
00372
00373 void THIS::updateTexture( unsigned char* imageData, unsigned width, unsigned height, ImageGrabber::ColorFormat format )
00374 {
00375 unsigned char* texturePos;
00376 unsigned char* imagePos;
00377
00378
00379 unsigned newTextureResolution=calcTextureSize(width,height);
00380 if ( (m_TextureData==0) || (m_TextureResolution!=newTextureResolution) )
00381 {
00382 std::ostringstream stream;
00383 int newTextureRes= calcTextureSize(width,height);
00384 stream << "Resizing Texture to " << newTextureRes << "x" << newTextureRes;
00385
00386 initTexture( newTextureRes, width, height, format );
00387 }
00388
00389 else if ( (m_ImageWidth != width) || (m_ImageHeight != height) ) {
00390 clearTexture();
00391 }
00392
00393 std::ostringstream stream;
00394 stream << "Updating texture";
00395
00396
00397 m_ImageWidth=width;
00398 m_ImageHeight=height;
00399 m_TextureFormat=format;
00400
00401 unsigned bytesPerPixel=1;
00402 if (format==ImageGrabber::RGB8) { bytesPerPixel=3; }
00403
00404
00405 texturePos=m_TextureData;
00406 imagePos=imageData;
00407
00408
00409 for( unsigned y = 0; y < height ; y++ ) {
00410 memcpy ( texturePos, imagePos, width*bytesPerPixel );
00411
00412 texturePos+=m_TextureResolution*bytesPerPixel;
00413 imagePos+=width*bytesPerPixel;
00414 }
00415
00416 updateGL();
00417 }
00418
00419 void THIS::clearTexture()
00420 {
00421 memset(m_TextureData, 128, m_TextureByteSize );
00422 }
00423
00424
00425 void THIS::initTexture( unsigned resolution, unsigned imageWidth, unsigned imageHeight, ImageGrabber::ColorFormat textureFormat )
00426 {
00427 m_ImageWidth=imageWidth;
00428 m_ImageHeight=imageHeight;
00429
00430 unsigned bytesPerPixel=1;
00431 if (textureFormat==ImageGrabber::RGB8) { bytesPerPixel=3; }
00432
00433 m_TextureResolution = resolution;
00434
00435 if( m_TextureData ) { delete m_TextureData; }
00436 m_TextureByteSize=m_TextureResolution * m_TextureResolution * bytesPerPixel;
00437 m_TextureData = new unsigned char[ m_TextureByteSize ];
00438 clearTexture();
00439 }
00440
00441
00442 void THIS::saveImage( std::string filename )
00443 {
00444 if ( !m_TextureData )
00445 {
00446
00447 return;
00448 }
00449
00450 switch( m_TextureFormat )
00451 {
00452 case ImageGrabber::RGB8:
00453 {
00454 ColorImageRGB8 image( m_ImageWidth, m_ImageHeight );
00455
00456 for( unsigned y = 0; y < m_ImageHeight ; y++ )
00457 {
00458 for( unsigned x = 0; x < m_ImageWidth; x++ )
00459 {
00460 image[y][x][0]=m_TextureData[x*3+y*m_TextureResolution*3];
00461 image[y][x][1]=m_TextureData[x*3+y*m_TextureResolution*3+1];
00462 image[y][x][2]=m_TextureData[x*3+y*m_TextureResolution*3+2];
00463 }
00464 }
00465
00466 break;
00467 }
00468 case ImageGrabber::GRAY8:
00469 {
00470 GrayLevelImage8 image( m_ImageWidth, m_ImageHeight );
00471
00472 for( unsigned y = 0; y < m_ImageHeight ; y++ )
00473 {
00474 for( unsigned x = 0; x < m_ImageWidth; x++ )
00475 {
00476 image[y][x]=m_TextureData[x+y*m_TextureResolution];
00477 }
00478 }
00479
00480 break;
00481 }
00482 default:
00483 break;
00484
00485 }
00486 }
00487
00488
00489
00490
00491 void THIS::mouseDoubleClickEvent( QMouseEvent* event = 0 )
00492 {
00493
00494 float viewPortAspect=float(m_ViewportWidth) / float(m_ViewportHeight);
00495 float imageAspect=float(m_ImageWidth) / float(m_ImageHeight) * m_PixelAspectRatio;
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 if (viewPortAspect > imageAspect) {
00508 m_Zoom = float(m_ImageHeight) / float(m_ViewportHeight);
00509 } else {
00510 m_Zoom = float(m_ImageWidth) / float(m_ViewportWidth);
00511 }
00512
00513 m_PosX=0.0;
00514 m_PosY=0.0;
00515 updateGL();
00516 }
00517
00518 void THIS::zoom(float z)
00519 {
00520 m_Zoom = z;
00521 m_PosX=0.0;
00522 m_PosY=0.0;
00523 updateGL();
00524 }
00525
00526 void THIS::mousePressEvent(QMouseEvent* event)
00527 {
00528 m_MousePosOld = event->pos();
00529 }
00530
00531 void THIS::mouseMoveEvent(QMouseEvent* event)
00532 {
00533 float deltaX=float(-m_MousePosOld.x() + event->x());
00534 float deltaY=float(-m_MousePosOld.y() + event->y());
00535 if (event->buttons() & Qt::LeftButton) {
00536 m_PosX += deltaX / m_ViewportWidth;
00537 m_PosY += deltaY / m_ViewportHeight;
00538 } else if (event->buttons() & Qt::RightButton) {
00539 m_Zoom *= std::pow( float(1.1), float(deltaY/10.0) );
00540 if (m_Zoom < 1.0) { m_Zoom=1.0; }
00541 if (m_Zoom > 32.0) { m_Zoom=32.0; }
00542 }
00543 m_MousePosOld = event->pos();
00544 updateGL();
00545 }
00546
00547
00548 void THIS::wheelEvent(QWheelEvent *event) {
00549 if (event->delta() < 0 ) {
00550 m_Zoom*=ZOOM_STEP;
00551
00552 m_PosX+=( 0.5 - float(event->x())/float(m_ViewportWidth ) ) / m_Zoom;
00553 m_PosY+=( 0.5 - float(event->y())/float(m_ViewportHeight) ) / m_Zoom;
00554 }
00555 if (event->delta() > 0 ) {
00556 m_Zoom/=ZOOM_STEP;
00557 }
00558
00559 if (m_Zoom > 32.0) { m_Zoom=32.0; }
00560 updateGL();
00561 }
00562
00563
00564
00565 int THIS::calcTextureSize( int width, int height )
00566 {
00567 int sizeSqared = 2;
00568
00569 while ( ( sizeSqared < width || sizeSqared < height ) && ( sizeSqared <= 256*256 ) )
00570 {
00571 sizeSqared = sizeSqared * 2;
00572 }
00573 return sizeSqared;
00574 }
00575
00576 #undef THIS