00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qapplication.h>
00013 #include <qpainter.h>
00014 #include <qpixmap.h>
00015 #include <qimage.h>
00016 #include <qaccel.h>
00017 #include <qcursor.h>
00018
00019
00020 #include "histogramInterface.h"
00021 #include "histogramEditor.h"
00022 #include "../../backend/tools/imageTools.h"
00023 #include "../cursors.h"
00024
00025
00026
00027
00028 #define DRAG_THRESHOLD 5
00029
00030 #define COLOR_BAR_MARGIN 2
00031 #define COLOR_BAR_BORDER 2
00032 #define COLOR_BAR_HEIGHT 6
00033 #define HISTOGRAM_HEIGHT ( height() - COLOR_BAR_BORDER - 2*COLOR_BAR_MARGIN - COLOR_BAR_HEIGHT )
00034
00035
00036 HistogramInterface::HistogramInterface( QString imageFilename,
00037 QWidget *parent, const char* name ) :
00038 QWidget (parent, name, WNoAutoErase)
00039 {
00040
00041 displayedChannel = LUMINOSITY;
00042
00043
00044 getImageSize( imageFilename, origImageSize );
00045
00046
00047
00048
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 }
00075 }
00076
00077
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
00091 dragMode = NO_EFFECT;
00092 currentMouseShape = NO_EFFECT;
00093
00094
00095 setMouseTracking(true);
00096
00097
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
00106 setCursor( getCursor(CROSS_CURSOR) );
00107
00108
00109 resetBoundaries();
00110 }
00111
00112 HistogramInterface::~HistogramInterface() { }
00113
00114 void HistogramInterface::resizeEvent( QResizeEvent * )
00115 {
00116 repaint(false);
00117 }
00118
00119 void HistogramInterface::getSelectedRange( int &left, int &right )
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 }
00144
00145 double HistogramInterface::displayToIndex( int coordinate )
00146 {
00147 return (255.0*coordinate) / ( width()-1 );
00148 }
00149
00150 int HistogramInterface::indexToDisplay( int index )
00151 {
00152 return (index* (width()-1) ) / 255;
00153 }
00154
00155 void HistogramInterface::paintEvent(QPaintEvent *e)
00156 {
00157
00158 QPixmap buffer( size() );
00159 buffer.fill( white );
00160
00161
00162 QPainter bufferPainter( &buffer );
00163
00164
00165 bufferPainter.setClipping(false);
00166
00167
00168 bufferPainter.fillRect( buffer.rect(), backgroundBrush() );
00169
00170
00171
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
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
00206 double scaledH = (histogramHeight*h)/maxCount;
00207 h = (int) scaledH;
00208
00209 if( h == 0 && scaledH > h) h++;
00210
00211 if(h > 0)
00212 {
00213
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
00223
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
00232
00233
00234 bufferPainter.fillRect( QRect(0, histogramHeight + COLOR_BAR_MARGIN,
00235 width(), COLOR_BAR_HEIGHT+2*COLOR_BAR_BORDER),
00236 QBrush(black) );
00237
00238
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
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
00269 bufferPainter.end();
00270
00271
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 }
00278
00279 void HistogramInterface::setDisplayChannel( DISPLAYED_CHANNEL channel )
00280 {
00281
00282 displayedChannel = channel;
00283 repaint(false);
00284 }
00285
00286 QSize HistogramInterface::minimumSizeHint() const
00287 {
00288 return QSize( 256,100 + COLOR_BAR_MARGIN + 2*COLOR_BAR_BORDER + COLOR_BAR_HEIGHT );
00289 }
00290
00291 bool HistogramInterface::nearBoundary( QPoint p )
00292 {
00293
00294 int index = (int) displayToIndex( p.x() );
00295
00296
00297 int left, right;
00298 getSelectedRange( left, right );
00299
00300
00301 return ( (index < left + 1 + DRAG_THRESHOLD &&
00302 index > left - DRAG_THRESHOLD) ||
00303 (index < right + DRAG_THRESHOLD &&
00304 index > right - 1 - DRAG_THRESHOLD) );
00305 }
00306
00307 void HistogramInterface::mousePressEvent( QMouseEvent *e)
00308 {
00309
00310 dragMode = DRAG;
00311
00312
00313 int index = (int) displayToIndex( e->pos().x() );
00314
00315
00316 int left, right;
00317 getSelectedRange( left, right );
00318
00319
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
00339 if( index < left + DRAG_THRESHOLD &&
00340 index > left - DRAG_THRESHOLD )
00341 {
00342 *click = right;
00343 *drag = left;
00344 return;
00345 }
00346
00347 if( index < right + DRAG_THRESHOLD &&
00348 index > right - DRAG_THRESHOLD )
00349 {
00350 *click = left;
00351 *drag = right;
00352 return;
00353 }
00354
00355 else
00356 {
00357 *click = index;
00358 *drag = index;
00359 repaint(false);
00360
00361
00362 int left, right;
00363 getSelectedRange( left, right );
00364 emit selectedRangeChanged();
00365 }
00366 }
00367
00368 void HistogramInterface::mouseMoveEvent( QMouseEvent *e)
00369 {
00370
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
00388 int x = QMAX( QMIN( e->pos().x(), width()-1 ), 0 );
00389 int index = (int) displayToIndex( x );
00390
00391
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
00398 repaint(false);
00399
00400
00401 int left, right;
00402 getSelectedRange( left, right );
00403 emit selectedRangeChanged();
00404 }
00405
00406 void HistogramInterface::mouseReleaseEvent( QMouseEvent *e)
00407 {
00408
00409 dragMode = NO_EFFECT;
00410
00411
00412 if( !nearBoundary(e->pos()) && currentMouseShape == DRAG )
00413 {
00414 currentMouseShape = NO_EFFECT;
00415 setCursor( getCursor(CROSS_CURSOR) );
00416 }
00417 }
00418
00419 void HistogramInterface::selectAll()
00420 {
00421
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
00429 int left, right;
00430 getSelectedRange( left, right );
00431 emit selectedRangeChanged();
00432 }
00433
00434 void HistogramInterface::getHistBoundaries(int &lumLeft, int &lumRight,
00435 int &redLeft, int &redRight,
00436 int &greenLeft, int &greenRight,
00437 int &blueLeft, int &blueRight)
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 }
00451
00452 void HistogramInterface::resetBoundaries()
00453 {
00454 lumClick = redClick = greenClick = blueClick = 0;
00455 lumDrag = redDrag = greenDrag = blueDrag = 255;
00456 repaint(false);
00457 emit selectedRangeChanged();
00458 }
00459
00460
00461
00462
00463