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

Interface for adjusting image historgram using upper and lower bounds and bright and contrast controls. More...

#include <histogramEditor.h>

Inheritance diagram for HistogramEditor:
Inheritance graph
[legend]
Collaboration diagram for HistogramEditor:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 HistogramEditor (QString filename, QWidget *parent=0, const char *name=0)
 Constructs layout.
 ~HistogramEditor ()
QImage * getModifiedImage ()
 get modified image that resulted from adjustments
void getHistBoundaries (int &lumLeft, int &lumRight, int &redLeft, int &redRight, int &greenLeft, int &greenRight, int &blueLeft, int &blueRight)
 returns histogram boundaries

Protected Member Functions

void keyPressEvent (QKeyEvent *e)
void keyReleaseEvent (QKeyEvent *e)

Private Slots

void selectPreviewImageType (int selection)
 updates preview image
void selectHistogramType (int selection)
 updates historgram interface
void resetBrightness ()
 reset brightness
void resetContrast ()
 reset contrast
void applyAction ()
 check for changes to settings, if so
void resetAction ()
 resets all adjustments
void generateAdjustedPreviewImage ()
 updates adjusted preview image

Private Member Functions

void adjustImage (QImage &image)
double scaleColor (double color, int left, int right)

Private Attributes

QString fileName
double meanR
 Mean color values.
double meanG
double meanB
ScaledPreviewInterfacepreviewInterface
 Preview image.
HistogramInterfacehistogramInterface
 Histogram view.
QComboBox * previewSelection
QComboBox * histogramType
ClickableLabelbrightnessIcon
ClickableLabelcontrastIcon
QFramebuttonsFrame
DynamicSliderbrightness
 Brightness slider.
DynamicSlidercontrast
 Contrast slider.

Detailed Description

Interface for adjusting image historgram using upper and lower bounds and bright and contrast controls.

Definition at line 31 of file histogramEditor.h.


Constructor & Destructor Documentation

HistogramEditor::HistogramEditor ( QString  filename,
QWidget parent = 0,
const char *  name = 0 
)

Constructs layout.

Definition at line 33 of file histogramEditor.cpp.

