HistogramInterface Class Reference

#include <histogramInterface.h>

Inheritance diagram for HistogramInterface:
[legend]
Collaboration diagram for HistogramInterface:
[legend]

List of all members.

Signals

void selectedRangeChanged ()

Public Member Functions

 HistogramInterface (QString imageFilename, QWidget *parent=0, const char *name=0)
 Creates layout.
 ~HistogramInterface ()
 Deletes objects.
void setDisplayChannel (DISPLAYED_CHANNEL channel)
 Sets currently displayed channel.
virtual QSize minimumSizeHint () const
void getHistBoundaries (int &lumLeft, int &lumRight, int &redLeft, int &redRight, int &greenLeft, int &greenRight, int &blueLeft, int &blueRight)
 returns histogram boundaries
void resetBoundaries ()
 resets all boundaries

Protected Member Functions

void paintEvent (QPaintEvent *e)
void resizeEvent (QResizeEvent *)
void mousePressEvent (QMouseEvent *e)
void mouseReleaseEvent (QMouseEvent *)
void mouseMoveEvent (QMouseEvent *e)

Private Slots

void selectAll ()

Private Member Functions

void getSelectedRange (int &left, int &right)
 this utility function finds currently selected range
double displayToIndex (int val)
 convert screen coordinate to index in 0-255 range
int indexToDisplay (int val)
 converts index in 0-255 ranges to screen coordinate
bool nearBoundary (QPoint p)
 determines if mouse is near boundary

Private Attributes

DISPLAYED_CHANNEL displayedChannel
 Currently displayed channel.
int redVals [256]
 color and luminosity histograms
int greenVals [256]
int blueVals [256]
int grayVals [256]
int maxRcount
 max r,g,b, and gray counts
int maxGcount
int maxBcount
int maxGRAYcount
int lumClick
 left and right bounds for each channel
int lumDrag
int redClick
int redDrag
int greenClick
int greenDrag
int blueClick
int blueDrag
QSize origImageSize
 original image dimensions, needed for painting
DRAG_MODE dragMode
 effect of mouse drags
DRAG_MODE currentMouseShape
 current mouse shape.

Detailed Description

Definition at line 40 of file histogramInterface.h.


Constructor & Destructor Documentation

HistogramInterface::HistogramInterface ( QString  imageFilename,
QWidget parent = 0,
const char *  name = 0 
)

Creates layout.

add keybinding for selecting entire range

Definition at line 36 of file histogramInterface.cpp.

References blueVals, CROSS_CURSOR, currentMouseShape, displayedChannel, dragMode, getCursor(), getImageSize(), grayVals, greenVals, LUMINOSITY, maxBcount, maxGcount, maxGRAYcount, maxRcount, NO_EFFECT, origImageSize, redVals, resetBoundaries(), scaleImage(), and selectAll().

00037                                                                             : 
00038                                         QWidget (parent, name, WNoAutoErase)
00039 {                     
00040   //set default mode to adjusted image
00041   displayedChannel = LUMINOSITY;
00042   
00043   //record original image width and height
00044   getImageSize( imageFilename, origImageSize );
00045   
00046   //construct histogram for color and luminosity channels
00047   //resize image to current screen size for faster
00048   //scaling during resize events
00049   QRect screenSize = qApp->desktop()->availableGeometry();
00050   QImage image;
00051   scaleImage( imageFilename, image, screenSize.width()/4, screenSize.height()/4 );
00052 
00053   int i;
00054   for(i=0; i<256; i++)
00055   {    
00056     redVals[i] = 0;
00057     greenVals[i] = 0;
00058     blueVals[i] = 0;
00059     grayVals[i] = 0;
00060   }
00061   int x, y;
00062   QRgb* rgb;
00063   uchar* scanLine;
00064   for( y=0; y<image.height(); y++)
00065   {   
00066     scanLine = image.scanLine(y);
00067     for( x=0; x<image.width(); x++)
00068     {
00069       rgb = ((QRgb*)scanLine+x);
00070       redVals[ qRed(*rgb) ]++;
00071       greenVals[ qGreen(*rgb) ]++; 
00072       blueVals[ qBlue(*rgb) ]++;
00073       grayVals[ qGray(*rgb) ]++;
00074     } //x
00075   } //y
00076   
00077   //find max r,g,b, and gray counts
00078   maxRcount = 0;
00079   maxGcount = 0;
00080   maxBcount = 0;
00081   maxGRAYcount = 0;
00082   for(i=0; i<256; i++)
00083   {
00084     if(redVals[i]   > maxRcount)    maxRcount    = redVals[i]; 
00085     if(greenVals[i] > maxGcount)    maxGcount    = greenVals[i]; 
00086     if(blueVals[i]  > maxBcount)    maxBcount    = blueVals[i]; 
00087     if(grayVals[i]  > maxGRAYcount) maxGRAYcount = grayVals[i]; 
00088   }
00089   //----          
00090   //by default mouse drags have no effect
00091   dragMode = NO_EFFECT;
00092   currentMouseShape = NO_EFFECT;
00093 
00094   //watch mouse movements in order to drag selection
00095   setMouseTracking(true);
00096   
00097   //accept focus when clicked on
00098   setFocusPolicy( QWidget::ClickFocus );  
00099 
00101   QAccel *keyAccel = new QAccel( this );
00102   keyAccel->connectItem( keyAccel->insertItem( CTRL + Key_A),
00103                          this, SLOT(selectAll()) );  
00104   
00105   //default cursor is cross hair indication regions can be selected
00106   setCursor( getCursor(CROSS_CURSOR) );
00107   
00108   //by default entire range is selected for all channels
00109   resetBoundaries();
00110 }

HistogramInterface::~HistogramInterface (  ) 

Deletes objects.

Definition at line 112 of file histogramInterface.cpp.

00112 { }


Member Function Documentation

double HistogramInterface::displayToIndex ( int  val  )  [private]

convert screen coordinate to index in 0-255 range

Definition at line 145 of file histogramInterface.cpp.

References width.

Referenced by mouseMoveEvent(), mousePressEvent(), nearBoundary(), and paintEvent().

00146 {
00147   return (255.0*coordinate) / ( width()-1 );
00148 }

void HistogramInterface::getHistBoundaries ( int &  lumLeft,
int &  lumRight,
int &  redLeft,
int &  redRight,
int &  greenLeft,
int &  greenRight,
int &  blueLeft,
int &  blueRight 
)

returns histogram boundaries

Definition at line 434 of file histogramInterface.cpp.

References blueClick, blueDrag, greenClick, greenDrag, lumClick, lumDrag, redClick, and redDrag.

Referenced by HistogramEditor::adjustImage(), HistogramEditor::applyAction(), and HistogramEditor::getHistBoundaries().

00438 {
00439   lumLeft = QMIN( lumClick, lumDrag );
00440   lumRight = QMAX( lumClick, lumDrag );
00441 
00442   redLeft = QMIN( redClick, redDrag );
00443   redRight = QMAX( redClick, redDrag );
00444 
00445   greenLeft = QMIN( greenClick, greenDrag );
00446   greenRight = QMAX( greenClick, greenDrag );
00447 
00448   blueLeft = QMIN( blueClick, blueDrag );
00449   blueRight = QMAX( blueClick, blueDrag );
00450 }

void HistogramInterface::getSelectedRange ( int &  left,
int &  right 
) [private]

this utility function finds currently selected range

Definition at line 119 of file histogramInterface.cpp.

References BLUE, blueClick, blueDrag, displayedChannel, GREEN, greenClick, greenDrag, lumClick, lumDrag, LUMINOSITY, RED, redClick, and redDrag.

Referenced by mouseMoveEvent(), mousePressEvent(), nearBoundary(), paintEvent(), and selectAll().

00120 {
00121   if(displayedChannel == LUMINOSITY) 
00122   {
00123     left = QMIN( lumClick, lumDrag );
00124     right = QMAX( lumClick, lumDrag );
00125   }
00126   else if(displayedChannel == RED)   
00127   { 
00128     left = QMIN( redClick, redDrag );
00129     right = QMAX( redClick, redDrag );
00130   }
00131   else if(displayedChannel == GREEN) 
00132   { 
00133     left = QMIN( greenClick, greenDrag );
00134     right = QMAX( greenClick, greenDrag );
00135   }
00136   else if(displayedChannel == BLUE)  
00137   { 
00138     left = QMIN( blueClick, blueDrag );
00139     right = QMAX( blueClick, blueDrag );
00140   }   
00141   else
00142   { left = 0; right = 0; }
00143 }

