AlbumShaper  1.0a3
grainEditor.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 <qcombobox.h>
15 #include <qpushbutton.h>
16 #include <q3frame.h>
17 #include <qslider.h>
18 #include <qtooltip.h>
19 #include <qsizegrip.h>
20 //Added by qt3to4:
21 #include <Q3GridLayout>
22 #include <QPixmap>
23 #include <QKeyEvent>
24 
25 //Projectwide includes
26 #include "grainEditor.h"
29 #include "../blurSharpenSlider.h"
30 #include "../clickableLabel.h"
31 #include "../../config.h"
32 #include "../../backend/manipulations/blur.h"
33 #include "../../backend/manipulations/sharpen.h"
34 #include "../../backend/manipulations/edgeDetect.h"
35 #include "../../backend/tools/imageTools.h"
36 
37 #define SLIDER_RADIUS 50
38 
39 //==============================================
40 GrainEditor::GrainEditor( QString fileName, QWidget *parent, const char* name ) : QDialog(parent,name,true)
41 {
42  //record filename
43  this->fileName = fileName;
44 
45  //record original image size
46  getImageSize( fileName, origImageSize );
47 
48  //construct edges image
49  //speed up edge finding by scaling image down to < 800x600
50  scaleImage( fileName, edgesImage, 512, 384 );
51  EdgeDetect detector( &edgesImage );
52  clusterMap = detector.getClusterMap();
53  numRegions = detector.getNumClusters();
54 
55  Q3Frame* visibleFrame = new Q3Frame( this, "visible widgets" );
56  //--------------
57  //Preview frame
59  visibleFrame, "previewInterface" );
60  previewSelection = new QComboBox( visibleFrame, "previewSelction" );
61  previewSelection->insertItem( tr("Split View") );
62  previewSelection->insertItem( tr("Original Image") );
63  previewSelection->insertItem( tr("Adjusted Image") );
64  connect( previewSelection, SIGNAL(activated(int)), this, SLOT(selectPreviewImageType(int)) );
65  //--------------
66  //Controls frame
67  Q3Frame* controlsFrame = new Q3Frame( visibleFrame, "controlsFrame" );
68 
69  QLabel* selectionLabel = new QLabel( tr("Region Shown in Detail:"),
70  controlsFrame, "selectionLabel" );
71 
73  controlsFrame,
74  "selectionPlacementInterface" );
75  //--
76  connect( previewInterface, SIGNAL( selectionChanged() ),
77  this, SLOT( previewResized() ) );
78  connect( selectionPlacementInterface, SIGNAL(placementChanged(QRect)),
79  previewInterface, SLOT(setSelection(QRect)) );
80  //--
81  boundariesSlider = new BlurSharpenSlider( Qt::Vertical, controlsFrame );
82  boundariesSlider->setMinValue( -SLIDER_RADIUS );
83  boundariesSlider->setMaxValue( SLIDER_RADIUS );
84  connect( boundariesSlider, SIGNAL(valueChanged(int)),
85  this, SLOT(generateAdjustedPreviewImage()) );
86 
87  boundariesIcon = new ClickableLabel( controlsFrame, "boundariesIcon" );
88  connect( boundariesIcon, SIGNAL(clicked()), SLOT(resetBoundaries()) );
89 
90 // boundariesIcon->setPixmap( QPixmap(QString(IMAGE_PATH)+"miscImages/boundaries.png") );
91 // QToolTip::add( boundariesSlider, tr("Blur/sharpen boundaries") );
92 // QToolTip::add( boundariesIcon, tr("Reset boundaries") );
93  boundariesIcon->setPixmap( QPixmap(QString(IMAGE_PATH)+"miscImages/blurSharpen.png") );
94  QToolTip::add( boundariesSlider, tr("Blur/Sharpen Image") );
95  QToolTip::add( boundariesIcon, tr("Reset") );
96  //--
97  /*
98  regionsSlider = new QSlider(Qt::Vertical, controlsFrame );
99  regionsSlider->setMinValue( -SLIDER_RADIUS );
100  regionsSlider->setMaxValue( SLIDER_RADIUS );
101  connect( regionsSlider, SIGNAL(valueChanged(int)),
102  this, SLOT(generateAdjustedPreviewImage()) );
103  QToolTip::add( regionsSlider, tr("Blur/sharpen regions") );
104 
105  regionsIcon = new ClickableLabel( controlsFrame, "regionsIcon" );
106  regionsIcon->setPixmap( QPixmap(QString(IMAGE_PATH)+"miscImages/regions.png") );
107  connect( regionsIcon, SIGNAL(clicked()), SLOT(resetRegions()) );
108  QToolTip::add( regionsIcon, tr("Reset regions") );
109  */
110  //--
111  Q3GridLayout* controlsGrid = new Q3GridLayout( controlsFrame, 6, 4, 0 );
112  controlsGrid->setRowStretch( 0, 1 );
113 
114  controlsGrid->addMultiCellWidget( selectionLabel, 1,1, 0,3 );
115  controlsGrid->addMultiCellWidget( selectionPlacementInterface, 2,2, 0,3 );
116 
117  controlsGrid->addWidget( boundariesSlider, 3, 1 );
118  controlsGrid->addWidget( boundariesIcon, 4, 1 );
119 
120 // controlsGrid->addWidget( regionsSlider, 3, 2 );
121 // controlsGrid->addWidget( regionsIcon, 4, 2 );
122 
123  //make sure sliders have enough space so all slider units are settable
124  controlsGrid->setRowSpacing( 3, 2*SLIDER_RADIUS + 5) ;
125 
126  controlsGrid->setRowStretch( 5, 1 );
127  controlsGrid->setSpacing( WIDGET_SPACING );
128 
129  controlsGrid->setColStretch( 0, 1 );
130  controlsGrid->setColStretch( 3, 1 );
131  //--------------
132  //Dialog buttons:
133  buttonsFrame = new Q3Frame( visibleFrame, "dialogButtons" );
134 
135  QPushButton* applyButton = new QPushButton( tr("Apply"), buttonsFrame );
136  applyButton->setDefault(true);
137  applyButton->setFocus();
138  connect( applyButton, SIGNAL(clicked()), SLOT(applyAction()) );
139 
140  QPushButton* cancelButton = new QPushButton( tr("Cancel"), buttonsFrame );
141  connect( cancelButton, SIGNAL(clicked()), SLOT(reject()) );
142 
143  QPushButton* resetButton = new QPushButton( tr("Reset"), buttonsFrame );
144  connect( resetButton, SIGNAL(clicked()), SLOT(resetAction()) );
145 
146  Q3GridLayout* buttonsGrid = new Q3GridLayout( buttonsFrame, 1, 5, 0 );
147  buttonsGrid->setColStretch( 0, 1 );
148  buttonsGrid->addWidget( applyButton, 0, 1 );
149  buttonsGrid->addWidget( cancelButton, 0, 2 );
150  buttonsGrid->addWidget( resetButton, 0, 3 );
151  buttonsGrid->setColStretch( 4, 1 );
152  buttonsGrid->setSpacing( WIDGET_SPACING );
153  //--------------
154  //Top level grid
155  Q3GridLayout* mainGrid = new Q3GridLayout( visibleFrame, 3, 2, 0 );
156 
157  mainGrid->addWidget( previewInterface, 0,0 );
158  mainGrid->addWidget( previewSelection, 1,0, Qt::AlignHCenter );
159 
160  mainGrid->addMultiCellWidget( controlsFrame, 0,1, 1,1 );
161 
162  mainGrid->addMultiCellWidget( buttonsFrame, 2,2, 0,1 );
163 
164  mainGrid->setRowStretch( 0, 1 );
165  mainGrid->setColStretch( 0, 1 );
166 
167  mainGrid->setSpacing( WIDGET_SPACING );
168  mainGrid->setMargin( WIDGET_SPACING );
169 
170 
171  Q3GridLayout* invisibleGrid = new Q3GridLayout( this, 2, 1, 0 );
172  invisibleGrid->addWidget( visibleFrame, 0, 0 );
173  invisibleGrid->setRowStretch( 0, 1 );
174 
175  //PLATFORM_SPECIFIC_CODE
176  //windows users expect a grip, but qt doesn't put one in by default. we'll add
177  //it for them too. :-)
178 #if defined(Q_OS_WIN)
179  QSizeGrip* sizeGrip = new QSizeGrip( this );
180  invisibleGrid->addWidget( sizeGrip, 1, 0, Qt::AlignRight | Qt::AlignBottom );
181 #endif
182 
183 
184 
185 
186  //--------------
187  //Window caption
188  setCaption( tr("Grain Editor") );
189  //-------------------------------
190 }
191 //==============================================
193 //==============================================
195 {
196  //check if user has adjusted grain.
197  //if any changes have taken place call "accept", else "reject" so image is not
198  //updated and appear modified
199  if( boundariesSlider->value() != 0 )
200  //||
201  // regionsSlider->value() != 0 )
202  { accept(); }
203  else
204  { reject(); }
205 }
206 //==============================================
208 {
209  boundariesSlider->setValue( 0 );
210 }
211 //==============================================
213 {
214  //regionsSlider->setValue( 0 );
215 }
216 //==============================================
218 {
219  boundariesSlider->setValue( 0 );
220  //regionsSlider->setValue( 0 );
221 }
222 //==============================================
224 {
225  QImage* adjustedImage = new QImage(fileName);
226 
227  //convert to 32-bit depth if necessary
228  if( adjustedImage->depth() < 32 )
229  {
230  QImage* tmp = adjustedImage;
231  adjustedImage = new QImage( tmp->convertDepth( 32, Qt::AutoColor ) );
232  delete tmp; tmp=NULL;
233  }
234 
235  adjustImage( *adjustedImage, QPoint(0,0) );
236  return adjustedImage;
237 }
238 //==============================================
240 {
242 }
243 //==============================================
245 {
246  //reset selected region in selection placement interface
248 
249  //regenerate adjusted image and repaint
251 }
252 //==============================================
254 {
255  //get original image
256  QImage origImage = previewInterface->getOrigImage();
257 
258  //construct adjusted image
259  QImage adjustedImage = origImage.copy();
260  adjustImage( adjustedImage, previewInterface->getSelection().topLeft() );
261 
262  //set adjusted image
263  previewInterface->setAdjustedImage( adjustedImage );
264 }
265 //==============================================
266 void GrainEditor::adjustImage( QImage& image, QPoint offset )
267 {
268  //no adjustment - don't change the image at all
269  if( boundariesSlider->value() == 0 )//&&
270  //regionsSlider->value() == 0 )
271  { return; }
272 
273  //compute sigma
274  float boundariesSigma;
275  if( boundariesSlider->value() < 0 )
276  boundariesSigma = (80.0f * QABS(boundariesSlider->value()) ) / 255.0f;
277  else
278  boundariesSigma = (25.5f * QABS(boundariesSlider->value()) ) / 255.0f;
279 // float regionsSigma = (20.0f * QABS(regionsSlider->value()) ) / 255.0f;
280 
281 
282  //sharpen
283  if ( boundariesSlider->value() < 0 )
284  {
285  sharpenImage( image, boundariesSigma,
286  offset, origImageSize,
287  &edgesImage, true );
288  }
289  //blur
290  else if( boundariesSlider->value() > 0 )
291  {
292  blurImage( image, boundariesSigma );
293  }
294 
295  /*
296  //sharpen boundaries
297  if ( boundariesSlider->value() < 0 )
298  {
299  sharpenImage( image, boundariesSigma,
300  offset, origImageSize,
301  &edgesImage, true );
302  }
303  //blur boundaries
304  else if( boundariesSlider->value() > 0 )
305  {
306  blurImage( image, boundariesSigma,
307  offset, origImageSize,
308  &edgesImage, NULL, numRegions, true );
309  }
310 
311  //sharpen regions
312  if ( regionsSlider->value() < 0 )
313  {
314  sharpenImage( image, regionsSigma,
315  offset, origImageSize,
316  &edgesImage, false );
317  }
318  //blur regions
319  else if( regionsSlider->value() > 0 )
320  {
321  blurImage( image, regionsSigma,
322  offset, origImageSize,
323  &edgesImage, clusterMap, numRegions, false );
324  }
325  */
326 
327 }
328 //==============================================
329 void GrainEditor::keyPressEvent(QKeyEvent *e)
330 {
331  if(e->key() == Qt::Key_Control )
332  {
333  PREVIEW_MODE curMode = (PREVIEW_MODE) previewSelection->currentItem();
334  if(curMode == ORIGINAL_IMAGE)
336  else if(curMode == ADJUSTED_IMAGE)
338  else
340  }
341  else { QDialog::keyPressEvent(e); }
342 }
343 //==============================================
345 {
346  if(e->key() == Qt::Key_Control )
347  {
349  false );
350  }
351  else { QDialog::keyReleaseEvent(e); }
352 }
353 //==============================================
354 
355 
356 
int * getClusterMap()
Definition: edgeDetect.cpp:244
void previewResized()
handle resize preview signals
void adjustImage(QImage &image, QPoint offset)
void blurImage(QImage &image, float sigma)
Definition: blur.cpp:94
QString fileName
Definition: grainEditor.h:81
int * clusterMap
Definition: grainEditor.h:90
void generateAdjustedPreviewImage()
generate and set adjusted image
QImage edgesImage
Definition: grainEditor.h:87
void setPixmap(const QPixmap &p)
#define SLIDER_RADIUS
Definition: grainEditor.cpp:37
void keyPressEvent(QKeyEvent *e)
A selection region placement interface.
QString IMAGE_PATH
Definition: config.cpp:18
void selectPreviewImageType(int selection)
updates preview image
QImage * getModifiedImage()
get modified image that resulted from adjustments
A clickable label.
ClickableLabel * boundariesIcon
Definition: grainEditor.h:104
void sharpenImage(QImage &image, float sigma, QPoint offset, QSize fullImageRes, QImage *edgeImage, bool blurEdges)
Definition: sharpen.cpp:95
int numRegions
Definition: grainEditor.h:91
QImage & getOrigImage()
returns orig image object
SelectionPlacementInterface * selectionPlacementInterface
Interface for placing selection.
Definition: grainEditor.h:97
void setSelectedRegion(QRect selection)
Set the select region using image space coordinates.
bool scaleImage(QString fileIn, QString fileOut, int newWidth, int newHeight)
Scale image and save copy to disk.
Definition: imageTools.cpp:157
BlurSharpenSlider * boundariesSlider
Grain slider.
Definition: grainEditor.h:103
#define WIDGET_SPACING
Definition: config.h:31
void resetBoundaries()
reset blur/sharpen of object boundaries
bool getImageSize(const char *filename, QSize &size)
Get image dimensions.
Definition: imageTools.cpp:192
QComboBox * previewSelection
Definition: grainEditor.h:99
void setPreviewMode(PREVIEW_MODE mode, bool forceDrawLabel=false)
Sets preview mode.
PREVIEW_MODE
current preview mode
void resetRegions()
reset blur/sharpen of regions
int getNumClusters()
Definition: edgeDetect.cpp:227
PanningPreviewInterface * previewInterface
Preview image.
Definition: grainEditor.h:94
QSize origImageSize
Definition: grainEditor.h:84
void setAdjustedImage(QImage adjustedImage)
sets adjusted image and repaints
Q3Frame * buttonsFrame
Definition: grainEditor.h:100
void applyAction()
check for changes to settings, if so
void resetAction()
resets image grain to original state
GrainEditor(QString filename, QWidget *parent=0, const char *name=0)
Constructs layout.
Definition: grainEditor.cpp:40
void keyReleaseEvent(QKeyEvent *e)