References applyAction(), b, brightness, brightnessIcon, buttonsFrame, contrast, contrastIcon, fileName, generateAdjustedPreviewImage(), histogramInterface, histogramType, IMAGE_PATH, meanB, meanG, meanR, previewInterface, previewSelection, resetAction(), resetBrightness(), resetContrast(), selectHistogramType(), selectPreviewImageType(), ClickableLabel::setPixmap(), DynamicSlider::setPrefixes(), DynamicSlider::setZeroString(), SLIDER_RADIUS, and WIDGET_SPACING.

                                                                                      : QDialog(parent,name,true)
{
  //set pointer to null to make sure no 
  //random data is ever accessed by the preview interface
  histogramInterface = NULL;

  //record filename
  this->fileName = fileName;
  
  //-----
  //find mean color values
  meanR = 0;
  meanG = 0;
  meanB = 0;
  int x, y;
  QRgb* rgb;
  uchar* scanLine;
  QImage image = QImage( fileName );
  for( y=0; y<image.height(); y++)
  {   
    scanLine = image.scanLine(y);
    for( x=0; x<image.width(); x++)
    {
      rgb = ((QRgb*)scanLine+x);
      double r = ((double)qRed(*rgb)   )/255.0;
      double g = ((double)qGreen(*rgb) )/255.0;
      double b = ((double)qBlue(*rgb)  )/255.0;
      
      meanR+=r;
      meanG+=g;
      meanB+=b;
    } //x
  } //y
  meanR = meanR / ( image.width() * image.height() );
  meanG = meanG / ( image.width() * image.height() );
  meanB = meanB / ( image.width() * image.height() );
  
  QFrame* visibleFrame = new QFrame( this, "visible widgets" );
  //--------------  
  //Preview frame: 
  previewInterface = new ScaledPreviewInterface( fileName, visibleFrame, 
                                                 "previewInterface" );
  connect( previewInterface, SIGNAL(resized()), 
           this, SLOT(generateAdjustedPreviewImage()) );  

  previewSelection = new QComboBox( visibleFrame, "previewSelction" );
  previewSelection->insertItem( tr("Split View") );
  previewSelection->insertItem( tr("Original Image") );
  previewSelection->insertItem( tr("Adjusted Image") );
  connect( previewSelection, SIGNAL(activated(int)), this, SLOT(selectPreviewImageType(int)) );  
  //--------------
  //Adjust frame:   
  histogramInterface = new HistogramInterface( fileName, visibleFrame, 
                                               "histogramInterface" );  

  //connect adjustments in histogram to generateAdjustedPreviewImage
  connect( histogramInterface, SIGNAL( selectedRangeChanged() ),
           SLOT( generateAdjustedPreviewImage() ) );
  
  QToolTip::add( histogramInterface, tr("Click and drag to select tonal range") );  

  histogramType = new QComboBox( visibleFrame, "histogramType" );
  histogramType->insertItem( tr("Luminosity") );
  histogramType->insertItem( tr("Red") );
  histogramType->insertItem( tr("Green") );
  histogramType->insertItem( tr("Blue") );  
  connect( histogramType, SIGNAL(activated(int)), this, SLOT(selectHistogramType(int)) );  
  QToolTip::add( histogramType, tr("Histogram channel displayed") );  
  //--------------
  //Slider frame:
  QString noChange = QString( tr("No change") );
  
  brightness = new DynamicSlider( Qt::Vertical, visibleFrame );
  brightness->setZeroString( noChange );
  brightness->setPrefixes("", "+");
  brightness->setMinValue( -SLIDER_RADIUS );
  brightness->setMaxValue( SLIDER_RADIUS );
  connect( brightness, SIGNAL(valueChanged(int)),
           this, SLOT(generateAdjustedPreviewImage()) );;
  QToolTip::add( brightness, tr("Drag to adjust image brightness") );  
           
  brightnessIcon = new ClickableLabel( visibleFrame, "brightnessIcon" );
  brightnessIcon->setPixmap( QPixmap(QString(IMAGE_PATH)+"miscImages/brightness.png") );
  connect( brightnessIcon, SIGNAL(clicked()), SLOT(resetBrightness()) );    
  QToolTip::add( brightnessIcon, tr("Reset brightness") );

  contrast = new DynamicSlider( Qt::Vertical, visibleFrame );
  contrast->setZeroString( noChange );
  contrast->setPrefixes("", "+");
  contrast->setMinValue( -SLIDER_RADIUS );
  contrast->setMaxValue( SLIDER_RADIUS );
  connect( contrast, SIGNAL(valueChanged(int)),
           this, SLOT(generateAdjustedPreviewImage()) );
  QToolTip::add( contrast, tr("Drag to adjust image contrast") );  

  contrastIcon = new ClickableLabel( visibleFrame, "contrastIcon" );
  contrastIcon->setPixmap( QPixmap(QString(IMAGE_PATH)+"miscImages/contrast.png") );
  connect( contrastIcon, SIGNAL(clicked()), SLOT(resetContrast()) );    
  QToolTip::add( contrastIcon, tr("Reset contrast") );
  //--------------
  //Dialog buttons:  
  buttonsFrame =   new QFrame( visibleFrame, "dialogButtons" );

  QPushButton* applyButton = new QPushButton( tr("Apply"), buttonsFrame );
  applyButton->setDefault(true);
  applyButton->setFocus();
  connect( applyButton, SIGNAL(clicked()), SLOT(applyAction()) );
                                
  QPushButton* cancelButton = new QPushButton( tr("Cancel"), buttonsFrame );
  connect( cancelButton, SIGNAL(clicked()), SLOT(reject()) );

  QPushButton* resetButton = new QPushButton( tr("Reset"), buttonsFrame );
  connect( resetButton, SIGNAL(clicked()), SLOT(resetAction()) );

  QGridLayout* buttonsGrid = new QGridLayout( buttonsFrame, 1, 5, 0 );
  buttonsGrid->setColStretch( 0, 1 );
  buttonsGrid->addWidget( applyButton,  0, 1 );
  buttonsGrid->addWidget( cancelButton, 0, 2 );
  buttonsGrid->addWidget( resetButton, 0, 3 );
  buttonsGrid->setColStretch( 4, 1 );  
  buttonsGrid->setSpacing( WIDGET_SPACING );
  //--------------
  QGridLayout* mainGrid = new QGridLayout( visibleFrame, 5, 3, 0 );
  
  mainGrid->addMultiCellWidget( previewInterface,     0,0, 0,2 );
  mainGrid->addMultiCellWidget( previewSelection, 1,1, 0,2, Qt::AlignHCenter );  
   
  mainGrid->addWidget( histogramInterface,    2, 0 ); 
  mainGrid->addWidget( brightness,            2, 1 );
  mainGrid->addWidget( contrast,              2, 2 );
  
  //make sure sliders have enough space so all slider units are settable
  mainGrid->setRowSpacing( 2, 2*SLIDER_RADIUS + 5) ;
    
  mainGrid->addWidget( histogramType,    3, 0, Qt::AlignHCenter );
  mainGrid->addWidget( brightnessIcon,   3, 1 );  
  mainGrid->addWidget( contrastIcon,     3, 2 );  
  
  mainGrid->addMultiCellWidget( buttonsFrame, 4,4, 0,2 );

  mainGrid->setRowStretch( 0, 1 );
  mainGrid->setColStretch( 0, 1 );
  
  mainGrid->setSpacing( WIDGET_SPACING );
  mainGrid->setMargin( WIDGET_SPACING );
  
  QGridLayout* invisibleGrid = new QGridLayout( this, 2, 1, 0 );
  invisibleGrid->addWidget( visibleFrame, 0, 0 );
  invisibleGrid->setRowStretch( 0, 1 );
  
  //PLATFORM_SPECIFIC_CODE
  //windows users expect a grip, but qt doesn't put one in by default. we'll add
  //it for them too. :-)
#if defined(Q_OS_WIN)
  QSizeGrip* sizeGrip = new QSizeGrip( this );
  invisibleGrid->addWidget( sizeGrip, 1, 0, Qt::AlignRight | Qt::AlignBottom );
#endif
  
  
  
  
  //Window caption
  setCaption( tr("Histogram Editor") );
  //-------------------------------
}
HistogramEditor::~HistogramEditor ( )

Definition at line 199 of file histogramEditor.cpp.

{ }

Member Function Documentation

void HistogramEditor::adjustImage ( QImage &  image) [private]

Definition at line 295 of file histogramEditor.cpp.

References b, brightness, contrast, HistogramInterface::getHistBoundaries(), histogramInterface, HSVtoRGB(), meanB, meanG, meanR, RGBtoHSV(), scaleColor(), and SLIDER_RADIUS.

Referenced by generateAdjustedPreviewImage(), and getModifiedImage().

{
  //obtain histogram left and right boundaries
  //sanity check
  int lumLeft, lumRight, redLeft, redRight, greenLeft, greenRight, blueLeft, blueRight;
  if( histogramInterface )
  {
    histogramInterface->getHistBoundaries( lumLeft, lumRight,
                                           redLeft, redRight,
                                           greenLeft, greenRight,
                                           blueLeft, blueRight );
  }
  else
  {
    lumLeft = 0; lumRight = 255;
    redLeft = 0; redRight = 255;
    greenLeft = 0; greenRight = 255;
    blueLeft = 0; blueRight = 255;
  }
  
  //modify image
  double displayToOneScalar = 1.0/255.0;
  double scaledMeanR = displayToOneScalar*scaleColor( 255.0*meanR, redLeft, redRight );
  double scaledMeanG = displayToOneScalar*scaleColor( 255.0*meanG, greenLeft, greenRight );
  double scaledMeanB = displayToOneScalar*scaleColor( 255.0*meanB, blueLeft, blueRight );
  
  double brightnessScalar, addedBrightnessColor;
  if(brightness->value() < 0)
  {
    brightnessScalar = ((double)(SLIDER_RADIUS + brightness->value()))/SLIDER_RADIUS;
    addedBrightnessColor = 1.0 - brightnessScalar;
  }
  else
  {
    brightnessScalar = ((double)(SLIDER_RADIUS - brightness->value()))/SLIDER_RADIUS;
    addedBrightnessColor = 0.0;
  }
  
  int x, y;  
  QRgb* rgb;
  double r,g,b;
  double h,s,v;
  int rPrime, gPrime, bPrime;
  uchar* scanLine;
  
  for( y=0; y<image.height(); y++)
  {   
    scanLine = image.scanLine(y);
    for( x=0; x<image.width(); x++)
    {
      //get rgb value
      rgb = ((QRgb*)scanLine+x);
      r = qRed(*rgb);
      g = qGreen(*rgb);
      b = qBlue(*rgb);
      
      //apply histogram boundaries
      RGBtoHSV(r,g,b,&h,&s,&v);
      v = scaleColor( v, lumLeft, lumRight );
      HSVtoRGB( &r,&g,&b, h,s,v);         
      
      r = scaleColor( r, redLeft, redRight );
      g = scaleColor( g, greenLeft, greenRight );
      b = scaleColor( b, blueLeft, blueRight );
      
      //convert to 0-1 scale
      r = r*displayToOneScalar;
      g = g*displayToOneScalar;
      b = b*displayToOneScalar;
      
      //adjust contrast
      r = ( (r-scaledMeanR) * (SLIDER_RADIUS-contrast->value()) )/SLIDER_RADIUS + scaledMeanR;
      g = ( (g-scaledMeanG) * (SLIDER_RADIUS-contrast->value()) )/SLIDER_RADIUS + scaledMeanG;
      b = ( (b-scaledMeanB) * (SLIDER_RADIUS-contrast->value()) )/SLIDER_RADIUS + scaledMeanB;
      
      //apply brightness adjustment
      //http://www.sgi.com/misc/grafica/interp/
      r = brightnessScalar*r + addedBrightnessColor;
      g = brightnessScalar*g + addedBrightnessColor;
      b = brightnessScalar*b + addedBrightnessColor;
      
      //scale and clamp to 0-255 range
      rPrime = (int) QMIN( QMAX((r*255), 0), 255 );
      gPrime = (int) QMIN( QMAX((g*255), 0), 255 );
      bPrime = (int) QMIN( QMAX((b*255), 0), 255 );
      
      //set adjusted color value
      *rgb = qRgb(rPrime, gPrime, bPrime);          
    } //x
  } //y  
}
void HistogramEditor::applyAction ( ) [private, slot]