int HistogramInterface::indexToDisplay ( int  val  )  [private]

converts index in 0-255 ranges to screen coordinate

Definition at line 150 of file histogramInterface.cpp.

References width.

Referenced by paintEvent().

00151 {
00152   return (index* (width()-1) ) / 255;
00153 }

QSize HistogramInterface::minimumSizeHint (  )  const [virtual]

Definition at line 286 of file histogramInterface.cpp.

References COLOR_BAR_BORDER, COLOR_BAR_HEIGHT, and COLOR_BAR_MARGIN.

00287 {
00288   return QSize( 256,100 + COLOR_BAR_MARGIN + 2*COLOR_BAR_BORDER + COLOR_BAR_HEIGHT );
00289 }

void HistogramInterface::mouseMoveEvent ( QMouseEvent *  e  )  [protected]

Definition at line 368 of file histogramInterface.cpp.

References BLUE, blueDrag, CROSS_CURSOR, currentMouseShape, displayedChannel, displayToIndex(), DRAG, dragMode, getCursor(), getSelectedRange(), GREEN, greenDrag, lumDrag, LUMINOSITY, MOVE_HOR_CURSOR, nearBoundary(), NO_EFFECT, RED, redDrag, selectedRangeChanged(), and width.

00369 {
00370   //if not dragging a selection then update mouse cursor as appropriate
00371   if(dragMode == NO_EFFECT)
00372   {
00373     if( nearBoundary(e->pos()) && currentMouseShape == NO_EFFECT )
00374     {
00375       currentMouseShape = DRAG;
00376       setCursor( getCursor(MOVE_HOR_CURSOR) );
00377     }
00378     else if( !nearBoundary(e->pos()) && currentMouseShape == DRAG )
00379     { 
00380       currentMouseShape = NO_EFFECT;
00381       setCursor( getCursor(CROSS_CURSOR) );
00382     }
00383 
00384     return;
00385   }
00386   
00387   //compute index in 0-255 range from mouse coordinates
00388   int x = QMAX( QMIN( e->pos().x(), width()-1 ), 0 );
00389   int index = (int) displayToIndex( x );
00390 
00391   //reset boundary
00392   if(displayedChannel == LUMINOSITY) { lumDrag = index; }
00393   else if(displayedChannel == RED)   { redDrag = index; }
00394   else if(displayedChannel == GREEN) { greenDrag = index; }
00395   else if(displayedChannel == BLUE)  { blueDrag = index; }          
00396   
00397   //repaint
00398   repaint(false);  
00399   
00400   //emit selectection changed signal
00401   int left, right;
00402   getSelectedRange( left, right );
00403   emit selectedRangeChanged();    
00404 }

void HistogramInterface::mousePressEvent ( QMouseEvent *  e  )  [protected]

Definition at line 307 of file histogramInterface.cpp.

References blueClick, blueDrag, displayedChannel, displayToIndex(), DRAG, DRAG_THRESHOLD, dragMode, getSelectedRange(), GREEN, greenClick, greenDrag, lumClick, lumDrag, LUMINOSITY, RED, redClick, redDrag, and selectedRangeChanged().

