AlbumShaper  1.0a3
Signals | Public Member Functions | Protected Member Functions | Private Slots | Private Member Functions | Private Attributes
HistogramInterface Class Reference

#include <histogramInterface.h>

Inheritance diagram for HistogramInterface:
Inheritance graph
[legend]
Collaboration diagram for HistogramInterface:
Collaboration graph
[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().

                                                                            : 
                                        QWidget (parent, name, WNoAutoErase)
{                     
  //set default mode to adjusted image
  displayedChannel = LUMINOSITY;
  
  //record original image width and height
  getImageSize( imageFilename, origImageSize );
  
  //construct histogram for color and luminosity channels
  //resize image to current screen size for faster
  //scaling during resize events
  QRect screenSize = qApp->desktop()->availableGeometry();
  QImage image;
  scaleImage( imageFilename, image, screenSize.width()/4, screenSize.height()/4 );

  int i;
  for(i=0; i<256; i++)
  {    
    redVals[i] = 0;
    greenVals[i] = 0;
    blueVals[i] = 0;
    grayVals[i] = 0;
  }
  int x, y;
  QRgb* rgb;
  uchar* scanLine;
  for( y=0; y<image.height(); y++)
  {   
    scanLine = image.scanLine(y);
    for( x=0; x<image.width(); x++)
    {
      rgb = ((QRgb*)scanLine+x);
      redVals[ qRed(*rgb) ]++;
      greenVals[ qGreen(*rgb) ]++; 
      blueVals[ qBlue(*rgb) ]++;
      grayVals[ qGray(*rgb) ]++;
    } //x
  } //y
  
  //find max r,g,b, and gray counts
  maxRcount = 0;
  maxGcount = 0;
  maxBcount = 0;
  maxGRAYcount = 0;
  for(i=0; i<256; i++)
  {
    if(redVals[i]   > maxRcount)    maxRcount    = redVals[i]; 
    if(greenVals[i] > maxGcount)    maxGcount    = greenVals[i]; 
    if(blueVals[i]  > maxBcount)    maxBcount    = blueVals[i]; 
    if(grayVals[i]  > maxGRAYcount) maxGRAYcount = grayVals[i]; 
  }
  //----          
  //by default mouse drags have no effect
  dragMode = NO_EFFECT;
  currentMouseShape = NO_EFFECT;

  //watch mouse movements in order to drag selection
  setMouseTracking(true);
  
  //accept focus when clicked on
  setFocusPolicy( QWidget::ClickFocus );  

  QAccel *keyAccel = new QAccel( this );
  keyAccel->connectItem( keyAccel->insertItem( CTRL + Key_A),
                         this, SLOT(selectAll()) );  
  
  //default cursor is cross hair indication regions can be selected
  setCursor( getCursor(CROSS_CURSOR) );
  
  //by default entire range is selected for all channels
  resetBoundaries();
}
HistogramInterface::~HistogramInterface ( )

Deletes objects.

Definition at line 112 of file histogramInterface.cpp.

{ }

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().

{
  return (255.0*coordinate) / ( width()-1 );
}
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().

{
  lumLeft = QMIN( lumClick, lumDrag );
  lumRight = QMAX( lumClick, lumDrag );

  redLeft = QMIN( redClick, redDrag );
  redRight = QMAX( redClick, redDrag );

  greenLeft = QMIN( greenClick, greenDrag );
  greenRight = QMAX( greenClick, greenDrag );

  blueLeft = QMIN( blueClick, blueDrag );
  blueRight = QMAX( blueClick, blueDrag );
}
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().

{
  if(displayedChannel == LUMINOSITY) 
  {
    left = QMIN( lumClick, lumDrag );
    right = QMAX( lumClick, lumDrag );
  }
  else if(displayedChannel == RED)   
  { 
    left = QMIN( redClick, redDrag );
    right = QMAX( redClick, redDrag );
  }
  else if(displayedChannel == GREEN) 
  { 
    left = QMIN( greenClick, greenDrag );
    right = QMAX( greenClick, greenDrag );
  }
  else if(displayedChannel == BLUE)  
  { 
    left = QMIN( blueClick, blueDrag );
    right = QMAX( blueClick, blueDrag );
  }   
  else
  { left = 0; right = 0; }
}
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().

{
  return (index* (width()-1) ) / 255;
}
QSize HistogramInterface::minimumSizeHint ( ) const [virtual]

Definition at line 286 of file histogramInterface.cpp.

References COLOR_BAR_BORDER, COLOR_BAR_HEIGHT, and COLOR_BAR_MARGIN.

{
  return QSize( 256,100 + COLOR_BAR_MARGIN + 2*COLOR_BAR_BORDER + COLOR_BAR_HEIGHT );
}
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.

{
  //if not dragging a selection then update mouse cursor as appropriate
  if(dragMode == NO_EFFECT)
  {
    if( nearBoundary(e->pos()) && currentMouseShape == NO_EFFECT )
    {
      currentMouseShape = DRAG;
      setCursor( getCursor(MOVE_HOR_CURSOR) );
    }
    else if( !nearBoundary(e->pos()) && currentMouseShape == DRAG )
    { 
      currentMouseShape = NO_EFFECT;
      setCursor( getCursor(CROSS_CURSOR) );
    }

    return;
  }
  
  //compute index in 0-255 range from mouse coordinates
  int x = QMAX( QMIN( e->pos().x(), width()-1 ), 0 );
  int index = (int) displayToIndex( x );

  //reset boundary
  if(displayedChannel == LUMINOSITY) { lumDrag = index; }
  else if(displayedChannel == RED)   { redDrag = index; }
  else if(displayedChannel == GREEN) { greenDrag = index; }
  else if(displayedChannel == BLUE)  { blueDrag = index; }          
  
  //repaint
  repaint(false);  
  
  //emit selectection changed signal
  int left, right;
  getSelectedRange( left, right );
  emit selectedRangeChanged();    
}
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().

{
  //begin drag mode!
  dragMode = DRAG;

  //compute index from mouse position
  int index = (int) displayToIndex( e->pos().x() );
      
  //get left and right to check for clicks near current boundaries
  int left, right;
  getSelectedRange( left, right );

  //get click and drag handles
  int *click, *drag;
  if(displayedChannel == LUMINOSITY) 
  { 
    click = &lumClick; drag = &lumDrag; 
  }
  else if(displayedChannel == RED)   
  { 
    click = &redClick; drag = &redDrag; 
  }
  else if(displayedChannel == GREEN) 
  { 
    click = &greenClick; drag = &greenDrag; 
  }
  else
  { 
    click = &blueClick; drag = &blueDrag; 
  }
    
  //if within threshold of left then start dragging that side
  if( index < left + DRAG_THRESHOLD &&
      index > left - DRAG_THRESHOLD )
  {
    *click = right;
    *drag = left;
    return;
  }
  //if within threshold of left then start dragging that side
  if( index < right + DRAG_THRESHOLD &&
      index > right - DRAG_THRESHOLD )
  {
    *click = left;
    *drag = right;
    return;
  }
  //else begin new drag
  else
  {
    *click = index;
    *drag = index;
    repaint(false);

    //emit selectection changed signal
    int left, right;
    getSelectedRange( left, right );
    emit selectedRangeChanged();    
  }
}
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.

{
  //set mouse drags to no longer have any effect on boundary
  dragMode = NO_EFFECT;

  //update mouse cursor if necessary
  if( !nearBoundary(e->pos()) && currentMouseShape == DRAG )
  { 
    currentMouseShape = NO_EFFECT;
    setCursor( getCursor(CROSS_CURSOR) );
  }    
}
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().

{
  //compute index from mouse position
  int index = (int) displayToIndex( p.x() );
  
  //get left and right to check for clicks near current boundaries
  int left, right;
  getSelectedRange( left, right );

  //check if within threshold of left or right boundaries
  return ( (index < left + 1 + DRAG_THRESHOLD &&
            index > left -     DRAG_THRESHOLD) ||
           (index < right + DRAG_THRESHOLD &&
            index > right - 1 - DRAG_THRESHOLD) );
}
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.

{ 
  //create buffer to draw in
  QPixmap buffer( size() );
  buffer.fill( white );
  
  //create a painter pointing to the buffer
  QPainter bufferPainter( &buffer );
  
  //turn off clipping to make painting operations faster
  bufferPainter.setClipping(false);

  //initialize buffer with background brush
  bufferPainter.fillRect( buffer.rect(), backgroundBrush() );

  //get handle on histogram data, get max count, set default draw color, and find
  //left and right boundaries of current selection  
  QColor color = black;
  int* data = grayVals;
  int maxCount = maxGRAYcount;

  if(displayedChannel == RED)        { data = redVals;   color = red;   maxCount = maxRcount; }
  else if(displayedChannel == GREEN) { data = greenVals; color = green; maxCount = maxGcount; }
  else if(displayedChannel == BLUE)  { data = blueVals;  color = blue;  maxCount = maxBcount; }
  
  int indexLeft, indexRight;
  getSelectedRange(indexLeft,indexRight);
  int displayLeft = indexToDisplay ( indexLeft );
  int displayRight = indexToDisplay ( indexRight );  

  int histogramHeight = HISTOGRAM_HEIGHT;
  
  //iterate over each pixel column
  int x;
  for(x=0; x<width(); x++)
  {    
    double index = displayToIndex( x );
    int indexL = (int)index;
    double scaleR = index - indexL;
    
    int h = 0;
    if(indexL < 255)
    { 
      h = (int) ((1-scaleR)*data[indexL] + scaleR*data[indexL+1]); 
    }
    else 
    { 
      h = data[255]; 
    }

    //scale count so that the maxCount maps to the maximum height
    double scaledH = (histogramHeight*h)/maxCount;
    h = (int) scaledH;    
    //round up values between 0 and 1 so show data is there
    if( h == 0 && scaledH > h) h++;
    
    if(h > 0)
    {
      //use a gray color outside selected range
      QColor usedColor = color;
      if(x < displayLeft || x > displayRight) { usedColor = gray; }
        
      bufferPainter.fillRect( QRect(x, histogramHeight - h, 
                                    1, h),
                              QBrush(usedColor) );    
    }
    
    //if this is left or right boundary of selection and entire range not selected then
    //draw a vertical black line to make it stand out more
    if( (x == displayLeft || x == displayLeft+1 ||
         x == displayRight || x == displayRight-1) )
    {
      bufferPainter.drawLine( x, 0, x, histogramHeight-1 );
    }
  }
  //----
  //paint color bar key below
  
  //first a black border
  bufferPainter.fillRect( QRect(0, histogramHeight + COLOR_BAR_MARGIN, 
                                width(), COLOR_BAR_HEIGHT+2*COLOR_BAR_BORDER),
                          QBrush(black) );    

  //next the color gradient
  QColor scaledColor;
  for(x=COLOR_BAR_BORDER; x < width()-COLOR_BAR_BORDER; x++)
  {    
    int index;
    if(x <= displayLeft )
      index = 0;
    else if(x >= displayRight)
      index = 255;
    else
      index = (int) (255.0*(x-displayLeft))/(displayRight - displayLeft);
  
    int r = color.red();
    int g = color.green();
    int b = color.blue();
    
    if( r != 0) r = index;
    if( g != 0) g = index;
    if( b != 0) b = index;
    
    //black color was used when adjusting luminance, scale to white instead (since black is 0)
    if( color == black )
    { r = g = b = index; }

    scaledColor.setRgb( r,g,b );
    bufferPainter.fillRect( QRect(x, histogramHeight + COLOR_BAR_MARGIN + COLOR_BAR_BORDER, 
                                  1, COLOR_BAR_HEIGHT),
                            QBrush(scaledColor) );    
  }    
    
  //end painter  
  bufferPainter.end();
  
  //blit buffer to screen
  bitBlt( this,
          e->rect().x(), e->rect().y(),
          &buffer, 
          e->rect().x(), e->rect().y(),
          e->rect().width(), e->rect().height() );
}
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().

{
  lumClick = redClick = greenClick = blueClick = 0; 
  lumDrag = redDrag = greenDrag = blueDrag = 255;  
  repaint(false);
  emit selectedRangeChanged();    
}
void HistogramInterface::resizeEvent ( QResizeEvent *  ) [protected]

Definition at line 114 of file histogramInterface.cpp.

{  
  repaint(false);
}
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().

{
  //reset boundary
  if(displayedChannel == LUMINOSITY) { lumClick = 0,   lumDrag = 255;   }
  else if(displayedChannel == RED)   { redClick = 0;   redDrag = 255;   }
  else if(displayedChannel == GREEN) { greenClick = 0; greenDrag = 255; }
  else if(displayedChannel == BLUE)  { blueClick = 0;  blueDrag = 255;  } 
  repaint(false);  

  //emit selectection changed signal
  int left, right;
  getSelectedRange( left, right );
  emit selectedRangeChanged();    
}
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().

{
  //set mode and repaint
  displayedChannel = channel;
  repaint(false);
}

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: