GLImageBox.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                                                         *
00003  *   This is a QGLWidget displaying an image or portion of an image in a   *
00004  *   box.                                                                  *
00005  *                                                                         *
00006  *   Author:    Graeme van der Vlugt                                       *
00007  *   Copyright: Imetric 3D GmbH                                            *
00008  *   Year:      2004                                                       *
00009  *                                                                         *
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU Library General Public License as       *
00013  *   published by the Free Software Foundation; either version 2 of the    *
00014  *   License, or (at your option) any later version.                       *
00015  *   for detail see the LICENCE text file.                                 *
00016  *                                                                         *
00017  ***************************************************************************/
00018 
00019 #include "PreCompiled.h"
00020 #ifndef _PreComp_
00021 # include <cmath>
00022 # include <QMessageBox>
00023 #endif
00024 
00025 #if defined(__MINGW32__)
00026 # include <GL/gl.h>
00027 # include <GL/glext.h>
00028 #endif
00029 
00030 #include "GLImageBox.h"
00031 
00032 using namespace ImageGui;
00033 
00034 #if defined(Q_CC_MSVC)
00035 #pragma warning(disable:4305) // init: truncation from const double to float
00036 #endif
00037 
00038 /* TRANSLATOR ImageGui::GLImageBox */
00039 
00040 // Constructor
00041 GLImageBox::GLImageBox(QWidget * parent, const QGLWidget * shareWidget, Qt::WFlags f)
00042     : QGLWidget(parent, shareWidget, f)
00043 {
00044     // uses default display format for the OpenGL rendering context
00045     // (double buffering is enabled)
00046 
00047     // enable mouse tracking when moving even if no buttons are pressed
00048     setMouseTracking(true);
00049 
00050     // initialise variables
00051     _x0 = 0;
00052     _y0 = 0;
00053     _zoomFactor = 1.0;
00054     _base_x0 = 0;
00055     _base_y0 = 0;
00056     _pColorMap = 0;
00057     _numMapEntries = 0;
00058 }
00059 
00060 
00061 // Destructor
00062 GLImageBox::~GLImageBox()
00063 {
00064     try
00065     {
00066         delete [] _pColorMap;
00067     }
00068     catch(...) {}
00069 }
00070 
00071 // Set up the OpenGL rendering state
00072 void GLImageBox::initializeGL()
00073 {
00074   qglClearColor( Qt::black );           // Let OpenGL clear to black
00075 }
00076 
00077 
00078 // Update the viewport
00079 void GLImageBox::resizeGL( int w, int h )
00080 {
00081     glViewport( 0, 0, (GLint)w, (GLint)h );
00082     glMatrixMode( GL_PROJECTION );
00083     glLoadIdentity();
00084     gluOrtho2D(0, width() - 1, height() - 1, 0);
00085     glMatrixMode(GL_MODELVIEW);
00086 }
00087 
00088 // Redraw (current image)
00089 void GLImageBox::redraw()
00090 {
00091     glDraw();
00092 }
00093 
00094 
00095 // Paint the box
00096 void GLImageBox::paintGL()
00097 {
00098     // clear background (in back buffer)
00099     glDrawBuffer(GL_BACK);
00100     glClear(GL_COLOR_BUFFER_BIT);
00101 
00102     // Draw the image
00103     drawImage();
00104 
00105     // Emit a signal for owners to draw any graphics that is needed.
00106     if (_image.hasValidData() == true)
00107         drawGraphics();
00108 
00109     // flush the OpenGL graphical pipeline
00110     glFinish();
00111 
00112     // Double buffering is used so we need to swap the buffers
00113     // There is no need to explicitly call this function because it is 
00114     // done automatically after each widget repaint, i.e. each time after paintGL() has been executed
00115     // swapBuffers();
00116 }
00117 
00118 // Draw the image
00119 void GLImageBox::drawImage()
00120 {
00121     if (_image.hasValidData() == false)
00122         return;
00123 
00124     // Gets the size of the diplayed image area using the current display settings 
00125     // (in units of image pixels)
00126     int dx, dy;
00127     getDisplayedImageAreaSize(dx, dy);
00128 
00129    // Draw the visible image region with the correct position and zoom
00130     if ((dx > 0) && (dy > 0))
00131     {
00132         // Get top left image pixel to display
00133         int tlx = std::max<int>(0, _x0);
00134         int tly = std::max<int>(0, _y0);
00135 
00136         // Get pointer to first pixel in source image rectangle
00137         unsigned char* pPix = (unsigned char *)(_image.getPixelDataPtr());
00138         pPix += (unsigned long)(_image.getNumBytesPerPixel()) * (tly * _image.getWidth() + tlx);
00139 
00140         // Draw in the back buffer, using the following parameters
00141         glDrawBuffer(GL_BACK);
00142         glPixelStorei(GL_UNPACK_ROW_LENGTH, _image.getWidth()); // defines number of pixels in a row
00143         glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // defines byte alignment of rows
00144         glPixelZoom(_zoomFactor, -_zoomFactor); // defines the zoom factors to draw at
00145 
00146         // set current raster position to coincide with top left image pixel to display
00147         // the first pixel is always displayed in full when zoomed in
00148          // round to nearest widget pixel that coincides with top left corner of top left image pixel to display
00149         int xx = (int)floor(ICToWC_X(tlx - 0.5) + 0.5);
00150         int yy = (int)floor(ICToWC_Y(tly - 0.5) + 0.5);
00151         glRasterPos2f(xx, yy);
00152 
00153         // Compute scale to stretch number of significant bits to full range
00154         // e.g. stretch 12 significant bits to 16-bit range: 0-4095 -> 0-65535, therefore scale = 65535/4095
00155         double scale = (pow(2.0, _image.getNumBitsPerSample()) - 1.0) / (pow(2.0, _image.getNumSigBitsPerSample()) - 1.0);
00156         glPixelTransferf(GL_RED_SCALE, (float)scale);
00157         glPixelTransferf(GL_GREEN_SCALE, (float)scale);
00158         glPixelTransferf(GL_BLUE_SCALE, (float)scale);
00159 
00160         // Load the color map if present
00161         if (_pColorMap != 0)
00162         {
00163             glPixelTransferf(GL_MAP_COLOR, 1.0);
00164             glPixelMapfv(GL_PIXEL_MAP_R_TO_R, _numMapEntries, _pColorMap);
00165             glPixelMapfv(GL_PIXEL_MAP_G_TO_G, _numMapEntries, _pColorMap + _numMapEntries);
00166             glPixelMapfv(GL_PIXEL_MAP_B_TO_B, _numMapEntries, _pColorMap + _numMapEntries * 2);
00167             glPixelMapfv(GL_PIXEL_MAP_A_TO_A, _numMapEntries, _pColorMap + _numMapEntries * 3);
00168         }
00169         else
00170         {
00171             glPixelTransferf(GL_MAP_COLOR, 0.0);
00172             float zero = 0.0;
00173             float one = 1.0;
00174             glPixelMapfv(GL_PIXEL_MAP_R_TO_R, 1, &zero);
00175             glPixelMapfv(GL_PIXEL_MAP_G_TO_G, 1, &zero);
00176             glPixelMapfv(GL_PIXEL_MAP_B_TO_B, 1, &zero);
00177             glPixelMapfv(GL_PIXEL_MAP_A_TO_A, 1, &one);
00178         }
00179 
00180         // Get the pixel format
00181         GLenum pixFormat;
00182         GLenum pixType;
00183         getPixFormat(pixFormat, pixType);
00184 
00185         // Draw the defined source rectangle
00186         glDrawPixels(dx, dy, pixFormat, pixType, (GLvoid *)pPix);
00187         glFlush();
00188     }
00189 }
00190 
00191 // Gets the size of the diplayed image area using the current display settings 
00192 // (in units of image pixels)
00193 void GLImageBox::getDisplayedImageAreaSize(int &dx, int &dy)
00194 {
00195     if (_image.hasValidData() == false)
00196     {
00197         dx = 0;
00198         dy = 0;
00199     }
00200     else
00201     {
00202         // Make sure drawing position and zoom factor are valid
00203         limitCurrPos();
00204         limitZoomFactor();
00205 
00206         // Image coordinates of top left widget pixel = (_x0, _y0)
00207         // Get image coordinates of bottom right widget pixel
00208         int brx = (int)ceil(WCToIC_X(width() - 1));
00209         int bry = (int)ceil(WCToIC_Y(height() - 1));
00210 
00211         // Find the outer coordinates of the displayed image area
00212         int itlx = std::max<int>(_x0, 0);
00213         int itly = std::max<int>(_y0, 0);
00214         int ibrx = std::min<int>(brx, (int)(_image.getWidth()) - 1);
00215         int ibry = std::min<int>(bry, (int)(_image.getHeight()) - 1);
00216         if ((itlx >= (int)(_image.getWidth())) || 
00217             (itly >= (int)(_image.getHeight())) || 
00218             (ibrx < 0) || 
00219             (ibry < 0))
00220         {
00221             dx = 0;
00222             dy = 0;
00223         }
00224         dx = ibrx - itlx + 1;
00225         dy = ibry - itly + 1;
00226     }
00227 }
00228 
00229 // Gets the value of an image sample at the given image pixel position
00230 // Returns 0 for valid value or -1 if coordinates or sample index are out of range or 
00231 // if there is no image data
00232 int GLImageBox::getImageSample(int x, int y, unsigned short sampleIndex, double &value)
00233 {
00234     return (_image.getSample(x, y, sampleIndex, value));
00235 }
00236 
00237 // Gets the number of samples per pixel for the image
00238 unsigned short GLImageBox::getImageNumSamplesPerPix()
00239 {
00240     return (_image.getNumSamples());
00241 }
00242 
00243 // Gets the format (color space format) of the image
00244 int GLImageBox::getImageFormat()
00245 {
00246     return (_image.getFormat());
00247 }
00248 
00249 
00250 // Get the OpenGL pixel format and pixel type from the image properties
00251 void GLImageBox::getPixFormat(GLenum &pixFormat, GLenum &pixType)
00252 {
00253     switch(_image.getFormat())
00254     {
00255         case IB_CF_GREY8:
00256             pixFormat = GL_LUMINANCE;
00257             pixType = GL_UNSIGNED_BYTE;
00258             break;
00259         case IB_CF_GREY16:
00260             pixFormat = GL_LUMINANCE;
00261             pixType = GL_UNSIGNED_SHORT;
00262             break;
00263         case IB_CF_GREY32:
00264             pixFormat = GL_LUMINANCE;
00265             pixType = GL_UNSIGNED_INT;
00266             break;
00267         case IB_CF_RGB24:
00268             pixFormat = GL_RGB;
00269             pixType = GL_UNSIGNED_BYTE;
00270             break;
00271 #ifndef FC_OS_CYGWIN
00272         case IB_CF_BGR24:
00273             pixFormat = GL_BGR_EXT;
00274             pixType = GL_UNSIGNED_BYTE;
00275             break;
00276         case IB_CF_RGB48:
00277             pixFormat = GL_RGB;
00278             pixType = GL_UNSIGNED_SHORT;
00279             break;
00280         case IB_CF_BGR48:
00281             pixFormat = GL_BGR_EXT;
00282             pixType = GL_UNSIGNED_SHORT;
00283             break;
00284 #endif
00285         case IB_CF_RGBA32:
00286             pixFormat = GL_RGBA;
00287             pixType = GL_UNSIGNED_BYTE;
00288             break;
00289         case IB_CF_RGBA64:
00290             pixFormat = GL_RGBA;
00291             pixType = GL_UNSIGNED_SHORT;
00292             break;
00293 #ifndef FC_OS_CYGWIN
00294         case IB_CF_BGRA32:
00295             pixFormat = GL_BGRA_EXT;
00296             pixType = GL_UNSIGNED_BYTE;
00297             break;
00298         case IB_CF_BGRA64:
00299             pixFormat = GL_BGRA_EXT;
00300             pixType = GL_UNSIGNED_SHORT;
00301             break;
00302 #endif
00303         default:
00304             // Should never happen
00305             pixFormat = GL_LUMINANCE;
00306             pixType = GL_UNSIGNED_BYTE;
00307             QMessageBox::warning((QWidget *)this, tr("Image pixel format"),
00308                 tr("Undefined type of colour space for image viewing"));
00309             return;
00310     }
00311 }
00312 
00313 // Limits the current position (centre of top left image pixel)
00314 // Currently we don't limit it!
00315 void GLImageBox::limitCurrPos()
00316 {
00317     if (_image.hasValidData() == false)
00318         return;
00319 
00320     /*
00321     if (_x0 < 0)
00322         _x0 = 0;
00323     else if (_x0 >= (int)(_image.getWidth()))
00324         _x0 = _image.getWidth() - 1;
00325     if (_y0 < 0)
00326         _y0 = 0;
00327     else if (_y0 >= (int)(_image.getHeight()))
00328         _y0 = _image.getHeight() - 1;
00329     */
00330 }
00331 
00332 // Limits the current zoom factor from 1:64 to 64:1
00333 void GLImageBox::limitZoomFactor()
00334 {
00335     if (_zoomFactor > 64.0)
00336         _zoomFactor = 64.0;
00337     else if (_zoomFactor < (1.0 / 64.0))
00338         _zoomFactor = 1.0 / 64.0;
00339 }
00340 
00341 // Set the current position (centre of top left image pixel coordinates)
00342 // This function does not redraw (call redraw afterwards)
00343 void GLImageBox::setCurrPos(int x0, int y0)
00344 {
00345     _x0 = x0;
00346     _y0 = y0;
00347     limitCurrPos();
00348 }
00349 
00350 // Fixes a base position at the current position
00351 void GLImageBox::fixBasePosCurr()
00352 {
00353     if (_image.hasValidData() == false)
00354     {
00355         _base_x0 = 0;
00356         _base_y0 = 0;
00357     }
00358     else
00359     {
00360         _base_x0 = _x0;
00361         _base_y0 = _y0;
00362     }
00363 }
00364 
00365 // Set the current zoom factor
00366 // Option to centre the zoom at a given image point or not
00367 // This function does not redraw (call redraw afterwards)
00368 void GLImageBox::setZoomFactor(double zoomFactor, bool useCentrePt, int ICx, int ICy)
00369 {
00370     if ((useCentrePt == false) || (_image.hasValidData() == false))
00371     {
00372         _zoomFactor = zoomFactor;
00373         limitZoomFactor();
00374     }
00375     else
00376     {
00377         // Set new zoom factor
00378         _zoomFactor = zoomFactor;
00379         limitZoomFactor();
00380 
00381         // get centre position of widget in image coordinates
00382         int ix, iy;
00383         getCentrePoint(ix, iy);
00384 
00385         // try to shift the current position so that defined centre point is in the middle of the widget
00386         // (this can be modified by the limitCurrPos function)
00387         setCurrPos(_x0 - ix + ICx, _y0 - iy + ICy);
00388     }
00389 }
00390 
00391 // Stretch or shrink the image to fit the view (although the zoom factor is limited so a 
00392 // very small or very big image may not fit completely (depending on the size of the view)
00393 // This function redraws
00394 void GLImageBox::stretchToFit()
00395 {
00396     if (_image.hasValidData() == false)
00397         return;
00398 
00399     setToFit();
00400     glDraw();
00401 }
00402 
00403 // Sets the settings needed to fit the image into the view (although the zoom factor is limited so a 
00404 // very small or very big image may not fit completely (depending on the size of the view)
00405 // This function does not redraw (call redraw afterwards)
00406 void GLImageBox::setToFit()
00407 {
00408     if (_image.hasValidData() == false)
00409         return;
00410 
00411     // Compute ideal zoom factor to fit the image
00412     double zoomX = (double)width() / (double)(_image.getWidth());
00413     double zoomY = (double)height() / (double)(_image.getHeight());
00414     if (zoomX > zoomY)
00415         _zoomFactor = zoomY;
00416     else
00417         _zoomFactor = zoomX;
00418     limitZoomFactor();
00419 
00420     // set current position to top left image pixel
00421     setCurrPos(0, 0);
00422 }
00423 
00424 // Sets the normal viewing position and zoom = 1
00425 // If the image is smaller than the widget then the image is centred 
00426 // otherwise we view the top left part of the image
00427 // This function does not redraw (call redraw afterwards)
00428 void GLImageBox::setNormal()
00429 {
00430     if (_image.hasValidData() == false)
00431         return;
00432 
00433     if (((int)(_image.getWidth()) < width()) && ((int)(_image.getHeight()) < height()))
00434     {
00435         setZoomFactor(1.0, true, _image.getWidth() / 2, _image.getHeight() / 2);
00436     }
00437     else
00438     {
00439         _zoomFactor = 1;
00440         setCurrPos(0, 0);
00441     }
00442 }
00443 
00444 // Gets the image coordinates of the centre point of the widget 
00445 void GLImageBox::getCentrePoint(int &ICx, int &ICy)
00446 {
00447     ICx = (int)floor(WCToIC_X((double)(width() - 1) / 2.0) + 0.5);
00448     ICy = (int)floor(WCToIC_Y((double)(height() - 1) / 2.0) + 0.5);
00449 }
00450 
00451 // Moves the image by a relative amount (in widget pixel units) from the base position
00452 // First use fixBasePosCurr() to fix the base position at a position
00453 void GLImageBox::relMoveWC(int WCdx, int WCdy)
00454 {
00455     double ICdx = WCdx / _zoomFactor;
00456     double ICdy = WCdy / _zoomFactor;
00457     setCurrPos(_base_x0 - (int)floor(ICdx + 0.5), _base_y0 - (int)floor(ICdy + 0.5));
00458     glDraw();
00459 }
00460 
00461 // Computes an image x-coordinate from the widget x-coordinate
00462 // Note: (_x0,_y0) is the centre of the image pixel displayed at the top left of the widget
00463 // therefore (_x0 - 0.5, _y0 - 0.5) is the top left coordinate of this pixel which will 
00464 // theoretically coincide with widget coordinate (-0.5,-0.5)
00465 // Zoom = 4:    Widget(0,0) = Image(_x0 - 0.375,_y0 - 0.375)
00466 // Zoom = 2:    Widget(0,0) = Image(_x0 - 0.250,_y0 - 0.250)
00467 // Zoom = 1:    Widget(0,0) = Image(_x0,_y0)
00468 // Zoom = 0.5:  Widget(0,0) = Image(_x0 + 0.500,_y0 + 0.500)
00469 // Zoom = 0.25: Widget(0,0) = Image(_x0 + 1.500,_y0 + 1.500)
00470 double GLImageBox::WCToIC_X(double WidgetX)
00471 {
00472     return ((double)_x0 - 0.5 + (WidgetX + 0.5) / _zoomFactor);
00473 }
00474 
00475 // Computes an image y-coordinate from the widget y-coordinate
00476 // Note: (_x0,_y0) is the centre of the image pixel displayed at the top left of the widget
00477 // therefore (_x0 - 0.5, _y0 - 0.5) is the top left coordinate of this pixel which will 
00478 // theoretically coincide with widget coordinate (-0.5,-0.5)
00479 // Zoom = 4:    Widget(0,0) = Image(_x0 - 0.375,_y0 - 0.375)
00480 // Zoom = 2:    Widget(0,0) = Image(_x0 - 0.250,_y0 - 0.250)
00481 // Zoom = 1:    Widget(0,0) = Image(_x0,_y0)
00482 // Zoom = 0.5:  Widget(0,0) = Image(_x0 + 0.500,_y0 + 0.500)
00483 // Zoom = 0.25: Widget(0,0) = Image(_x0 + 1.500,_y0 + 1.500)
00484 double GLImageBox::WCToIC_Y(double WidgetY)
00485 {
00486     return ((double)_y0 - 0.5 + (WidgetY + 0.5) / _zoomFactor);
00487 }
00488 
00489 // Computes a widget x-coordinate from an image x-coordinate
00490 // Note: (_x0,_y0) is the centre of the image pixel displayed at the top left of the widget
00491 // therefore (_x0 - 0.5, _y0 - 0.5) is the top left coordinate of this pixel which will 
00492 // theoretically coincide with widget coordinate (-0.5,-0.5)
00493 // Zoom = 4:    Widget(0,0) = Image(_x0 - 0.375,_y0 - 0.375)
00494 // Zoom = 2:    Widget(0,0) = Image(_x0 - 0.250,_y0 - 0.250)
00495 // Zoom = 1:    Widget(0,0) = Image(_x0,_y0)
00496 // Zoom = 0.5:  Widget(0,0) = Image(_x0 + 0.500,_y0 + 0.500)
00497 // Zoom = 0.25: Widget(0,0) = Image(_x0 + 1.500,_y0 + 1.500)
00498 double GLImageBox::ICToWC_X(double ImageX)
00499 {
00500     return ((ImageX - (double)_x0 + 0.5) * _zoomFactor - 0.5);
00501 }
00502 
00503 // Computes a widget y-coordinate from an image y-coordinate
00504 // Note: (_x0,_y0) is the centre of the image pixel displayed at the top left of the widget
00505 // therefore (_x0 - 0.5, _y0 - 0.5) is the top left coordinate of this pixel which will 
00506 // theoretically coincide with widget coordinate (-0.5,-0.5)
00507 // Zoom = 4:    Widget(0,0) = Image(_x0 - 0.375,_y0 - 0.375)
00508 // Zoom = 2:    Widget(0,0) = Image(_x0 - 0.250,_y0 - 0.250)
00509 // Zoom = 1:    Widget(0,0) = Image(_x0,_y0)
00510 // Zoom = 0.5:  Widget(0,0) = Image(_x0 + 0.500,_y0 + 0.500)
00511 // Zoom = 0.25: Widget(0,0) = Image(_x0 + 1.500,_y0 + 1.500)
00512 double GLImageBox::ICToWC_Y(double ImageY)
00513 {
00514     return ((ImageY - (double)_y0 + 0.5) * _zoomFactor - 0.5);
00515 }
00516 
00517 
00518 // Clears the image data
00519 void GLImageBox::clearImage()
00520 {
00521     _image.clear();
00522     resetDisplay();
00523 }
00524 
00525 // Load image by copying the pixel data
00526 // The image object will take ownership of the copied pixel data
00527 // (the source image is still controlled by the caller)
00528 // If numSigBitsPerSample = 0 then the full range is assumed to be significant
00529 // displayMode ... controls the initial display of the image, one of:
00530 //                      IV_DISPLAY_NOCHANGE  ... no change to view settings when displaying a new image
00531 //                      IV_DISPLAY_FITIMAGE  ... fit-image when displaying a new image (other settings remain the same)
00532 //                      IV_DISPLAY_RESET     ... reset settings when displaying a new image (image will be displayed at 1:1 scale with no color map)
00533 // This function does not redraw (call redraw afterwards)
00534 // Returns:
00535 //               0 for OK
00536 //              -1 for invalid color format
00537 //              -2 for memory allocation error
00538 int GLImageBox::createImageCopy(void* pSrcPixelData, unsigned long width, unsigned long height, int format, unsigned short numSigBitsPerSample, int displayMode)
00539 {
00540     // Copy image
00541     int ret = _image.createCopy(pSrcPixelData, width, height, format, numSigBitsPerSample);
00542 
00543     // Set display settings depending on mode
00544     if (displayMode == IV_DISPLAY_RESET)
00545     {
00546         // reset drawing settings (position, scale, colour mapping) if requested
00547         resetDisplay();
00548     }
00549     else if (displayMode == IV_DISPLAY_FITIMAGE)
00550     {
00551         // compute stretch to fit settings
00552         setToFit();
00553     }
00554     else // if (displayMode == IV_DISPLAY_NOCHANGE)
00555     {
00556         // use same settings
00557         limitCurrPos();
00558         limitZoomFactor();
00559     }
00560     return ret;
00561 }
00562 
00563 // Make the image object point to another image source
00564 // If takeOwnership is false then:
00565 //      This object will not own (control) or copy the pixel data
00566 //      (the source image is still controlled by the caller)
00567 // Else if takeOwnership is true then:
00568 //      This object will take ownership (control) of the pixel data
00569 //      (the source image is not (should not be) controlled by the caller anymore)
00570 //      In this case the memory must have been allocated with the new operator (because this class will use the delete operator)
00571 // If numSigBitsPerSample = 0 then the full range is assumed to be significant
00572 // displayMode ... controls the initial display of the image, one of:
00573 //                      IV_DISPLAY_NOCHANGE  ... no change to view settings when displaying a new image
00574 //                      IV_DISPLAY_FITIMAGE  ... fit-image when displaying a new image (other settings remain the same)
00575 //                      IV_DISPLAY_RESET     ... reset settings when displaying a new image (image will be displayed at 1:1 scale with no color map)
00576 // This function does not redraw (call redraw afterwards)
00577 // Returns:
00578 //               0 for OK
00579 //              -1 for invalid color format
00580 int GLImageBox::pointImageTo(void* pSrcPixelData, unsigned long width, unsigned long height, int format, unsigned short numSigBitsPerSample, bool takeOwnership, int displayMode)
00581 {
00582     // Point to image
00583     int ret = _image.pointTo(pSrcPixelData, width, height, format, numSigBitsPerSample, takeOwnership);
00584 
00585     // Set display settings depending on mode
00586     if (displayMode == IV_DISPLAY_RESET)
00587     {
00588         // reset drawing settings (position, scale, colour mapping) if requested
00589         resetDisplay();
00590     }
00591     else if (displayMode == IV_DISPLAY_FITIMAGE)
00592     {
00593         // compute stretch to fit settings
00594         setToFit();
00595     }
00596     else // if (displayMode == IV_DISPLAY_NOCHANGE)
00597     {
00598         // use same settings
00599         limitCurrPos();
00600         limitZoomFactor();
00601     }
00602     return ret;
00603 }
00604 
00605 // Reset display settings
00606 void GLImageBox::resetDisplay()
00607 {
00608     clearColorMap();
00609     setNormal(); // re-draws as well
00610 }
00611 
00612 // Clears the color map
00613 void GLImageBox::clearColorMap()
00614 {
00615     delete [] _pColorMap;
00616     _pColorMap = 0;
00617     _numMapEntries = 0;
00618 }
00619 
00620 // Calculate the number of color map entries to use
00621 int GLImageBox::calcNumColorMapEntries()
00622 {
00623     // Get the maximum number of map entries that the system supports
00624     // Get the number of bits per sample for the image if it exists and compute the number of pixel values
00625     // Return the fewer amount of entries
00626     GLint maxMapEntries;
00627     glGetIntegerv(GL_MAX_PIXEL_MAP_TABLE, &maxMapEntries);
00628     int NumEntries = maxMapEntries;
00629     if (_image.hasValidData() == true)
00630         NumEntries = (int)std::min<double>(pow(2.0, (double)(_image.getNumSigBitsPerSample())), (double)maxMapEntries);
00631     return NumEntries;
00632 }
00633 
00634 // Creates a color map (All red entries come first, then green, then blue, then alpha)
00635 // returns 0 for OK, -1 for memory allocation error
00636 // numRequestedEntries ... requested number of map entries (used if not greater than maximum possible or number of intensity values)
00637 // Initialise ... flag to initialise the map to a linear scale or not
00638 int GLImageBox::createColorMap(int numEntriesReq, bool Initialise)
00639 {
00640     // Get the number of map entries to use
00641     int maxNumEntries = calcNumColorMapEntries();
00642     int numEntries;
00643     if (numEntriesReq <= 0)
00644         numEntries = maxNumEntries;
00645     else
00646         numEntries = std::min<int>(numEntriesReq, maxNumEntries);
00647 
00648     // Clear and re-create the color map if it's not the desired size
00649     if (numEntries != _numMapEntries)
00650     {
00651         clearColorMap();
00652         _numMapEntries = numEntries;
00653 
00654         // Create the color map (RGBA)
00655         try
00656         {
00657             _pColorMap = new float[4 * _numMapEntries];
00658         }
00659         catch(...)
00660         {
00661             clearColorMap();
00662             return -1;
00663         }
00664     }
00665 
00666     // Initialise the color map if requested
00667     // (All red entries come first, then green, then blue, then alpha)
00668     if (Initialise == true)
00669     {
00670         // For each RGB channel
00671         int arrayIndex = 0;
00672         for (int chan = 0; chan < 3; chan++)
00673         {
00674             for (int in = 0; in < _numMapEntries; in++)
00675             {
00676                 _pColorMap[arrayIndex] = (float)in / (float)(_numMapEntries - 1);
00677                 arrayIndex++;
00678             }
00679         }
00680         // For alpha channel
00681         for (int in = 0; in < _numMapEntries; in++)
00682         {
00683             _pColorMap[arrayIndex] = 1.0;
00684             arrayIndex++;
00685         }
00686     }
00687 
00688     return 0;
00689 }
00690 
00691 // Sets a color map RGBA value
00692 // (All red entries come first, then green, then blue, then alpha)
00693 // index ... index of color map RGBA entry
00694 // red ... intensity value for this red entry (range 0 to 1)
00695 // green ... intensity value for this green entry (range 0 to 1)
00696 // blue ... intensity value for this blue entry (range 0 to 1)
00697 // alpha ... value for this alpha entry (range 0 to 1)
00698 int GLImageBox::setColorMapRGBAValue(int index, float red, float green, float blue, float alpha)
00699 {
00700     if ((index < 0) || (index >= _numMapEntries) || 
00701         (red < 0.0) || (red > 1.0) || 
00702         (green < 0.0) || (green > 1.0) || 
00703         (blue < 0.0) || (blue > 1.0) || 
00704         (alpha < 0.0) || (alpha > 1.0))
00705         return -1;
00706 
00707     _pColorMap[index] = red;
00708     _pColorMap[_numMapEntries + index] = green;
00709     _pColorMap[_numMapEntries * 2 + index] = blue;
00710     _pColorMap[_numMapEntries * 3 + index] = alpha;
00711     return 0;
00712 }
00713 
00714 // Sets a color map red value
00715 // (All red entries come first, then green, then blue, then alpha)
00716 // index ... index of color map red entry
00717 // value ... intensity value for this red entry (range 0 to 1)
00718 int GLImageBox::setColorMapRedValue(int index, float value)
00719 {
00720     if ((index < 0) || (index >= _numMapEntries) || (value < 0.0) || (value > 1.0))
00721         return -1;
00722 
00723     _pColorMap[index] = value;
00724     return 0;
00725 }
00726 
00727 // Sets a color map green value
00728 // (All red entries come first, then green, then blue, then alpha)
00729 // index ... index of color map green entry
00730 // value ... intensity value for this green entry (range 0 to 1)
00731 int GLImageBox::setColorMapGreenValue(int index, float value)
00732 {
00733     if ((index < 0) || (index >= _numMapEntries) || (value < 0.0) || (value > 1.0))
00734         return -1;
00735 
00736     _pColorMap[_numMapEntries + index] = value;
00737     return 0;
00738 }
00739 
00740 // Sets a color map blue value
00741 // (All red entries come first, then green, then blue, then alpha)
00742 // index ... index of color map blue entry
00743 // value ... intensity value for this blue entry (range 0 to 1)
00744 int GLImageBox::setColorMapBlueValue(int index, float value)
00745 {
00746     if ((index < 0) || (index >= _numMapEntries) || (value < 0.0) || (value > 1.0))
00747         return -1;
00748 
00749     _pColorMap[_numMapEntries * 2 + index] = value;
00750     return 0;
00751 }
00752 
00753 // Sets a color map alpha value
00754 // (All red entries come first, then green, then blue, then alpha)
00755 // index ... index of color map alpha entry
00756 // value ... value for this alpha entry (range 0 to 1)
00757 int GLImageBox::setColorMapAlphaValue(int index, float value)
00758 {
00759     if ((index < 0) || (index >= _numMapEntries) || (value < 0.0) || (value > 1.0))
00760         return -1;
00761 
00762     _pColorMap[_numMapEntries * 3 + index] = value;
00763     return 0;
00764 }
00765 
00766 // Helper function to convert a pixel's value (of a sample) to the color map index (i.e. the map index that will be used for that pixel value)
00767 unsigned int GLImageBox::pixValToMapIndex(double PixVal)
00768 {
00769     if (_pColorMap != NULL)
00770     {
00771         double MaxVal = pow(2.0, _image.getNumBitsPerSample()) - 1.0;
00772         double Scale = (pow(2.0, _image.getNumBitsPerSample()) - 1.0) / (pow(2.0, _image.getNumSigBitsPerSample()) - 1.0);
00773         double PixVal01 = Scale * PixVal / MaxVal;
00774         int numMapEntries = getNumColorMapEntries();
00775         unsigned int MapIndex = (unsigned int)floor(0.5 + PixVal01 * (double)(numMapEntries - 1));
00776         return MapIndex;
00777     }
00778     else
00779     {
00780         return 0;
00781     }
00782 }
00783 
00784 
00785 #include "moc_GLImageBox.cpp"

Generated on Wed Nov 23 19:00:16 2011 for FreeCAD by  doxygen 1.6.1