00308 {
00309   //begin drag mode!
00310   dragMode = DRAG;
00311 
00312   //compute index from mouse position
00313   int index = (int) displayToIndex( e->pos().x() );
00314       
00315   //get left and right to check for clicks near current boundaries
00316   int left, right;
00317   getSelectedRange( left, right );
00318 
00319   //get click and drag handles
00320   int *click, *drag;
00321   if(displayedChannel == LUMINOSITY) 
00322   { 
00323     click = &lumClick; drag = &lumDrag; 
00324   }
00325   else if(displayedChannel == RED)   
00326   { 
00327     click = &redClick; drag = &redDrag; 
00328   }
00329   else if(displayedChannel == GREEN) 
00330   { 
00331     click = &greenClick; drag = &greenDrag; 
00332   }
00333   else
00334   { 
00335     click = &blueClick; drag = &blueDrag; 
00336   }
00337     
00338   //if within threshold of left then start dragging that side
00339   if( index < left + DRAG_THRESHOLD &&
00340       index > left - DRAG_THRESHOLD )
00341   {
00342     *click = right;
00343     *drag = left;
00344     return;
00345   }
00346   //if within threshold of left then start dragging that side
00347   if( index < right + DRAG_THRESHOLD &&
00348       index > right - DRAG_THRESHOLD )
00349   {
00350     *click = left;
00351     *drag = right;
00352     return;
00353   }
00354   //else begin new drag
00355   else
00356   {
00357     *click = index;
00358     *drag = index;
00359     repaint(false);
00360 
00361     //emit selectection changed signal
00362     int left, right;
00363     getSelectedRange( left, right );
00364     emit selectedRangeChanged();    
00365   }
00366 }

void HistogramInterface::mouseReleaseEvent ( QMouseEvent *  e  )  [protected]

Definition at line 406 of file histogramInterface.cpp.

References CROSS_CURSOR, currentMouseShape, DRAG, dragMode, getCursor(), nearBoundary(), and NO_EFFECT.

00407 {
00408   //set mouse drags to no longer have any effect on boundary
00409   dragMode = NO_EFFECT;
00410 
00411   //update mouse cursor if necessary
00412   if( !nearBoundary(e->pos()) && currentMouseShape == DRAG )
00413   { 
00414     currentMouseShape = NO_EFFECT;
00415     setCursor( getCursor(CROSS_CURSOR) );
00416   }    
00417 }

bool HistogramInterface::nearBoundary ( QPoint  p  )  [private]

determines if mouse is near boundary

Definition at line 291 of file histogramInterface.cpp.

References displayToIndex(), DRAG_THRESHOLD, and getSelectedRange().

Referenced by mouseMoveEvent(), and mouseReleaseEvent().

00292 {
00293   //compute index from mouse position
00294   int index = (int) displayToIndex( p.x() );
00295   
00296   //get left and right to check for clicks near current boundaries
00297   int left, right;
00298   getSelectedRange( left, right );
00299 
00300   //check if within threshold of left or right boundaries
00301   return ( (index < left + 1 + DRAG_THRESHOLD &&
00302             index > left -     DRAG_THRESHOLD) ||
00303            (index < right + DRAG_THRESHOLD &&
00304             index > right - 1 - DRAG_THRESHOLD) );
00305 }

void HistogramInterface::paintEvent ( QPaintEvent *  e  )  [protected]

Definition at line 155 of file histogramInterface.cpp.

References b, BLUE, blueVals, buffer, COLOR_BAR_BORDER, COLOR_BAR_HEIGHT, COLOR_BAR_MARGIN, displayedChannel, displayToIndex(), getSelectedRange(), grayVals, GREEN, greenVals, HISTOGRAM_HEIGHT, indexToDisplay(), maxBcount, maxGcount, maxGRAYcount, maxRcount, RED, redVals, and width.