check for changes to settings, if so

Definition at line 201 of file histogramEditor.cpp.

References brightness, contrast, HistogramInterface::getHistBoundaries(), and histogramInterface.

Referenced by HistogramEditor().

{
  //check if user has adjusted brightness, contrast, or histogram ranges.
  //if any changes have taken place call "accept", else "reject" so image is not
  //updated and appear modified
  int lumLeft, lumRight, redLeft, redRight, greenLeft, greenRight, blueLeft, blueRight;
  histogramInterface->getHistBoundaries( lumLeft, lumRight,
                                         redLeft, redRight,
                                         greenLeft, greenRight,
                                         blueLeft, blueRight );  
  if( brightness->value() != 0 || contrast->value()   != 0 ||
      lumLeft != 0 || lumRight != 255 ||
      redLeft !=0 || redRight != 255 ||
      greenLeft != 0 || greenRight != 255 ||
      blueLeft != 0 || blueRight != 255 )
  { accept(); }
  else
  { reject(); }  
}
void HistogramEditor::generateAdjustedPreviewImage ( ) [private, slot]

updates adjusted preview image

Definition at line 282 of file histogramEditor.cpp.

References adjustImage(), SplitViewInterface::getOrigImage(), previewInterface, and SplitViewInterface::setAdjustedImage().

Referenced by HistogramEditor().

{
  //get original image
  QImage origImage = previewInterface->getOrigImage();

  //construct adjusted image
  QImage adjustedImage = origImage.copy();
  adjustImage( adjustedImage );
  
  //set adjusted image
  previewInterface->setAdjustedImage( adjustedImage );
}
void HistogramEditor::getHistBoundaries ( int &  lumLeft,
int &  lumRight,
int &  redLeft,
int &  redRight,
int &  greenLeft,
int &  greenRight,
int &  blueLeft,
int &  blueRight 
)

returns histogram boundaries

Definition at line 260 of file histogramEditor.cpp.

References HistogramInterface::getHistBoundaries(), and histogramInterface.

{
  //sanity check
  if( histogramInterface )
  {
    histogramInterface->getHistBoundaries( lumLeft, lumRight,
                                           redLeft, redRight,
                                           greenLeft, greenRight,
                                           blueLeft, blueRight );
  }
  else
  {
    lumLeft = 0; lumRight = 255;
    redLeft = 0; redRight = 255;
    greenLeft = 0; greenRight = 255;
    blueLeft = 0; blueRight = 255;
  }
}
QImage * HistogramEditor::getModifiedImage ( )

