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