00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "../../Workers/Puma2/ThermalToColorOperator.h"
00012 #include "../../Workers/Puma2/Y8UV8ToRGB8Operator.h"
00013
00014
00015 #include "GLImagePainter.h"
00016
00017 #include <sstream>
00018 #include <QMouseEvent>
00019
00020 using namespace puma2;
00021
00022 #define THIS GLImagePainter
00023
00024 THIS::THIS()
00025 {
00026 m_ImageWidth = 1;
00027 m_ImageHeight = 1;
00028
00029 setPixelAspectRatio ( 1.0 );
00030
00031 m_TextureId = -1;
00032 m_TextureData = 0;
00033 m_TextureResolution = 0;
00034 m_TextureFormat = ImageGrabber::GRAY8;
00035 m_TextureByteSize = 0;
00036 }
00037
00038 THIS::~THIS()
00039 {
00040 if ( m_TextureData )
00041 {
00042
00043 delete m_TextureData;
00044 }
00045 if ( int ( m_TextureId ) != -1 )
00046 {
00047
00048 glDeleteTextures ( 1, &m_TextureId );
00049 }
00050 }
00051
00052 void THIS::paintImage( float alpha )
00053 {
00054
00055
00056
00057
00058 glEnable ( GL_BLEND );
00059 glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00060
00061 glColor4f ( 1.0, 1.0, 1.0, alpha );
00062
00063
00064 if ( m_TextureData )
00065 {
00066
00067 if ( int ( m_TextureId ) == -1 )
00068 {
00069 glGenTextures ( 1, &m_TextureId );
00070 std::ostringstream stream;
00071 stream << "Using OpenGL texture # " << m_TextureId;
00072
00073 }
00074 else
00075 {
00076 glDeleteTextures ( 1, &m_TextureId );
00077 glGenTextures ( 1, &m_TextureId );
00078 }
00079
00080 std::ostringstream stream;
00081 stream << "Loading texture data to texture ID " << m_TextureId;
00082
00083
00084 glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );
00085 glEnable ( GL_TEXTURE_2D );
00086 glBindTexture ( GL_TEXTURE_2D, m_TextureId );
00087
00088 if ( m_TextureFormat == ImageGrabber::RGB8 )
00089 {
00090 glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, m_TextureResolution, m_TextureResolution, 0, GL_RGB, GL_UNSIGNED_BYTE, m_TextureData );
00091 }
00092 else
00093 {
00094 glTexImage2D ( GL_TEXTURE_2D, 0, GL_LUMINANCE, m_TextureResolution, m_TextureResolution, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_TextureData );
00095 }
00096
00097 glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
00098 glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
00099 glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
00100
00101 float usedTextureY = float ( m_ImageHeight ) / float ( m_TextureResolution );
00102 float usedTextureX = float ( m_ImageWidth ) / float ( m_TextureResolution );
00103
00104
00105 glBegin ( GL_POLYGON );
00106 glTexCoord2f ( 0.0, 0.0 );
00107 glVertex3f ( -0.5, 0.5, 0.0 );
00108 glTexCoord2f ( 0.0, usedTextureY );
00109 glVertex3f ( -0.5, -0.5, 0.0 );
00110 glTexCoord2f ( usedTextureX, usedTextureY );
00111 glVertex3f ( 0.5, -0.5, 0.0 );
00112 glTexCoord2f ( usedTextureX, 0.0 );
00113 glVertex3f ( 0.5, 0.5, 0.0 );
00114 glEnd();
00115
00116 glDisable ( GL_TEXTURE_2D );
00117 }
00118
00119
00120 }
00121
00122
00123 void THIS::paintVectorObjects()
00124 {
00125 glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE );
00126
00127
00128 glColor3f ( 1.0, 1.0, 1.0 );
00129 glLineWidth( 1.0 );
00130 glBegin ( GL_POLYGON );
00131 glVertex3f ( -0.5, -0.5, 0.0 );
00132 glVertex3f ( -0.5, 0.5, 0.0 );
00133 glVertex3f ( 0.5, 0.5, 0.0 );
00134 glVertex3f ( 0.5, -0.5, 0.0 );
00135 glEnd();
00136
00137 glColor3f ( 1.0, 1.0, 1.0 );
00138 glPushMatrix();
00139
00140 glScalef ( 1.0 , -1.0, 1.0 );
00141 glTranslatef ( -0.5, -0.5, 0.0 );
00142
00143 glScalef ( 1.0 / m_ImageWidth, 1.0 / m_ImageHeight, 1.0 );
00144
00145 glTranslatef ( 0.5, 0.5, 0.0 );
00146
00147 std::list< VectorObject2D >::iterator vectorObjectIt;
00148 vectorObjectIt = m_VectorObjects.begin();
00149 while ( vectorObjectIt != m_VectorObjects.end() )
00150 {
00151 vectorObjectIt->paintGl();
00152 vectorObjectIt++;
00153 }
00154
00155 glPopMatrix();
00156 }
00157
00158
00159 void THIS::setColorImage ( const ColorImageRGB8* image, float aspect )
00160 {
00161 if ( !image )
00162 {
00163
00164 return;
00165 }
00166 setPixelAspectRatio ( aspect );
00167 updateTexture ( ( unsigned char* ) ( const_cast<ColorImageRGB8*> ( image )->unsafeRowPointerArray() [0][0] ), image->getWidth(), image->getHeight(), ImageGrabber::RGB8 );
00168 }
00169
00170 void THIS::setColorImage ( const GrayLevelImage8* yImage, const ColorImageUV8* uvImage, float aspect )
00171 {
00172 if ( ( !yImage ) || ( !uvImage ) )
00173 {
00174
00175 return;
00176 }
00177
00178 ColorImageRGB8 rgbImage;
00179 Y8UV8ToRGB8Operator o ( *yImage, *uvImage, rgbImage );
00180 setPixelAspectRatio ( aspect );
00181 updateTexture ( ( unsigned char* ) ( rgbImage.unsafeRowPointerArray() [0][0] ), rgbImage.getWidth(), rgbImage.getHeight(), ImageGrabber::RGB8 );
00182 }
00183
00184 void THIS::setGrayLevelImage ( const puma2::GrayLevelImage8* image, float aspect )
00185 {
00186 if ( !image )
00187 {
00188
00189 return;
00190 }
00191
00192 setPixelAspectRatio ( aspect );
00193 updateTexture ( ( unsigned char* ) ( const_cast<GrayLevelImage8*> ( image )->unsafeRowPointerArray() [0] ), image->getWidth(), image->getHeight(), ImageGrabber::GRAY8 );
00194 }
00195
00196 void THIS::setThermalImage ( const puma2::GrayLevelImage8* image, float roomTemp )
00197 {
00198 if ( !image )
00199 {
00200
00201 return;
00202 }
00203
00204
00205 ColorImageRGB8 coloredThermalImage;
00206 ThermalToColorOperator ( *image, coloredThermalImage, roomTemp - 20, roomTemp + 100 );
00207
00208
00209 float width = image->getWidth();
00210 float height = image->getHeight();
00211 float correctAspect = 4.0 / 3.0;
00212 float imageAspect = float ( width ) / float ( height );
00213 setColorImage ( &coloredThermalImage, correctAspect / imageAspect );
00214 }
00215
00216 void THIS::setAnaglyphImage ( const puma2::GrayLevelImage8* leftYImage, const puma2::GrayLevelImage8* rightYImage, float aspect )
00217 {
00218 if ( !leftYImage || !rightYImage )
00219 {
00220
00221 return;
00222 }
00223
00224 int w = leftYImage->getWidth();
00225 int h = leftYImage->getHeight();
00226
00227 setPixelAspectRatio ( aspect );
00228
00229 unsigned char* tempImage = new unsigned char[w*h*3];
00230 unsigned char* left = ( unsigned char* ) ( const_cast<GrayLevelImage8*> ( leftYImage )->unsafeRowPointerArray() [0] );
00231 unsigned char* right = ( unsigned char* ) ( const_cast<GrayLevelImage8*> ( rightYImage )->unsafeRowPointerArray() [0] );
00232
00233
00234 int anaglyphOffset = 1;
00235
00236
00237
00238
00239 for ( int y = 0; y < h; y++ )
00240 {
00241 int i = y * w;
00242 int j = i * 3;
00243 for ( int x = 0; x < w - anaglyphOffset; x++ )
00244 {
00245 tempImage[j] = left[i+anaglyphOffset];
00246 i++;
00247 j += 3;
00248 }
00249 for ( int x = w - anaglyphOffset; x < w; x++ )
00250 {
00251 tempImage[j] = 0;
00252 j += 3;
00253 }
00254 }
00255 for ( int y = 0; y < h; y++ )
00256 {
00257 int i = y * w;
00258 int j = i * 3;
00259 for ( int x = 0; x < anaglyphOffset; x++ )
00260 {
00261 tempImage[j+1] = 0;
00262 tempImage[j+2] = 0;
00263 j += 3;
00264 i++;
00265 }
00266 for ( int x = anaglyphOffset; x < w; x++ )
00267 {
00268 tempImage[j+1] = right[i-anaglyphOffset];
00269 tempImage[j+2] = right[i-anaglyphOffset];
00270 j += 3;
00271 i++;
00272 }
00273 }
00274
00275 updateTexture ( tempImage, w, h, ImageGrabber::RGB8 );
00276
00277 delete tempImage;
00278 }
00279
00280
00281 void THIS::addVectorObject ( VectorObject2D vectorObject )
00282 {
00283 m_VectorObjects.push_back ( vectorObject );
00284 }
00285
00286
00287 void THIS::clearForms()
00288 {
00289 m_VectorObjects.clear();
00290 }
00291
00292
00293
00294
00295 void THIS::updateTexture ( unsigned char* imageData, unsigned width, unsigned height, ImageGrabber::ColorFormat format )
00296 {
00297 unsigned char* texturePos;
00298 unsigned char* imagePos;
00299
00300
00301 unsigned newTextureResolution = GLImagePainter::calcTextureSize ( width, height );
00302 if ( ( m_TextureData == 0 ) || ( m_TextureResolution != newTextureResolution ) )
00303 {
00304 std::ostringstream stream;
00305 int newTextureRes = GLImagePainter::calcTextureSize ( width, height );
00306 stream << "Resizing Texture to " << newTextureRes << "x" << newTextureRes;
00307
00308 initTexture ( newTextureRes, width, height, format );
00309 }
00310
00311 else if ( ( m_ImageWidth != width ) || ( m_ImageHeight != height ) )
00312 {
00313 clearTexture();
00314 }
00315
00316 std::ostringstream stream;
00317 stream << "Updating texture";
00318
00319
00320 m_ImageWidth = width;
00321 m_ImageHeight = height;
00322 m_TextureFormat = format;
00323
00324 unsigned bytesPerPixel = 1;
00325 if ( format == ImageGrabber::RGB8 ) { bytesPerPixel = 3; }
00326
00327
00328 texturePos = m_TextureData;
00329 imagePos = imageData;
00330
00331
00332 for ( unsigned y = 0; y < height ; y++ )
00333 {
00334 memcpy ( texturePos, imagePos, width*bytesPerPixel );
00335
00336 texturePos += m_TextureResolution * bytesPerPixel;
00337 imagePos += width * bytesPerPixel;
00338 }
00339 }
00340
00341 void THIS::clearTexture()
00342 {
00343 memset ( m_TextureData, 128, m_TextureByteSize );
00344 }
00345
00346
00347 void THIS::initTexture ( unsigned resolution, unsigned imageWidth, unsigned imageHeight, ImageGrabber::ColorFormat textureFormat )
00348 {
00349 m_ImageWidth = imageWidth;
00350 m_ImageHeight = imageHeight;
00351
00352 unsigned bytesPerPixel = 1;
00353 if ( textureFormat == ImageGrabber::RGB8 ) { bytesPerPixel = 3; }
00354
00355 m_TextureResolution = resolution;
00356
00357 if ( m_TextureData ) { delete m_TextureData; }
00358 m_TextureByteSize = m_TextureResolution * m_TextureResolution * bytesPerPixel;
00359 m_TextureData = new unsigned char[ m_TextureByteSize ];
00360 clearTexture();
00361 }
00362
00363
00364 void THIS::saveImage ( std::string filename )
00365 {
00366 if ( !m_TextureData )
00367 {
00368
00369 return;
00370 }
00371
00372 switch ( m_TextureFormat )
00373 {
00374 case ImageGrabber::RGB8:
00375 {
00376 ColorImageRGB8 image ( m_ImageWidth, m_ImageHeight );
00377
00378 for ( unsigned y = 0; y < m_ImageHeight ; y++ )
00379 {
00380 for ( unsigned x = 0; x < m_ImageWidth; x++ )
00381 {
00382 image[y][x][0] = m_TextureData[x*3+y*m_TextureResolution*3];
00383 image[y][x][1] = m_TextureData[x*3+y*m_TextureResolution*3+1];
00384 image[y][x][2] = m_TextureData[x*3+y*m_TextureResolution*3+2];
00385 }
00386 }
00387
00388 break;
00389 }
00390 case ImageGrabber::GRAY8:
00391 {
00392 GrayLevelImage8 image ( m_ImageWidth, m_ImageHeight );
00393
00394 for ( unsigned y = 0; y < m_ImageHeight ; y++ )
00395 {
00396 for ( unsigned x = 0; x < m_ImageWidth; x++ )
00397 {
00398 image[y][x] = m_TextureData[x+y*m_TextureResolution];
00399 }
00400 }
00401
00402 break;
00403 }
00404 default:
00405
00406 break;
00407 }
00408 }
00409
00410
00411
00412 int THIS::calcTextureSize( int width, int height )
00413 {
00414 int sizeSqared = 2;
00415
00416 while ( ( sizeSqared < width || sizeSqared < height ) && ( sizeSqared <= 256*256 ) )
00417 {
00418 sizeSqared = sizeSqared * 2;
00419 }
00420 return sizeSqared;
00421 }
00422
00423
00424
00425 #undef THIS