00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <qlayout.h>
00019 #include <qlabel.h>
00020 #include <qfont.h>
00021 #include <qframe.h>
00022 #include <qpushbutton.h>
00023 #include <qpixmap.h>
00024 #include <qimage.h>
00025 #include <qlineedit.h>
00026 #include <qcursor.h>
00027 #include <qapplication.h>
00028 #include <math.h>
00029
00030
00031 #include "photoEditWidget.h"
00032 #include "photoViewWidget.h"
00033 #include "questionDialog.h"
00034 #include "../backend/photo.h"
00035 #include "layoutWidget.h"
00036 #include "../config.h"
00037 #include "../backend/imageTools.h"
00038
00039 #include <iostream.h>
00040
00041 PhotoEditWidget::PhotoEditWidget(QWidget *parent,
00042 const char* name ) :
00043 QWidget(parent,name)
00044 {
00045
00046 photo = NULL;
00047
00048
00049 originalImage = NULL;
00050
00051
00052 layout = (LayoutWidget*)parent;
00053
00054
00055 photoDescription = new QLabel( this );
00056 photoDescription->setText( "Photo Description:" );
00057 photoDescription->setFont( QFont( "Times", 12, QFont::Bold ) );
00058 photoDescriptionVal = new QLineEdit( this );
00059 photoDescriptionVal->setFont( QFont( "Times", 12, QFont::Bold ) );
00060 connect( photoDescriptionVal, SIGNAL(textChanged(const QString&)),
00061 SLOT(updateDescription(const QString&)) );
00062
00063
00064 photoView = new PhotoViewWidget( this, "photo view" );
00065
00066
00067 buttons = new QFrame(this);
00068
00069 adjExposureImage = new QPixmap( QString(IMAGE_PATH)+"adjExposure.png" );
00070 adjExposureButton = new QPushButton( buttons );
00071 adjExposureButton->setPixmap( *adjExposureImage );
00072 adjExposureButton->setEnabled(false);
00073 connect( adjExposureButton, SIGNAL(clicked()), SLOT(adjustExposure()) );
00074
00075 cropImage = new QPixmap( QString(IMAGE_PATH)+"crop.png" );
00076 cropButton = new QPushButton( buttons );
00077 cropButton->setPixmap( *cropImage );
00078 connect( cropButton, SIGNAL(clicked()), SLOT(cropToRegion()) );
00079
00080 invertImage = new QPixmap( QString(IMAGE_PATH)+"invert.png" );
00081 invertButton = new QPushButton( buttons );
00082 invertButton->setPixmap( *invertImage );
00083 connect( invertButton, SIGNAL(clicked()), SLOT(invertSelection()) );
00084
00085 redEyeImage = new QPixmap( QString(IMAGE_PATH)+"removeRedEye.png" );
00086 redEyeButton = new QPushButton( buttons );
00087 redEyeButton->setPixmap( *redEyeImage );
00088 redEyeButton->setEnabled(false);
00089 connect( redEyeButton, SIGNAL(clicked()), SLOT(reduceRedeye()) );
00090
00091 resetImage = new QPixmap( QString(IMAGE_PATH)+"reset.png" );
00092 resetButton = new QPushButton( buttons );
00093 resetButton->setPixmap( *resetImage );
00094 connect( resetButton, SIGNAL(clicked()), SLOT(resetImageAction()) );
00095
00096 returnImage = new QPixmap( QString(IMAGE_PATH)+"return.png" );
00097 returnButton = new QPushButton( buttons );
00098 returnButton->setPixmap( *returnImage );
00099 connect( returnButton, SIGNAL(clicked()), SLOT(returnFromEdit()) );
00100
00101
00102 grid = new QGridLayout( this, 3, 3, 0 );
00103 grid->addWidget( photoDescription, 0, 0, Qt::AlignLeft );
00104 grid->addWidget( photoDescriptionVal, 0, 1 );
00105 grid->addMultiCellWidget( photoView, 1, 1, 0, 2, Qt::AlignCenter );
00106
00107 grid2 = new QGridLayout( buttons, 1, 8, 0 );
00108 grid2->addWidget( adjExposureButton, 0, 1, Qt::AlignLeft );
00109 grid2->addWidget( cropButton, 0, 2, Qt::AlignLeft );
00110 grid2->addWidget( invertButton, 0, 3, Qt::AlignLeft );
00111 grid2->addWidget( redEyeButton, 0, 4, Qt::AlignLeft );
00112 grid2->addWidget( resetButton, 0, 5, Qt::AlignLeft );
00113 grid2->addWidget( returnButton, 0, 6, Qt::AlignLeft );
00114
00115
00116 grid2->setColStretch( 0, 1 );
00117 grid2->setColStretch( 7, 1 );
00118 grid->addMultiCellWidget( buttons, 2, 2, 0, 2 );
00119
00120
00121 grid->setColStretch( 2, 1 );
00122
00123
00124 grid->setRowStretch( 1, 1 );
00125
00126
00127
00128 grid->addColSpacing(1, 300 );
00129
00130
00131 setPaletteBackgroundColor( QColor(255, 255, 255) );
00132 }
00133
00134 PhotoEditWidget::~PhotoEditWidget()
00135 {
00136 delete originalImage;
00137 originalImage = NULL;
00138 }
00139
00140 void PhotoEditWidget::setPhoto(Photo* photo)
00141 {
00142
00143 this->photo = photo;
00144
00145
00146 delete originalImage;
00147 originalImage = NULL;
00148
00149
00150 photoDescriptionVal->setText( photo->getDescription() );
00151
00152
00153 photoView->setPhoto(photo);
00154
00155
00156
00157
00158 if(photo->actualSlideshowWidth() == -1)
00159 {
00160 QImage *backendImage = new QImage( photo->getImageFilename() );
00161
00162 int w, h;
00163 resizeImage( backendImage->width(), backendImage->height(),
00164 SLIDESHOW_WIDTH, SLIDESHOW_HEIGHT,
00165 w, h);
00166 photo->setActualSlideshowDimensions( w, h);
00167 delete backendImage;
00168 backendImage = NULL;
00169 }
00170 }
00171
00172 void PhotoEditWidget::updateDescription( const QString& val )
00173 {
00174 if(photo != NULL)
00175 photo->setDescription(val);
00176 }
00177
00178 void PhotoEditWidget::adjustExposure()
00179 {
00180
00181
00182 QImage *backendImage = new QImage( photo->getImageFilename() );
00183
00184
00185 double delta = 0.00001;
00186 double max = 0.0;
00187 double sum = 0.0;
00188 double tmp, tmp2;
00189 int x;
00190 for(x=0; x<backendImage->width(); x++)
00191 {
00192 int y;
00193 for(y=0; y<backendImage->height(); y++)
00194 {
00195 QRgb val = backendImage->pixel( x, y );
00196 tmp = qGray(val);
00197 tmp = tmp / 255.0;
00198 tmp2 = log( tmp + delta );
00199
00200 sum+=tmp2;
00201 if(tmp > max)
00202 max = tmp;
00203 }
00204 }
00205 double avg = exp(sum/(backendImage->width() * backendImage->height()));
00206 cout << "max: " << max << endl;
00207 cout << "avg: " << avg << endl;
00208 double whiteSquared = max*max;
00209
00210
00211 QImage* equalizedImage = new QImage(backendImage->width(),
00212 backendImage->height(),
00213 backendImage->depth());
00214 double r, g, b;
00215 double alpha = 0.18;
00216 for(x=0; x<backendImage->width(); x++)
00217 {
00218 int y;
00219 for(y=0; y<backendImage->height(); y++)
00220 {
00221 QRgb val = backendImage->pixel( x, y );
00222 r = qRed(val); g = qGreen(val); b = qBlue(val);
00223 r = r/255.0; g = g/255.0; b = b/255.0;
00224
00225 r = (alpha/avg) * r;
00226 g = (alpha/avg) * g;
00227 b = (alpha/avg) * b;
00228
00229 r = (r * (1 + (r / whiteSquared))) / (1 + r);
00230 g = (g * (1 + (g / whiteSquared))) / (1 + g);
00231 b = (b * (1 + (b / whiteSquared))) / (1 + b);
00232
00233 r = r*255; g = g*255; b = b*255;
00234 val = qRgb( (int)r, (int)g, (int)b );
00235
00236 equalizedImage->setPixel( x, y, val );
00237 }
00238 }
00239
00242 if(originalImage == NULL)
00243 {
00244 originalImage = backendImage;
00245 }
00246 else
00247 {
00248 delete backendImage;
00249 backendImage = NULL;
00250 }
00251
00253 photo->setImage(equalizedImage);
00254
00255
00256
00257 equalizedImage = NULL;
00258
00260 photoView->setPhoto( photo );
00261
00262 }
00263
00264 void PhotoEditWidget::cropToRegion()
00265 {
00266
00267
00268 QPoint topLeft, bottomRight;
00269 photoView->getSelection(topLeft, bottomRight);
00270
00271
00272 if(bottomRight.x() - topLeft.x() == 0 ||
00273 bottomRight.y() - topLeft.y() == 0)
00274 {
00275
00276
00277 return;
00278 }
00279
00280
00281 QImage *backendImage = new QImage( photo->getImageFilename() );
00282
00283
00284 float widthRatio = (1.0f * backendImage->width()) / photo->actualSlideshowWidth();
00285 float heightRatio = (1.0f * backendImage->height()) / photo->actualSlideshowHeight();
00286
00287
00288
00289
00290 if(bottomRight.x() == (photo->actualSlideshowWidth() - 1))
00291 bottomRight.setX( backendImage->width() - 1 );
00292 else
00293 bottomRight.setX( bottomRight.x() * widthRatio );
00294
00295 if(bottomRight.y() == (photo->actualSlideshowHeight() - 1))
00296 bottomRight.setY( backendImage->height() - 1 );
00297 else
00298 bottomRight.setY( bottomRight.y() * heightRatio );
00299
00300
00301 QImage* croppedImage = new QImage(bottomRight.x() - topLeft.x() + 1,
00302 bottomRight.y() - topLeft.y() + 1,
00303 backendImage->depth());
00304 int newX, newY;
00305 newX = 0;
00306
00307 int x;
00308 for(x=topLeft.x(); x<= bottomRight.x(); x++)
00309 {
00310 newY = 0;
00311 int y;
00312 for(y=topLeft.y(); y<= bottomRight.y(); y++)
00313 {
00314 croppedImage->setPixel( newX, newY, backendImage->pixel(x, y) );
00315 newY++;
00316 }
00317 newX++;
00318 }
00319
00322 if(originalImage == NULL)
00323 {
00324 originalImage = backendImage;
00325 }
00326 else
00327 {
00328 delete backendImage;
00329 backendImage = NULL;
00330 }
00331
00333 photo->setImage(croppedImage);
00334
00335
00336
00337 croppedImage = NULL;
00338
00340 photoView->setPhoto( photo );
00341
00342 }
00343
00344 void PhotoEditWidget::invertSelection()
00345 {
00346
00347
00348 QPoint topLeft, bottomRight;
00349 photoView->getSelection(topLeft, bottomRight);
00350
00351
00352 QImage *backendImage = new QImage( photo->getImageFilename() );
00353
00354
00355 if(bottomRight.x() - topLeft.x() == 0 ||
00356 bottomRight.y() - topLeft.y() == 0)
00357 {
00358 topLeft.setX(0);
00359 topLeft.setY(0);
00360 bottomRight.setX(backendImage->width() - 1);
00361 bottomRight.setY(backendImage->height() - 1);
00362 }
00363
00364 else
00365 {
00366 float widthRatio = (1.0f * backendImage->width()) / photo->actualSlideshowWidth();
00367 float heightRatio = (1.0f * backendImage->height()) / photo->actualSlideshowHeight();
00368
00369 topLeft.setX( topLeft.x() * widthRatio );
00370 topLeft.setY( topLeft.y() * heightRatio );
00371
00372
00373
00374
00375 if(bottomRight.x() == (photo->actualSlideshowWidth() - 1))
00376 bottomRight.setX( backendImage->width() - 1 );
00377 else
00378 bottomRight.setX( bottomRight.x() * widthRatio );
00379
00380 if(bottomRight.y() == (photo->actualSlideshowHeight() - 1))
00381 bottomRight.setY( backendImage->height() - 1 );
00382 else
00383 bottomRight.setY( bottomRight.y() * heightRatio );
00384 }
00385
00386
00387 QImage* invertedImage = new QImage(backendImage->width(),
00388 backendImage->height(),
00389 backendImage->depth());
00390 int x;
00391 for(x=0; x<backendImage->width(); x++)
00392 {
00393 int y;
00394 for(y=0; y<backendImage->height(); y++)
00395 {
00396
00397 if( x >= topLeft.x() && x <= bottomRight.x() &&
00398 y >= topLeft.y() && y <= bottomRight.y())
00399 {
00400 QRgb val = backendImage->pixel( x, y );
00401 val = qRgb( 255 - qRed(val), 255 - qGreen(val), 255 - qBlue(val) );
00402 invertedImage->setPixel( x, y, val );
00403 }
00404
00405 else
00406 {
00407 invertedImage->setPixel( x, y, backendImage->pixel(x, y) );
00408 }
00409 }
00410 }
00411
00414 if(originalImage == NULL)
00415 {
00416 originalImage = backendImage;
00417 }
00418 else
00419 {
00420 delete backendImage;
00421 backendImage = NULL;
00422 }
00423
00425 photo->setImage(invertedImage);
00426
00427
00428
00429 invertedImage = NULL;
00430
00432 photoView->setPhoto( photo );
00433
00434 }
00435
00436 void PhotoEditWidget::reduceRedeye()
00437 {
00438
00439 }
00440
00441 void PhotoEditWidget::resetImageAction()
00442 {
00443
00444 if(originalImage != NULL)
00445 {
00447 photo->setImage(originalImage);
00448
00449
00450
00451 originalImage = NULL;
00452
00454 photoView->setPhoto( photo );
00455 }
00456 }
00457
00458 void PhotoEditWidget::returnFromEdit()
00459 {
00460
00461 if(originalImage == NULL)
00462 {
00463 layout->stopEdit(true);
00464 return;
00465 }
00466
00467
00468 QuestionDialog sure( "Keep changes?",
00469 "Once applied alterations cannot be undone.",
00470 "warning.png",
00471 this );
00472
00473 if(sure.exec())
00474 {
00475 layout->stopEdit(true);
00476 }
00477
00478 else
00479 {
00480 resetImageAction();
00481 layout->stopEdit(true);
00482 }
00483 }
00484