get modified image that resulted from adjustments

Definition at line 228 of file histogramEditor.cpp.

References adjustImage(), and fileName.

{ 
  QImage* adjustedImage = new QImage(fileName);
  
  //convert to 32-bit depth if necessary
  if( adjustedImage->depth() < 32 )
  {
    QImage* tmp = adjustedImage;
    adjustedImage = new QImage( tmp->convertDepth( 32, Qt::AutoColor ) );
    delete tmp; tmp=NULL;
  }
  
  adjustImage( *adjustedImage );
  return adjustedImage;  
}
void HistogramEditor::keyPressEvent ( QKeyEvent *  e) [protected]
void HistogramEditor::keyReleaseEvent ( QKeyEvent *  e) [protected]

Definition at line 407 of file histogramEditor.cpp.

References previewInterface, previewSelection, and SplitViewInterface::setPreviewMode().

{
  if(e->key() == Qt::Key_Control )
  {
    previewInterface->setPreviewMode( (PREVIEW_MODE) previewSelection->currentItem(), 
                                      false );
  }
  else { QDialog::keyReleaseEvent(e); }
}
void HistogramEditor::resetAction ( ) [private, slot]
void HistogramEditor::resetBrightness ( ) [private, slot]

reset brightness

Definition at line 254 of file histogramEditor.cpp.

References brightness.

Referenced by HistogramEditor(), and resetAction().

{ brightness->setValue( 0 ); }
void HistogramEditor::resetContrast ( ) [private, slot]

reset contrast

Definition at line 257 of file histogramEditor.cpp.

References contrast.

Referenced by HistogramEditor(), and resetAction().

{ contrast->setValue( 0 ); }
double HistogramEditor::scaleColor ( double  color,
int  left,
int  right 
) [private]

Definition at line 387 of file histogramEditor.cpp.

Referenced by adjustImage().

{
  return QMAX( QMIN( (255.0*(color-left)) / (right-left), 255), 0 );  
}
void HistogramEditor::selectHistogramType ( int  selection) [private, slot]

updates historgram interface

Definition at line 249 of file histogramEditor.cpp.

References histogramInterface, and HistogramInterface::setDisplayChannel().

Referenced by HistogramEditor().

void HistogramEditor::selectPreviewImageType ( int  selection) [private, slot]

updates preview image

Definition at line 244 of file histogramEditor.cpp.

References previewInterface, and SplitViewInterface::setPreviewMode().

Referenced by HistogramEditor().


Member Data Documentation

Brightness slider.

Definition at line 105 of file histogramEditor.h.

Referenced by adjustImage(), applyAction(), HistogramEditor(), and resetBrightness().

Definition at line 99 of file histogramEditor.h.

Referenced by HistogramEditor().

Definition at line 101 of file histogramEditor.h.

Referenced by HistogramEditor().

Contrast slider.

Definition at line 108 of file histogramEditor.h.

Referenced by adjustImage(), applyAction(), HistogramEditor(), and resetContrast().

Definition at line 100 of file histogramEditor.h.

Referenced by HistogramEditor().

QString HistogramEditor::fileName [private]

Definition at line 86 of file histogramEditor.h.

Referenced by getModifiedImage(), and HistogramEditor().

QComboBox* HistogramEditor::histogramType [private]

Definition at line 98 of file histogramEditor.h.

Referenced by HistogramEditor().

double HistogramEditor::meanB [private]

Definition at line 89 of file histogramEditor.h.

Referenced by adjustImage(), and HistogramEditor().

double HistogramEditor::meanG [private]

Definition at line 89 of file histogramEditor.h.

Referenced by adjustImage(), and HistogramEditor().

double HistogramEditor::meanR [private]

Mean color values.

Definition at line 89 of file histogramEditor.h.

Referenced by adjustImage(), and HistogramEditor().

QComboBox* HistogramEditor::previewSelection [private]

Definition at line 97 of file histogramEditor.h.

Referenced by HistogramEditor(), keyPressEvent(), and keyReleaseEvent().


The documentation for this class was generated from the following files: