AlbumShaper  1.0a3
editingInterface.cpp
Go to the documentation of this file.
1 //==============================================
2 // copyright : (C) 2003-2005 by Will Stokes
3 //==============================================
4 // This program is free software; you can redistribute it
5 // and/or modify it under the terms of the GNU General
6 // Public License as published by the Free Software
7 // Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //==============================================
10 
11 //Systemwide includes
12 #include <qlayout.h>
13 #include <qlabel.h>
14 #include <qfont.h>
15 #include <q3frame.h>
16 #include <qsize.h>
17 #include <qtoolbutton.h>
18 #include <qimage.h>
19 #include <qcursor.h>
20 #include <qapplication.h>
21 //Added by qt3to4:
22 #include <QKeyEvent>
23 #include <Q3GridLayout>
24 #include <QPixmap>
25 #include <math.h>
26 #include <qtooltip.h>
27 #include <q3hgroupbox.h>
28 #include <qpushbutton.h>
29 #include <qcombobox.h>
30 #include <math.h>
31 #include <QDesktopWidget>
32 
33 //Projectwide includes
34 #include "../clickableLabel.h"
35 #include "editingInterface.h"
36 #include "selectionInterface.h"
37 #include "histogramEditor.h"
38 #include "grainEditor.h"
40 #include "../statusWidget.h"
41 #include "../layoutWidget.h"
42 #include "../window.h"
43 #include "../titleWidget.h"
44 #include "../dialogs/questionDialog.h"
45 #include "../../config.h"
46 #include "../../backend/album.h"
47 #include "../../backend/subalbum.h"
48 #include "../../backend/photo.h"
49 #include "../../backend/tools/fileTools.h"
50 #include "../../backend/tools/imageTools.h"
51 
52 #include "../../backend/enhancements/color.h"
53 #include "../../backend/enhancements/contrast.h"
54 #include "../../backend/enhancements/redEye.h"
55 #include "../../backend/enhancements/tilt.h"
56 
57 #include "../../backend/manipulations/manipulationOptions.h"
58 #include "../../backend/manipulations/blackWhite.h"
59 #include "../../backend/manipulations/crop.h"
60 #include "../../backend/manipulations/emboss.h"
61 #include "../../backend/manipulations/invert.h"
62 #include "../../backend/manipulations/mosaic.h"
63 #include "../../backend/manipulations/painting.h"
64 #include "../../backend/manipulations/pointillism.h"
65 #include "../../backend/manipulations/sepia.h"
66 
67 #include "../../configuration/configuration.h"
68 
69 #define EFFECT_PREVIEW_WIDTH 107
70 #define EFFECT_PREVIEW_HEIGHT 80
71 
72 #include <iostream>
73 using namespace std;
74 
75 //==============================================
76 EditingInterface::EditingInterface(QWidget *parent, const char* name )
77  : QWidget(parent,name)
78 {
79  //create a smaller font for drawing various labels and items
80  QFont smallerFont = font();
81  smallerFont.setPointSize( smallerFont.pointSize() - 1 );
82 
83  setFocusPolicy(Qt::StrongFocus);
84 
85  //set photo pointer to null by default
86  photo = NULL;
87 
88  //store layout pointer
89  layout = (LayoutWidget*)parent;
90 
91  //----------
92  //Construct photo frame that houses photo being edited and prev and next buttons
93  Q3Frame* photoFrame = new Q3Frame(this, "photoFrame" );
94 
95  //Construct the frame that houses all the controls
96  Q3Frame* controlsFrame = new Q3Frame(this, "controlsFrame");
97 
98  //Place photo fram and control widgets in a top level grid
99  Q3GridLayout* mainGrid = new Q3GridLayout( this, 3, 3, 0 );
100  mainGrid->addWidget( photoFrame, 0, 1 );
101  mainGrid->setRowStretch(0, 1);
102  mainGrid->addMultiCellWidget( controlsFrame, 1,1, 0,2 );
103  mainGrid->setRowSpacing( 2, WIDGET_SPACING );
104  //----------
105  //Previous photo button
106  previousButton = new ClickableLabel( photoFrame, "previousButton" );
107  previousButton->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/previous.png") );
108  connect( previousButton, SIGNAL(clicked()), SLOT(showPrevPhoto()) );
109 
110  //Create widget for displaying and selecting regions of the current photo
111  selectionInterface = new SelectionInterface( photoFrame, "selectionInterface" );
112  connect( selectionInterface, SIGNAL( selectionChanged() ), this, SLOT( handleSelectionChanged() ) );
113  connect( selectionInterface, SIGNAL( aspectRatioChanged() ), this, SLOT( handleAspectRatioChanged() ) );
114  connect( selectionInterface, SIGNAL( ctrlClick() ), this, SLOT( rotateSelection() ) );
115 
116  //Next photo button
117  nextButton = new ClickableLabel( photoFrame, "nextButton" );
118  nextButton->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/next.png") );
119  connect( nextButton, SIGNAL(clicked()), SLOT(showNextPhoto()) );
120 
121  //Place above widgets in grid, allow seletion interface to take up extra room
122  Q3GridLayout* selectionGrid = new Q3GridLayout( photoFrame, 1, 5, 0 );
123  selectionGrid->setColSpacing( 0, WIDGET_SPACING );
124  selectionGrid->addWidget( previousButton, 0, 1, Qt::AlignCenter );
125  selectionGrid->addWidget( selectionInterface, 0, 2 );
126  selectionGrid->setColStretch( 2, 1 );
127  selectionGrid->addWidget( nextButton, 0, 3, Qt::AlignCenter );
128  selectionGrid->setColSpacing( 4, WIDGET_SPACING );
129  selectionGrid->setSpacing( WIDGET_SPACING );
130  //-----------
131  //construct the frames each set of controls is placed in
132  Q3HGroupBox* frameControls = new Q3HGroupBox( tr("Frame"), controlsFrame, "frameControls" );
133  frameControls->setAlignment( Qt::AlignHCenter );
134  frameControls->setInsideMargin( WIDGET_SPACING );
135 
136  Q3HGroupBox* enhanceControls = new Q3HGroupBox( tr("Enhance"), controlsFrame, "enhanceControls" );
137  enhanceControls->setAlignment( Qt::AlignHCenter );
138  enhanceControls->setInsideMargin( WIDGET_SPACING );
139 
140  Q3HGroupBox* manipulateControls = new Q3HGroupBox( tr("Manipulate"), controlsFrame, "applyEffect" );
141  manipulateControls->setAlignment( Qt::AlignHCenter );
142  manipulateControls->setInsideMargin( WIDGET_SPACING );
143 
144  //layout groups of controls
145  Q3GridLayout* controlsGrid = new Q3GridLayout( controlsFrame, 1, 5, 0 );
146  controlsGrid->addWidget( frameControls, 0, 1 );
147  controlsGrid->addWidget( enhanceControls, 0, 2 );
148  controlsGrid->addWidget( manipulateControls, 0, 3 );
149 
150  controlsGrid->setSpacing( WIDGET_SPACING );
151  controlsGrid->setColSpacing(0, WIDGET_SPACING );
152  controlsGrid->setColStretch(0, 1);
153  controlsGrid->setColSpacing(4, WIDGET_SPACING );
154  controlsGrid->setColStretch(4, 1);
155 
156  //----------
157  //Frame Controls
158  //----------
159  Q3Frame* frameControlsFrame = new Q3Frame( frameControls );
160 
161  //-----
162  //rotate and flip buttons
163  Q3Frame* rotateFlipFrame = new Q3Frame( frameControlsFrame );
164 
165  QToolButton* rotateRightButton = new QToolButton( rotateFlipFrame, "rotateRight" );
166  rotateRightButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/rotate90.png") );
167  rotateRightButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
168  connect( rotateRightButton, SIGNAL(clicked()), SLOT(rotateRight()) );
169  QToolTip::add( rotateRightButton, tr("Rotate clockwise") );
170 
171  QToolButton* rotateLeftButton = new QToolButton( rotateFlipFrame, "rotateLeft" );
172  rotateLeftButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/rotate270.png") );
173  rotateLeftButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
174  connect( rotateLeftButton, SIGNAL(clicked()), SLOT(rotateLeft()) );
175  QToolTip::add( rotateLeftButton, tr("Rotate counterclockwise") );
176 
177  QToolButton* flipHorizontalButton = new QToolButton( rotateFlipFrame, "flipHorizontal" );
178  flipHorizontalButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/flipHorizontally.png") );
179  flipHorizontalButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
180  connect( flipHorizontalButton, SIGNAL(clicked()), SLOT(flipHorizontal()) );
181  QToolTip::add( flipHorizontalButton, tr("Flip horizontally") );
182 
183  QToolButton* flipVerticalButton = new QToolButton( rotateFlipFrame, "flipVertical" );
184  flipVerticalButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/flipVertically.png") );
185  flipVerticalButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
186  connect( flipVerticalButton, SIGNAL(clicked()), SLOT(flipVertical()) );
187  QToolTip::add( flipVerticalButton, tr("Flip vertically") );
188 
189  correctTiltButton = new QToolButton( rotateFlipFrame, "correctTilt" );
190  correctTiltButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/correctTilt.png") );
191  correctTiltButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
192 
193  connect( correctTiltButton, SIGNAL(clicked()), SLOT(startCorrectTilt()) );
194 
195  connect( selectionInterface, SIGNAL(lineSelected(QPoint, QPoint)),
196  this, SLOT(finishCorrectTilt( QPoint, QPoint)) );
197 
198  QToolTip::add( correctTiltButton, tr("Correct tilt") );
199 
200  //Place buttons in grid
201  Q3GridLayout* rotateFlipGrid = new Q3GridLayout( rotateFlipFrame, 1, 5, 0 );
202  rotateFlipGrid->setSpacing(TIGHT_WIDGET_SPACING);
203  rotateFlipGrid->addWidget( rotateRightButton, 0, 0 );
204  rotateFlipGrid->addWidget( rotateLeftButton, 0, 1 );
205  rotateFlipGrid->addWidget( flipHorizontalButton, 0, 2 );
206  rotateFlipGrid->addWidget( flipVerticalButton, 0, 3 );
207  rotateFlipGrid->addWidget( correctTiltButton, 0, 4 );
208  //-----
209  //aspect ratio selection and crop controls
210  aspectRatios = new QComboBox( frameControlsFrame );
211  aspectRatios->setFont( smallerFont );
212  connect( aspectRatios, SIGNAL(activated(int)), this, SLOT(selectAspectRatio()) );
213  aspectRatioValues = new QSize[8];
214  maxDimensions = new double[8];
215  int curAspectRatio = 0;
216  //--
217  aspectRatios->insertItem( tr("Custom") );
218  maxDimensions[curAspectRatio] = -1.0;
219  aspectRatioValues[curAspectRatio++] = QSize( -1, -1 );
220  //--
221  aspectRatios->insertItem( tr("Photo (3.5 x 5)") );
222  maxDimensions[curAspectRatio] = 5.0;
223  aspectRatioValues[curAspectRatio++] = QSize( 10, 7 );
224  //--
225  aspectRatios->insertItem( tr("Photo (4 x 6)") );
226  maxDimensions[curAspectRatio] = 6.0;
227  aspectRatioValues[curAspectRatio++] = QSize( 6, 4 );
228  //--
229  aspectRatios->insertItem( tr("Photo (5 x 7)") );
230  maxDimensions[curAspectRatio] = 7.0;
231  aspectRatioValues[curAspectRatio++] = QSize( 7, 5 );
232  //--
233  aspectRatios->insertItem( tr("Photo (8 x 10)") );
234  maxDimensions[curAspectRatio] = 10.0;
235  aspectRatioValues[curAspectRatio++] = QSize( 10, 8 );
236  //--
237  aspectRatios->insertItem( tr("Postcard") );
238  maxDimensions[curAspectRatio] = 6.0;
239  aspectRatioValues[curAspectRatio++] = QSize( 6, 4 );
240  //--
241  aspectRatios->insertItem( tr("Wallet") );
242  maxDimensions[curAspectRatio] = 3.0;
243  aspectRatioValues[curAspectRatio++] = QSize( 3, 2 );
244  //--
245  aspectRatios->insertItem( tr("Desktop") );
246  displayResolutionIndex = curAspectRatio;
247  maxDimensions[curAspectRatio] = -1.0;
248  aspectRatioValues[curAspectRatio++] = qApp->desktop()->screenGeometry().size();
249  //--
250  //connect signal emitted when screen resolution changes
251  //so as to update this stored value (and selction if necessary)
252  connect( qApp->desktop(), SIGNAL( resized(int)), this, SLOT(screenResolutionChanged()) );
253 
254  QToolTip::add( aspectRatios, tr("Select region for cropping using a particular aspect ratio") );
255 
256  QLabel* aspectRatioLabel = new QLabel( tr("Aspect Ratio"), frameControlsFrame );
257  aspectRatioLabel->setFont( smallerFont );
258  //--
259 
260  //Crop button
261  cropButton = new QToolButton( frameControlsFrame );
262  QIcon cropIcon;
263  cropIcon.setPixmap( QString(IMAGE_PATH)+"buttonIcons/crop.png",
264  QIcon::Automatic,
265  QIcon::Normal );
266 
267  cropIcon.setPixmap( QString(IMAGE_PATH)+"buttonIcons/crop_disabled.png",
268  QIcon::Automatic,
269  QIcon::Disabled );
270  cropButton->setIconSet( cropIcon );
271  connect( cropButton, SIGNAL(clicked()), SLOT(crop()) );
272  QToolTip::add( cropButton, tr("Crop photo to selected region") );
273 
274  QLabel* cropLabel = new QLabel( tr("Crop"), frameControlsFrame );
275  cropLabel->setFont( smallerFont );
276 
277  //--
278 
279  //Place frame controls in a grid
280  Q3GridLayout* frameControlsGrid = new Q3GridLayout( frameControlsFrame, 3, 2, 0 );
281  frameControlsGrid->setSpacing(TIGHT_WIDGET_SPACING);
282  frameControlsGrid->addMultiCellWidget( rotateFlipFrame, 0,0, 0,1 );
283  frameControlsGrid->addWidget( aspectRatios, 1, 0, Qt::AlignHCenter );
284  frameControlsGrid->addWidget( cropButton, 1, 1, Qt::AlignHCenter );
285  frameControlsGrid->addWidget( aspectRatioLabel, 2, 0, Qt::AlignHCenter );
286  frameControlsGrid->addWidget( cropLabel, 2, 1, Qt::AlignHCenter );
287 
288  //----------
289  //Enhance Controls
290  //----------
291  Q3Frame* enhanceControlsFrame = new Q3Frame( enhanceControls );
292 
293  //setup params for large buttons
294  int numLargeButtons = 3;
295  int curButtonIndex=0;
296  ClickableLabel** largeButtons = new ClickableLabel*[numLargeButtons];
297 
298 
299  //--------------------
300  //Frame for semi-automatic enhance controls
301  Q3Frame* autoEnhanceControlsFrame = new Q3Frame( enhanceControlsFrame );
302 
303  //Enhance Color
304  ClickableLabel* enhanceColorButton = largeButtons[curButtonIndex] =
305  new ClickableLabel( autoEnhanceControlsFrame );
306  largeButtons[curButtonIndex]->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/improveColorBalance.png") );
307  connect( largeButtons[curButtonIndex], SIGNAL(clicked()), SLOT(colorBalance()) );
308  QToolTip::add( largeButtons[curButtonIndex], tr("Enhance color balance") );
309  curButtonIndex++;
310 
311  QLabel* enhanceColorLabel = new QLabel( tr("Color"), autoEnhanceControlsFrame );
312  enhanceColorLabel->setFont( smallerFont );
313 
314  //Enhance Contrast
315  ClickableLabel* enhanceContrastButton = largeButtons[curButtonIndex] =
316  new ClickableLabel( autoEnhanceControlsFrame );
317  largeButtons[curButtonIndex]->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/enhanceContrast.png") );
318  connect( largeButtons[curButtonIndex], SIGNAL(clicked()), SLOT(enhanceContrast()) );
319  QToolTip::add( largeButtons[curButtonIndex], tr("Enhance contrast") );
320  curButtonIndex++;
321 
322  QLabel* enhanceContrastLabel = new QLabel( tr("Contrast"), autoEnhanceControlsFrame );
323  enhanceContrastLabel->setFont( smallerFont );
324 
325  //Remove Red-Eye
326  redEyeReductionButton = largeButtons[curButtonIndex] = new ClickableLabel( autoEnhanceControlsFrame );
328 
329  largeButtons[curButtonIndex]->setPixmap( QPixmap( QString(IMAGE_PATH)+"buttonIcons/redEyeReduction.png" ) );
330  connect( largeButtons[curButtonIndex], SIGNAL(clicked()), SLOT(removeRedeye()) );
331  QToolTip::add( largeButtons[curButtonIndex], tr("Remove red-eye") );
332  curButtonIndex++;
333 
334  QLabel* removeRedyEyeLabel = new QLabel( tr("Red Eye"), autoEnhanceControlsFrame );
335  removeRedyEyeLabel->setFont( smallerFont );
336 
337  //Place semi-automatic enhance controls in grid
338  Q3GridLayout* autoEnhanceControlsGrid = new Q3GridLayout( autoEnhanceControlsFrame, 2, 3, 0 );
339  autoEnhanceControlsGrid->setSpacing(TIGHT_WIDGET_SPACING);
340  autoEnhanceControlsGrid->addWidget( enhanceColorButton, 0, 0, Qt::AlignHCenter );
341  autoEnhanceControlsGrid->addWidget( enhanceColorLabel, 1, 0, Qt::AlignHCenter );
342 
343  autoEnhanceControlsGrid->addWidget( enhanceContrastButton, 0, 1, Qt::AlignHCenter );
344  autoEnhanceControlsGrid->addWidget( enhanceContrastLabel, 1, 1, Qt::AlignHCenter );
345 
346  autoEnhanceControlsGrid->addWidget( redEyeReductionButton, 0, 2, Qt::AlignHCenter );
347  autoEnhanceControlsGrid->addWidget( removeRedyEyeLabel, 1, 2, Qt::AlignHCenter );
348  //--------------------
349  //Frame for more labor intensive enhance controls
350  Q3Frame* manualEnhanceControlsFrame = new Q3Frame( enhanceControlsFrame );
351 
352  //Tune Levels Button
353  ClickableLabel* tuneLevelsButton = new ClickableLabel( manualEnhanceControlsFrame );
354  tuneLevelsButton->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/tuneLevels.png") );
355  connect( tuneLevelsButton, SIGNAL(clicked()), SLOT(tuneLevels()) );
356  QToolTip::add( tuneLevelsButton, tr("Fine tune brightness, contrast, and colors") );
357 
358  QLabel* tuneLevelsLabel = new QLabel( tr("Levels..."), manualEnhanceControlsFrame );
359  tuneLevelsLabel->setFont( smallerFont );
360 
361  //Adjust Grain Button
362  ClickableLabel* adjustGrainButton = new ClickableLabel( manualEnhanceControlsFrame );
363  adjustGrainButton->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/adjustGrain.png") );
364  connect( adjustGrainButton, SIGNAL(clicked()), SLOT(adjustGrain()) );
365  QToolTip::add( adjustGrainButton, tr("Blur or sharpen image") );
366 
367  QLabel* adjustGrainLabel = new QLabel( tr("Grain..."), manualEnhanceControlsFrame );
368  adjustGrainLabel->setFont( smallerFont );
369 
370  //Place manual enhance controls in grid
371  Q3GridLayout* manualEnhanceControlsGrid = new Q3GridLayout( manualEnhanceControlsFrame, 2, 3, 0 );
372  manualEnhanceControlsGrid->setSpacing(TIGHT_WIDGET_SPACING);
373  manualEnhanceControlsGrid->addWidget( tuneLevelsButton, 0, 0, Qt::AlignHCenter );
374  manualEnhanceControlsGrid->addWidget( tuneLevelsLabel, 1, 0, Qt::AlignHCenter );
375  manualEnhanceControlsGrid->setColSpacing( 1, WIDGET_SPACING );
376  manualEnhanceControlsGrid->addWidget( adjustGrainButton, 0, 2, Qt::AlignHCenter );
377  manualEnhanceControlsGrid->addWidget( adjustGrainLabel, 1, 2, Qt::AlignHCenter );
378  //--------------------
379 
380  //Place enhance controls in a grid
381  Q3GridLayout* enhanceControlsGrid = new Q3GridLayout( enhanceControlsFrame, 4, 2, 0 );
382  enhanceControlsGrid->setSpacing(WIDGET_SPACING);
383  enhanceControlsGrid->addWidget( autoEnhanceControlsFrame, 0, 0, Qt::AlignHCenter );
384  enhanceControlsGrid->addWidget( manualEnhanceControlsFrame, 1, 0, Qt::AlignHCenter );
385  enhanceControlsGrid->setRowStretch( 0, 1 );
386  enhanceControlsGrid->setRowStretch( 3, 1 );
387 
388  //----------
389  //Effects Controls
390  //----------
391  Q3Frame* manipulateControlsFrame = new Q3Frame( manipulateControls, "manipulateControlsFrame" );
392  //--
393  //Effects
394  effectsList = new QComboBox( manipulateControlsFrame );
395  effectsList->setFont( smallerFont );
396  connect( effectsList, SIGNAL(activated(int)), this, SLOT(selectEffect()) );
397 
398  int i;
399  for(i=0; i<NUM_MANIPULATIONS; i++)
400  {
401  switch(i)
402  {
403  case BW_EFFECT: effectsList->insertItem( tr("B + W") ); break;
404  case SEPIA_EFFECT: effectsList->insertItem( tr("Sepia") ); break;
405  case INVERT_EFFECT: effectsList->insertItem( tr("Invert") ); break;
406  case EMBOSS_EFFECT: effectsList->insertItem( tr("Emboss") ); break;
407  case MOSAIC_EFFECT: effectsList->insertItem( tr("Mosaic") ); break;
408  case PAINTING_EFFECT: effectsList->insertItem( tr("Painting") ); break;
409  case POINTILLISM_EFFECT: effectsList->insertItem( tr("Pointillism") ); break;
410  }
411  }
412 
413  //Apply effect button
414  applyEffectButton = new QPushButton( tr("Apply"), manipulateControlsFrame );
415  applyEffectButton->setFont( smallerFont );
416  connect( applyEffectButton, SIGNAL(clicked()), SLOT(applyEffect()) );
417 
418  //preview of seleted effect
419  effectPreview = new QLabel( manipulateControlsFrame );
420 
421  //Place effects controls in a grid
422  Q3GridLayout* manipulateControlsGrid = new Q3GridLayout( manipulateControlsFrame, 2, 2, 0 );
423  manipulateControlsGrid->setSpacing(TIGHT_WIDGET_SPACING);
424  manipulateControlsGrid->addWidget( effectsList, 0, 0 );
425  manipulateControlsGrid->addWidget( applyEffectButton, 1, 0, Qt::AlignHCenter );
426  manipulateControlsGrid->addMultiCellWidget( effectPreview, 0,1, 1,1, Qt::AlignHCenter );
427 
428  //make sure preview image always requires EFFECT_PREVIEW_WIDTH width so contorls don't
429  //move around when rotating photos
430  manipulateControlsGrid->setColSpacing(1, 85 );
431 }
432 //==============================================
434 //==============================================
436 //==============================================
438 {
439  //store photo and collection object handles
440  this->collection = collection;
441  this->photo = photo;
442 
443  //update visibility of prev and next buttons
444  previousButton->setInvisible( photo->getPrev() == NULL );
445  nextButton->setInvisible( photo->getNext() == NULL );
446 
447  //reset combo menu's back to first entries
448  aspectRatios->setCurrentItem(0);
449  effectsList->setCurrentItem(0);
450 
451  //reset selectionRotated bool to false
452  selectionRotated = false;
453 
454  //update view of photo
456 
457  //created effect preview image
458  effectPreviewImageFilename = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() +
459  "/effectPreviewImage.jpg";
461  selectEffect();
462 
463  //get full size photo dimensions
465 
466  //get display size photo dimensions
468 
469  //disable the crop and reset buttons
470  cropButton->setEnabled( false );
472 }
473 //==============================================
475 {
476  Photo* prevPhoto = photo->getPrev();
477 
478  if( prevPhoto != NULL &&
479  prevPhoto != photo )
480  { showNextPrevFirstLastPhoto( prevPhoto ); }
481 }
482 //==============================================
484 {
485  Photo* nextPhoto = photo->getNext();
486 
487  if( nextPhoto != NULL &&
488  nextPhoto != photo )
489  { showNextPrevFirstLastPhoto( nextPhoto ); }
490 }
491 //==============================================
493 {
494  Photo* firstPhoto = collection->getFirst();
495 
496  if(firstPhoto != photo)
497  { showNextPrevFirstLastPhoto( firstPhoto ); }
498 }
499 //==============================================
501 {
502  Photo* lastPhoto = collection->getLast();
503 
504  if(lastPhoto != photo)
505  { showNextPrevFirstLastPhoto( lastPhoto ); }
506 }
507 //==============================================
509 {
510  //set busy pointer
511  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
512  qApp->processEvents();
513 
514  //reset photo object handle
515  photo = newPhoto;
516 
517  //reset selectionRotated bool to false
518  selectionRotated = false;
519 
520  //update visibility of prev and next buttons
521  previousButton->setInvisible( photo->getPrev() == NULL );
522  nextButton->setInvisible( photo->getNext() == NULL );
523 
524  //update view of photo
526 
527  //created effect preview image
528  effectPreviewImageFilename = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() + "/effectPreviewImage.jpg";
530  selectEffect();
531 
532  //get full size photo dimensions
534 
535  //get display size photo dimensions
537 
538  //auto select region if custom not selected, else select nothing
539  if(aspectRatios->currentItem() != 0)
540  { selectAspectRatio(); }
541  else
542  { selectionInterface->setSelection( QPoint(-1,-1), QPoint(-1, -1) ); }
543 
544  //emit signal that photo state possibly has changed
545  emit photoModified();
546 
547  //remove busy cursor
548  qApp->restoreOverrideCursor();
549  qApp->processEvents();
550 }
551 //==============================================
553 {
555 }
556 //==============================================
558 {
560 }
561 //==============================================
563 {
564  rotateFlip( FLIP_H );
565 }
566 //==============================================
568 {
569  rotateFlip( FLIP_V );
570 }
571 //==============================================
573 {
574  //set busy pointer
575  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
576  qApp->processEvents();
577 
578  //disable user input
580 
581  //rotate image, bail if rotation fails
582  QString editedImagePath = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() + "/editedImage.jpg";
583  transformImage( photo->getImageFilename(), editedImagePath, rotationFlipType );
584 
585  //apply changes to photo
586  photo->setImage( editedImagePath );
587 
588  //Reload photo view
589  bool aspectRatioChanged = ( rotationFlipType == ROTATE_90 || rotationFlipType == ROTATE_270 );
590  selectionInterface->setPhoto( editedImagePath, aspectRatioChanged );
591 
592  //update image dimension variables
594 
595  //get display size photo dimensions
597 
598  //reapply selected aspect ratio selection if aspect ratio changed
599  if( aspectRatioChanged )
600  {
601  //reset selectionRotated bool to false
602  selectionRotated = false;
604  }
605 
606  //update effect preview
608  selectEffect();
609 
610  //emit modified signal
611  emit photoModified();
612 
613  //enable user input
615 
616  //remove busy cursor
617  qApp->restoreOverrideCursor();
618  qApp->processEvents();
619 }
620 //==============================================
622 {
623  //reset display resolution
624  aspectRatioValues[displayResolutionIndex] = qApp->desktop()->screenGeometry().size();
625 
626  //if user is currently constraining the current selection then reset to fit new display resolution
627  if(aspectRatios->currentItem() == displayResolutionIndex )
628  { selectAspectRatio(); }
629 }
630 //==============================================
632 {
633  //find selection, if empty bail!
634  QPoint topLeft, bottomRight;
635  if (!findSelection(topLeft, bottomRight) )
636  return;
637 
638  //set busy cursor
639  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
640 
641  //disable user input
643 
644  //crop image
646  true );
647 
648  //enable user input
650 
651  //remove busy cursor
652  qApp->restoreOverrideCursor();
653 }
654 //==============================================
656 {
657  //set busy cursor
658  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
659  qApp->processEvents();
660 
661  //disable user input
663 
664  //enhance image
666  layout->getWindow()->getStatus() ),
667  false );
668 
669  //enable user input
671 
672  //remove busy cursor
673  qApp->restoreOverrideCursor();
674  qApp->processEvents();
675 }
676 //==============================================
678 {
679  //set busy cursor
680  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
681  qApp->processEvents();
682 
683  //disable user input
685 
686  //improve color balance
688  layout->getWindow()->getStatus() ),
689  false );
690 
691  //enable user input
693 
694  //remove busy cursor
695  qApp->restoreOverrideCursor();
696  qApp->processEvents();
697 }
698 //==============================================
700 {
701  //find selection, if empty bail!
702  QPoint topLeft, bottomRight;
703  if (!findSelection(topLeft, bottomRight) )
704  return;
705 
706  //set busy cursor
707  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
708  qApp->processEvents();
709 
710  //disable user input
712 
713  //remove redeye image
716  layout->getWindow()->getStatus() ),
717  true );
718 
719  //enable user input
721 
722  //remove busy cursor
723  qApp->restoreOverrideCursor();
724  qApp->processEvents();
725 }
726 //==============================================
728 {
729  //load photo in histogram editor
730  //if changes took place update image
731  HistogramEditor editor( photo->getImageFilename(), this);
732  if( editor.exec() )
733  {
734  //set busy cursor
735  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
736  qApp->processEvents();
737 
738  //disable user input
740 
741  //update image
742  applyImageUpdate( editor.getModifiedImage(), false );
743 
744  //enable user input
746 
747  //remove busy cursor
748  qApp->restoreOverrideCursor();
749  qApp->processEvents();
750  }
751 }
752 //==============================================
754 {
755  //load photo in grain editor
756  //if changes took place update image
757  GrainEditor editor( photo->getImageFilename(), this);
758  if( editor.exec() )
759  {
760  //set busy cursor
761  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
762  qApp->processEvents();
763 
764  //disable user input
766 
767  //update image
768  applyImageUpdate( editor.getModifiedImage(), false );
769 
770  //enable user input
772 
773  //remove busy cursor
774  qApp->restoreOverrideCursor();
775  qApp->processEvents();
776  }
777 }
778 //==============================================
780 {
781  //apply effect on preview image
783 
784  //bail if generated preview image failed
785  if( editedImage == NULL ) return;
786 
787  //refresh displayed preview image
788  effectPreview->setPixmap( QPixmap(*editedImage) );
789  delete editedImage;
790  editedImage = NULL;
791 }
792 //==============================================
794 {
795  //--------------------------------
796  //Get any manipulation options if needed
797  ManipulationOptions* options = NULL;
798  if( effectsList->currentItem() == MOSAIC_EFFECT )
799  {
800  MosaicOptionsDialog optionsDialog(this);
801  //user accepted so get selected options
802  if( optionsDialog.exec() )
803  {
804  //constructing the tiles list can unfortunately be quite slow so show a preparing tiles message
805  //and busy icon while getting the options chosen
806  layout->getWindow()->getStatus()->showProgressBar( QString(tr("Preparing Tiles")), 100 );
807  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
808  qApp->processEvents();
809  options = optionsDialog.getOptions();
810  qApp->restoreOverrideCursor();
811  }
812  //user hit cancel so bail
813  else
814  { return; }
815  }
816  else
817  { options = new ManipulationOptions( layout->getWindow()->getStatus() ); }
818  //--------------------------------
819  //Disable user input
821  applyEffectButton->setEnabled(false);
822  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
823  qApp->processEvents();
824  //--------------------------------
825  //Apply effect
826  QImage* editedImage = applyEffect( photo->getImageFilename(), options );
827  applyImageUpdate( editedImage, false );
828  delete options; options = NULL;
829  //--------------------------------
830  //Remove status bar if present and reenable user input
831  layout->getWindow()->getStatus()->setStatus( "" );
833  applyEffectButton->setEnabled(true);
834  qApp->restoreOverrideCursor();
835  qApp->processEvents();
836  //--------------------------------
837 }
838 //==============================================
839 QImage* EditingInterface::applyEffect(QString filename, ManipulationOptions* options)
840 {
841  //apply effect
842  QImage* effectedImage = NULL;
843  switch( effectsList->currentItem() )
844  {
845  case BW_EFFECT: effectedImage = blackWhiteEffect( filename, options ); break;
846  case SEPIA_EFFECT: effectedImage = sepiaEffect( filename, options ); break;
847  case INVERT_EFFECT: effectedImage = invertEffect( filename, options ); break;
848  case EMBOSS_EFFECT: effectedImage = embossEffect( filename, options ); break;
849  case PAINTING_EFFECT: effectedImage = oilPaintingEffect( filename, options ); break;
850  case POINTILLISM_EFFECT: effectedImage = pointillismEffect( filename, options ); break;
851  case MOSAIC_EFFECT: effectedImage = mosaicEffect( filename, (MosaicOptions*) options ); break;
852  }
853 
854  //return effected image
855  return effectedImage;
856 }
857 //==============================================
858 void EditingInterface::applyImageUpdate(QImage* editedImage, bool resetSelection)
859 {
860  //skip apply step if pointer is null. this usually means
861  //no modifications were made (for example: no red eyes were detected)
862  if(editedImage == NULL)
863  {
864  //sometimes the user instructs the program to modify an image in a way
865  //where no real changes are actually necessary. case in point, red eye reduction
866  //on a region where there is no red stuff at all! in order to be consistant, if
867  //the user is expecting the selection to be reset then always reset it! this
868  //normally occurs below when resetting the photo but we'll do it here
869  //since resetting the photo will not take place
870  if(resetSelection)
871  {
873  }
874 
875  return;
876  }
877 
878  //construct edited image path
879  QString editedImagePath = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() + "/editedImage.jpg";
880 
881  //save edited image to temporary location
882  //TODO: EXIF information is lost at this point, Qt does not support
883  //storing exif information, but perhaps a 2nd pass can be made on the file
884  //where exif info is added using libjpeg functions?
885  editedImage->save( editedImagePath, "JPEG", 95 );
886  delete editedImage;
887  editedImage = NULL;
888 
889  //apply changes to photo
890  photo->setImage( editedImagePath );
891 
892  //Reload photo view
893  selectionInterface->setPhoto( editedImagePath, resetSelection );
894 
895  //If we're resetting the selection (due to cropping), reset the
896  //selection rotated bit as well
897  if( resetSelection ) { selectionRotated = false; }
898 
899  //update image dimension variables
901 
902  //get display size photo dimensions
904 
905  //update effect preview
907  selectEffect();
908 
909  //emit modified signal
910  emit photoModified();
911 }
912 //==============================================
914 {
915  //exit edit mode
916  layout->organize();
917 }
918 //==============================================
920 {
921  //get raw selection in display coordinates
922  selectionInterface->getSelection(topLeft, bottomRight);
923 
924  //if range is empty then retrun false
925  if(topLeft.x() >= bottomRight.x() ||
926  topLeft.y() >= bottomRight.y())
927  return false;
928 
929  //return success
930  return true;
931 }
932 //==============================================
934 {
935  //crop button is enabled only when a portion of the image is selected
936  QPoint topLeft, bottomRight;
937  bool selectionPresent = findSelection(topLeft,bottomRight);
938 
939  cropButton->setEnabled( selectionPresent );
940  redEyeReductionButton->setEnabled( selectionPresent );
941 }
942 //==============================================
944 {
945  //change aspect ratio combo box to custom
946  aspectRatios->setCurrentItem(0);
947 }
948 //==============================================
950 {
951  topLeft.setX(0);
952  topLeft.setY(0);
953  bottomRight.setX(imageWidth - 1);
954  bottomRight.setY(imageHeight - 1);
955 }
956 //==============================================
958 {
959  //next handle additional keys
960  switch( e->key() )
961  {
962  //apply changes and exit
963  case Qt::Key_Escape:
964  returnAction();
965  break;
966  case Qt::Key_PageUp:
967  showPrevPhoto();
968  break;
969  case Qt::Key_PageDown:
970  showNextPhoto();
971  break;
972  case Qt::Key_Home:
973  showFirstPhoto();
974  break;
975  case Qt::Key_End:
976  showLastPhoto();
977  break;
978  case Qt::Key_R:
979  if(e->state() & Qt::ControlModifier)
980  rotateRight();
981  break;
982  case Qt::Key_L:
983  if(e->state() & Qt::ControlModifier)
984  rotateLeft();
985  break;
986  case Qt::Key_F:
987  if(e->state() & Qt::ControlModifier)
988  {
989  if( e->state() & Qt::AltModifier )
990  flipVertical();
991  else
992  flipHorizontal();
993  }
994  break;
995  default:
996  e->ignore();
997  }
998 }
999 //==============================================
1001 {
1002  if(photo == NULL)
1003  return false;
1004  else
1005  return photo->revertPossible();
1006 }
1007 //==============================================
1009 {
1010  //if current photo not revertable immediately bail
1011  if( ! currentPhotoRevertable() ) return;
1012 
1013  //set busy cursor
1014  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
1015 
1016  //disable user input
1018 
1019  //get current and reverted image sizes and compare to see if size has changed.
1020  //if so reset selected region
1021  int origWidth, origHeight;
1022  getImageSize( photo->originalImageFilename(), origWidth, origHeight );
1023  bool resetSelection = (origWidth != imageWidth) || (origHeight != imageHeight);
1024 
1026  photo->revertPhoto();
1027 
1028  //Reload photo view
1029  selectionInterface->setPhoto( photo->getImageFilename(), resetSelection );
1030 
1031  //update image dimension variables
1033 
1034  //get display size photo dimensions
1036 
1037  //update effect preview
1039  selectEffect();
1040 
1041  //emit modified signal
1042  emit photoModified();
1043 
1044  //enable user input
1046 
1047  //remove busy cursor
1048  qApp->restoreOverrideCursor();
1049 }
1050 //==============================================
1052 {
1053  //always pass off focus even to selection interface so it can get key strokes
1054  selectionInterface->setFocus();
1055 }
1056 //==============================================
1058 {
1059  //invert rotate bool
1061 
1062  //rotate custom selection in place, scale/shift if necessary to keep on image
1063  if(aspectRatios->currentItem() == 0)
1064  {
1065  //get cur selection
1066  QPoint curTopLeft, curBottomRight;
1067  selectionInterface->getSelection(curTopLeft, curBottomRight);
1068 
1069  //find center
1070  QPoint selectionCenter = QPoint( ( curTopLeft.x() + curBottomRight.x() ) / 2,
1071  ( curTopLeft.y() + curBottomRight.y() ) / 2 );
1072 
1073  //scale rotated width/height to fit image
1074  int newWidth = curBottomRight.y() - curTopLeft.y() + 1;
1075  int newHeight =curBottomRight.x() - curTopLeft.x() + 1;
1076  calcScaledImageDimensions( newWidth, newHeight,
1078  newWidth, newHeight );
1079 
1080  //center new selection over old selection
1081  QPoint topLeft = QPoint( selectionCenter.x() - newWidth/2,
1082  selectionCenter.y() - newHeight/2 );
1083  QPoint bottomRight = QPoint( topLeft.x() + newWidth - 1,
1084  topLeft.y() + newHeight - 1 );
1085 
1086  //shift selection area to not go outside image boundary
1087  if(topLeft.x() < 0)
1088  {
1089  bottomRight.setX( bottomRight.x() - topLeft.x() );
1090  topLeft.setX( 0 );
1091  }
1092 
1093  if(topLeft.y() < 0)
1094  {
1095  bottomRight.setY( bottomRight.y() - topLeft.y() );
1096  topLeft.setY( 0 );
1097  }
1098 
1099  if(bottomRight.x() >= imageWidth )
1100  {
1101  topLeft.setX( topLeft.x() - ( bottomRight.x() - imageWidth + 1 ) );
1102  bottomRight.setX( imageWidth - 1 );
1103  }
1104 
1105  if(bottomRight.y() >= imageHeight )
1106  {
1107  topLeft.setY( topLeft.y() - ( bottomRight.y() - imageHeight + 1 ) );
1108  bottomRight.setY( imageHeight - 1 );
1109  }
1110 
1111  //select new region
1112  selectionInterface->setSelection(topLeft, bottomRight);
1113  }
1114  //else call selectAspectRatio passing true that we're
1115  //using the rotated version of the current aspect ratio
1116  else
1117  {
1118  selectAspectRatio();
1119  }
1120 }
1121 //==============================================
1123 {
1124  //if user selected "custom" don't modify current selection
1125  if( aspectRatios->currentItem() == 0 ) return;
1126 
1127  //get default aspect ratio
1128  QSize aspectRatio = aspectRatioValues[ aspectRatios->currentItem() ];
1129 
1130  //automatically rotate default if current photo is taller than wide
1131  if( imageHeight > imageWidth )
1132  { aspectRatio = QSize( aspectRatio.height(), aspectRatio.width() ); }
1133 
1134  //exchange aspect ratio dimensions if we're in rotated selection mode
1135  if( selectionRotated )
1136  { aspectRatio = QSize( aspectRatio.height(), aspectRatio.width() ); }
1137 
1138  //determine selected width and height;
1139  int selectedWidth = 0;
1140  int selectedHeight = 0;
1141 
1142  //display resolution, match exactly or scale down
1143  if(aspectRatios->currentItem() == displayResolutionIndex)
1144  {
1145  //select region less than or equal to display resolution while maintaining aspect ratio
1146  selectedWidth = aspectRatio.width();
1147  selectedHeight = aspectRatio.height();
1148  calcScaledImageDimensions( selectedWidth, selectedHeight,
1150  selectedWidth, selectedHeight );
1151  }
1152  //else use aspect ratio directly as a ratio
1153  else
1154  {
1155  //select region using same aspect ratio
1156  selectedWidth = imageWidth;
1157  selectedHeight = (int) (((double) (imageWidth * aspectRatio.height()) ) / aspectRatio.width() );
1158  calcScaledImageDimensions( selectedWidth, selectedHeight,
1160  selectedWidth, selectedHeight );
1161 
1162  }
1163 
1164  //get current selection boundary
1165  QPoint curTopLeft, curBottomRight;
1166  selectionInterface->getSelection( curTopLeft, curBottomRight );
1167 
1168  //get current selection center
1169  QPoint curCenter;
1170  curCenter.setX( (curTopLeft.x() + curBottomRight.x()) / 2 );
1171  curCenter.setY( (curTopLeft.y() + curBottomRight.y()) / 2 );
1172 
1173  //if center is off image (no previous selection) then
1174  //fix center to center of image
1175  if( curCenter.x() < 0 || curCenter.y() < 0 )
1176  {
1177  curCenter.setX( imageWidth/2 );
1178  curCenter.setY( imageHeight/2 );
1179  }
1180 
1181  //attempt to center new selection overold selection, only
1182  //offset if necessary
1183  QPoint newTopLeft, newBottomRight;
1184 
1185  newTopLeft.setX( curCenter.x() - selectedWidth/2 );
1186  newTopLeft.setY( curCenter.y() - selectedHeight/2 );
1187 
1188  //push right/down if necessary
1189  if( newTopLeft.x() < 0 ) newTopLeft.setX( 0 );
1190  if( newTopLeft.y() < 0 ) newTopLeft.setY( 0 );
1191 
1192  //push left/up if necessary
1193  newBottomRight.setX( newTopLeft.x() + selectedWidth - 1 );
1194  if( newBottomRight.x() >= imageWidth )
1195  {
1196  newBottomRight.setX( imageWidth-1 );
1197  newTopLeft.setX( newBottomRight.x() - selectedWidth + 1 );
1198  }
1199 
1200  newBottomRight.setY( newTopLeft.y() + selectedHeight - 1 );
1201  if( newBottomRight.y() >= imageHeight )
1202  {
1203  newBottomRight.setY( imageHeight-1 );
1204  newTopLeft.setY( newBottomRight.y() - selectedHeight + 1 );
1205  }
1206 
1207  //select region
1208  selectionInterface->setSelection(newTopLeft, newBottomRight,
1209  maxDimensions[aspectRatios->currentItem()] );
1210 }
1211 //==============================================
1213 {
1214  //instruct user to select a horizontal or vertical line in the image by
1215  //beginning draw line mode in the selection interface
1216  correctTiltButton->setEnabled( false );
1218 }
1219 //==============================================
1220 void EditingInterface::finishCorrectTilt( QPoint p1, QPoint p2 )
1221 {
1222  //if either point is invalid ignore action
1223  if( p1.x() == -1 || p2.x() == -1 )
1224  {
1225  //reenable tilt button
1226  correctTiltButton->setEnabled( true );
1227  return;
1228  }
1229 
1230  //set busy cursor
1231  qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
1232 
1233  //disable user input
1235 
1236  //rotate image by determining correct angle from two points
1237  QImage* rotatedImage = correctImageTilt( photo->getImageFilename(), p1, p2,
1238  layout->getWindow()->getStatus() );
1239  applyImageUpdate( rotatedImage, true );
1240 
1241  //reenable tilt button
1242  correctTiltButton->setEnabled( true );
1243 
1244  //enable user input
1246 
1247  //remove busy cursor
1248  qApp->restoreOverrideCursor();
1249 }
1250 //==============================================
1251 
1252 
ClickableLabel * nextButton
QPoint bottomRight
QPoint topLeft
void crop()
Cropped image.
void applyImageUpdate(QImage *editedImage, bool resetSelection)
Applies update to image.
QImage * correctImageTilt(QString filename, QPoint p1, QPoint p2, StatusWidget *status)
Definition: tilt.cpp:103
QString getImageFilename()
Gets the image filename.
Definition: photo.cpp:192
void enhanceContrast()
Enhance image contrast.
Interface for adjusting image historgram using upper and lower bounds and bright and contrast control...
QString originalImageFilename()
orig filename
Definition: photo.cpp:572
A photo consists of a full size image, a smaller slide show image, a very small thumbnail image...
Definition: photo.h:44
int imageWidth
Dimension of photo in image coordinates.
TRANSFORM_CODE
Definition: imageTools.h:24
ClickableLabel * previousButton
Buttons for changing the shown image
void revertPhoto()
revert photo to original form
Definition: photo.cpp:557
void showPrevPhoto()
Show prev photo.
void adjustGrain()
Opens image grain editor.
QImage * mosaicEffect(QString filename, MosaicOptions *options)
Definition: mosaic.cpp:293
Top level widget, encapsulates the title widget, the layout widget, and the toolbar widget...
Definition: window.h:39
void showProgressBar(QString message, int numSteps)
Initializes the progress bar.
StatusWidget * getStatus()
returns a pointer to the status widget
Definition: window.cpp:198
QToolButton * correctTiltButton
The start tilt button is disabled while a line is being selected.
Subalbum * collection
========== Pointer to backend collection
void removeRedeye()
Applies redeye removal.
#define TIGHT_WIDGET_SPACING
Definition: config.h:32
void setPixmap(const QPixmap &p)
bool findSelection(QPoint &topLeft, QPoint &bottomRight)
Finds the selected region of the image.
void flipVertical()
Flip image vertically.
void rotateLeft()
Rotate image left 90 degrees.
QImage * sepiaEffect(QString filename, ManipulationOptions *options)
Definition: sepia.cpp:54
QImage * enhanceImageContrast(QString filename, StatusWidget *status)
Definition: contrast.cpp:88
void enterDrawLineMode()
enter draw line mode - used for tilt correction
void startCorrectTilt()
Enter correct image tilt mode.
Photo * getNext()
Returns next photo pointer.
Definition: photo.cpp:225
void tuneLevels()
Opens levels editor for manual histogram and brightness/contrast adjustments.
Displays list of subalbums and a particular subalbum layout.
Definition: layoutWidget.h:39
void colorBalance()
Improve color balance.
Interface for adjusting image grain by bluring and sharpening.
Definition: grainEditor.h:34
QImage * oilPaintingEffect(QString filename, ManipulationOptions *options)
Definition: painting.cpp:106
QString IMAGE_PATH
Definition: config.cpp:18
void setPhoto(QString imageFilename, bool resetSelection=true)
Updates displayed photo.
void keyPressEvent(QKeyEvent *e)
void rotateRight()
Rotate image right 90 degrees.
void setStatus(QString message)
Update message.
void revertCurrentPhoto()
reverts current photo and updates display
A clickable label.
Interface for choosing mosiac effect options.
bool setImage(QString imageName, QString slideshowName, QString thumbnailName)
Setup photo using preexisting full size, slideshow, and thumbnail images.
Definition: photo.cpp:105
QString effectPreviewImageFilename
Path to scaled down version of image for fast generation of previews of effects.
A subalbum contains photos.
Definition: subalbum.h:48
QComboBox * effectsList
List of effects that can be applied to photos.
QPushButton * applyEffectButton
The apply effect button is disabled when no effect has been chosen.
void showNextPhoto()
Show next photo.
void rotateFlip(TRANSFORM_CODE rotationFlipType)
Utility method for rotation + flip slots.
bool transformImage(QString fileIn, QString fileOut, TRANSFORM_CODE transformation)
Apply image transformation on image.
Definition: imageTools.cpp:112
void releaseInput()
void applyEffect()
Apply selected effect.
void getSelection(QPoint &topLeft, QPoint &bottomRight)
Returns the current selected coordinates (actual slideshow image space, aka not including buffered wh...
void finishCorrectTilt(QPoint p1, QPoint p2)
Finish correcting and image&#39;s tilt.
void rotateSelection()
Rotate current selection.
QImage * removeRedeyeRegions(QString filename, QPoint topLeftExtreme, QPoint bottomRightExtreme, StatusWidget *statusWidget)
Definition: redEye.cpp:206
SelectionInterface * selectionInterface
This widget scales and displays the photo to fit the available screen space, and provides extensive s...
void setEnabled(bool val)
bool scaleImage(QString fileIn, QString fileOut, int newWidth, int newHeight)
Scale image and save copy to disk.
Definition: imageTools.cpp:157
#define WIDGET_SPACING
Definition: config.h:31
ClickableLabel * redEyeReductionButton
The red eye reduction button is disabled when no selection is present.
void getDisplaySize(int &width, int &height)
returns the current photo display size (in screen pixels)
void selectAspectRatio()
Aspect ratio selection changed.
void setSelection(QPoint topLeft, QPoint bottomRight, double cropMaxDimen=-1.0)
Sets the current selection cropMaxDimen specifies the idealized dimension in dominant direction in in...
Photo * getFirst()
Returns first photo in subalbum.
Definition: subalbum.cpp:100
MosaicOptions * getOptions()
returns a populate options object
bool getImageSize(const char *filename, QSize &size)
Get image dimensions.
Definition: imageTools.cpp:192
Display widget for photos. Used by the PhotoEditWidget.
QComboBox * aspectRatios
Widget for selection aspect ratio to crop to.
void flipHorizontal()
Flip image horizontally.
bool selectionRotated
state variable indicating if the user wants to use a rotate aspect ratio
Photo * photo
Pointer to backend photo.
QImage * embossEffect(QString filename, ManipulationOptions *options)
Definition: emboss.cpp:85
QImage * cropImage(QString filename, QPoint topLeft, QPoint bottomRight)
Definition: crop.cpp:36
void setPhoto(Subalbum *collection, Photo *photo)
Sets the photo pointer and constructs scaled qimage&#39;s for painting.
QLabel * effectPreview
Label that shows preview of effect.
void selectNone()
selects none of the image
QToolButton * cropButton
The crop buttons is disabled when no seletion is present.
void screenResolutionChanged()
Update recorded screen resolution and selection if necessary.
Window * getWindow()
Returns a pointer to the window.
int displayResolutionIndex
Index for screen resolution, needed if this value pair changes during program executing.
#define EFFECT_PREVIEW_WIDTH
void showNextPrevFirstLastPhoto(Photo *newPhoto)
Utility method for show prev/next photos.
QSize * aspectRatioValues
array of common aspect ratios to crop to
#define EFFECT_PREVIEW_HEIGHT
void setInvisible(bool val)
LayoutWidget * layout
Pointer to the parent layout widget.
QImage * editedImage
QImage * pointillismEffect(QString filename, ManipulationOptions *)
void showFirstPhoto()
Show first photo.
QImage * blackWhiteEffect(QString filename, ManipulationOptions *options)
Definition: blackWhite.cpp:60
QImage * improveColorBalance(QString filename, StatusWidget *status)
Definition: color.cpp:92
void calcScaledImageDimensions(int origWidth, int origHeight, int idealWidth, int idealHeight, int &width, int &height)
Computes scale of image dimensions while respecting aspect ratio, equivalent to a QImage::scaleMin wi...
Definition: imageTools.cpp:39
Photo * getPhoto()
Returns a pointer to the currently selected photo.
EditingInterface(QWidget *parent=0, const char *name=0)
Constructs layout.
void selectAll(QPoint &topLeft, QPoint &bottomRight)
Return coordinates that select entire image.
Photo * getPrev()
Returns the previous photo pointer.
Definition: photo.cpp:224
void returnAction()
Exit editing interface.
QImage * invertEffect(QString filename, ManipulationOptions *)
Definition: invert.cpp:40
int displayWidth
Dimension of photo in display coordinates.
void showLastPhoto()
Show last photo.
void selectEffect()
Effect seletion changed.
Photo * getLast()
Returns last photo in subalbum.
Definition: subalbum.cpp:101
void organize()
Select organize tab.
bool revertPossible()
can photo be reverted to a differnt original form
Definition: photo.cpp:537