00156 { 
00157   //create buffer to draw in
00158   QPixmap buffer( size() );
00159   buffer.fill( white );
00160   
00161   //create a painter pointing to the buffer
00162   QPainter bufferPainter( &buffer );
00163   
00164   //turn off clipping to make painting operations faster
00165   bufferPainter.setClipping(false);
00166 
00167   //initialize buffer with background brush
00168   bufferPainter.fillRect( buffer.rect(), backgroundBrush() );
00169 
00170   //get handle on histogram data, get max count, set default draw color, and find
00171   //left and right boundaries of current selection  
00172   QColor color = black;
00173   int* data = grayVals;
00174   int maxCount = maxGRAYcount;
00175 
00176   if(displayedChannel == RED)        { data = redVals;   color = red;   maxCount = maxRcount; }
00177   else if(displayedChannel == GREEN) { data = greenVals; color = green; maxCount = maxGcount; }
00178   else if(displayedChannel == BLUE)  { data = blueVals;  color = blue;  maxCount = maxBcount; }
00179   
00180   int indexLeft, indexRight;
00181   getSelectedRange(indexLeft,indexRight);
00182   int displayLeft = indexToDisplay ( indexLeft );
00183   int displayRight = indexToDisplay ( indexRight );  
00184 
00185   int histogramHeight = HISTOGRAM_HEIGHT;
00186   
00187   //iterate over each pixel column
00188   int x;
00189   for(x=0; x<width(); x++)
00190   {    
00191     double index = displayToIndex( x );
00192     int indexL = (int)index;
00193     double scaleR = index - indexL;
00194     
00195     int h = 0;
00196     if(indexL < 255)
00197     { 
00198       h = (int) ((1-scaleR)*data[indexL] + scaleR*data[indexL+1]); 
00199     }
00200     else 
00201     { 
00202       h = data[255]; 
00203     }
00204 
00205     //scale count so that the maxCount maps to the maximum height
00206     double scaledH = (histogramHeight*h)/maxCount;
00207     h = (int) scaledH;    
00208     //round up values between 0 and 1 so show data is there
00209     if( h == 0 && scaledH > h) h++;
00210     
00211     if(h > 0)
00212     {
00213       //use a gray color outside selected range
00214       QColor usedColor = color;
00215       if(x < displayLeft || x > displayRight) { usedColor = gray; }
00216         
00217       bufferPainter.fillRect( QRect(x, histogramHeight - h, 
00218                                     1, h),
00219                               QBrush(usedColor) );    
00220     }
00221     
00222     //if this is left or right boundary of selection and entire range not selected then
00223     //draw a vertical black line to make it stand out more
00224     if( (x == displayLeft || x == displayLeft+1 ||
00225          x == displayRight || x == displayRight-1) )
00226     {
00227       bufferPainter.drawLine( x, 0, x, histogramHeight-1 );
00228     }
00229   }
00230   //----
00231   //paint color bar key below
00232   
00233   //first a black border
00234   bufferPainter.fillRect( QRect(0, histogramHeight + COLOR_BAR_MARGIN, 
00235                                 width(), COLOR_BAR_HEIGHT+2*COLOR_BAR_BORDER),
00236                           QBrush(black) );    
00237 
00238   //next the color gradient
00239   QColor scaledColor;
00240   for(x=COLOR_BAR_BORDER; x < width()-COLOR_BAR_BORDER; x++)
00241   {    
00242     int index;
00243     if(x <= displayLeft )
00244       index = 0;
00245     else if(x >= displayRight)
00246       index = 255;
00247     else
00248       index = (int) (255.0*(x-displayLeft))/(displayRight - displayLeft);
00249   
00250     int r = color.red();
00251     int g = color.green();
00252     int b = color.blue();
00253     
00254     if( r != 0) r = index;
00255     if( g != 0) g = index;
00256     if( b != 0) b = index;
00257     
00258     //black color was used when adjusting luminance, scale to white instead (since black is 0)
00259     if( color == black )
00260     { r = g = b = index; }
00261 
00262     scaledColor.setRgb( r,g,b );
00263     bufferPainter.fillRect( QRect(x, histogramHeight + COLOR_BAR_MARGIN + COLOR_BAR_BORDER, 
00264                                   1, COLOR_BAR_HEIGHT),
00265                             QBrush(scaledColor) );    
00266   }    
00267     
00268   //end painter  
00269   bufferPainter.end();
00270   
00271   //blit buffer to screen
00272   bitBlt( this,
00273           e->rect().x(), e->rect().y(),
00274           &buffer, 
00275           e->rect().x(), e->rect().y(),
00276           e->rect().width(), e->rect().height() );
00277 }

void HistogramInterface::resetBoundaries (  ) 

resets all boundaries

Definition at line 452 of file histogramInterface.cpp.

References blueClick, blueDrag, greenClick, greenDrag, lumClick, lumDrag, redClick, redDrag, and selectedRangeChanged().

Referenced by HistogramInterface(), and HistogramEditor::resetAction().

00453 {
00454   lumClick = redClick = greenClick = blueClick = 0; 
00455   lumDrag = redDrag = greenDrag = blueDrag = 255;  
00456   repaint(false);
00457   emit selectedRangeChanged();    
00458 }

void HistogramInterface::resizeEvent ( QResizeEvent *   )  [protected]

Definition at line 114 of file histogramInterface.cpp.

00115 {  
00116   repaint(false);
00117 }

void HistogramInterface::selectAll (  )  [private, slot]

Definition at line 419 of file histogramInterface.cpp.

References BLUE, blueClick, blueDrag, displayedChannel, getSelectedRange(), GREEN, greenClick, greenDrag, lumClick, lumDrag, LUMINOSITY, RED, redClick, redDrag, and selectedRangeChanged().

Referenced by HistogramInterface().

00420 {
00421   //reset boundary
00422   if(displayedChannel == LUMINOSITY) { lumClick = 0,   lumDrag = 255;   }
00423   else if(displayedChannel == RED)   { redClick = 0;   redDrag = 255;   }
00424   else if(displayedChannel == GREEN) { greenClick = 0; greenDrag = 255; }
00425   else if(displayedChannel == BLUE)  { blueClick = 0;  blueDrag = 255;  } 
00426   repaint(false);  
00427 
00428   //emit selectection changed signal
00429   int left, right;
00430   getSelectedRange( left, right );
00431   emit selectedRangeChanged();    
00432 }

void HistogramInterface::selectedRangeChanged (  )  [signal]
void HistogramInterface::setDisplayChannel ( DISPLAYED_CHANNEL  channel  ) 

Sets currently displayed channel.

Definition at line 279 of file histogramInterface.cpp.

References displayedChannel.

Referenced by HistogramEditor::selectHistogramType().

00280 {
00281   //set mode and repaint
00282   displayedChannel = channel;
00283   repaint(false);
00284 }


Member Data Documentation

int HistogramInterface::blueVals[256] [private]

Definition at line 100 of file histogramInterface.h.

Referenced by HistogramInterface(), and paintEvent().

current mouse shape.

by caching this value we avoid resetting the mouse cursor every time it moves etc.

Definition at line 120 of file histogramInterface.h.

Referenced by HistogramInterface(), mouseMoveEvent(), and mouseReleaseEvent().

Currently displayed channel.

Definition at line 95 of file histogramInterface.h.

Referenced by getSelectedRange(), HistogramInterface(), mouseMoveEvent(), mousePressEvent(), paintEvent(), selectAll(), and setDisplayChannel().

effect of mouse drags

Definition at line 116 of file histogramInterface.h.

Referenced by HistogramInterface(), mouseMoveEvent(), mousePressEvent(), and mouseReleaseEvent().

int HistogramInterface::grayVals[256] [private]

Definition at line 101 of file histogramInterface.h.

Referenced by HistogramInterface(), and paintEvent().

int HistogramInterface::greenVals[256] [private]

Definition at line 99 of file histogramInterface.h.

Referenced by HistogramInterface(), and paintEvent().

left and right bounds for each channel

Definition at line 107 of file histogramInterface.h.

Referenced by getHistBoundaries(), getSelectedRange(), mousePressEvent(), resetBoundaries(), and selectAll().

Definition at line 104 of file histogramInterface.h.

Referenced by HistogramInterface(), and paintEvent().

Definition at line 104 of file histogramInterface.h.

Referenced by HistogramInterface(), and paintEvent().

Definition at line 104 of file histogramInterface.h.

Referenced by HistogramInterface(), and paintEvent().

max r,g,b, and gray counts

Definition at line 104 of file histogramInterface.h.

Referenced by HistogramInterface(), and paintEvent().

original image dimensions, needed for painting

Definition at line 113 of file histogramInterface.h.

Referenced by HistogramInterface().

int HistogramInterface::redVals[256] [private]

color and luminosity histograms

Definition at line 98 of file histogramInterface.h.

Referenced by HistogramInterface(), and paintEvent().


The documentation for this class was generated from the following files:
Generated on Sun Dec 5 14:44:57 2010 for AlbumShaper by  doxygen 1.6.3