7
7
* Description : Red eyes correction tool for image editor
9
9
* Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
10
* Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
10
* Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
12
12
* This program is free software; you can redistribute it
13
13
* and/or modify it under the terms of the GNU General
70
71
ImageEffect_RedEye::ImageEffect_RedEye(QWidget* parent)
71
: Digikam::ImageDlgBase(parent, i18n("Red Eye Reduction"),
72
: Digikam::ImageDlgBase(parent, i18n("Red Eye Reduction"), "redeye", false)
74
m_destinationPreviewData = 0L;
74
m_destinationPreviewData = 0;
75
75
setHelp("redeyecorrectiontool.anchor", "digikam");
77
77
m_previewWidget = new Digikam::ImageWidget("redeye Tool Dialog", plainPage(),
92
92
m_channelCB->insertItem( i18n("Red") );
93
93
m_channelCB->insertItem( i18n("Green") );
94
94
m_channelCB->insertItem( i18n("Blue") );
95
QWhatsThis::add( m_channelCB, i18n("<p>Select here the histogram channel to display:<p>"
95
QWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
96
96
"<b>Luminosity</b>: display the image's luminosity values.<p>"
97
97
"<b>Red</b>: display the red image channel values.<p>"
98
98
"<b>Green</b>: display the green image channel values.<p>"
102
102
m_scaleBG->setExclusive(true);
103
103
m_scaleBG->setFrameShape(QFrame::NoFrame);
104
104
m_scaleBG->setInsideMargin(0);
105
QWhatsThis::add( m_scaleBG, i18n("<p>Select here the histogram scale.<p>"
105
QWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
106
106
"If the image's maximum counts are small, you can use the linear scale.<p>"
107
107
"The logarithmic scale can be used when the maximal counts are big "
108
108
"to show all values (small and large) on the graph."));
110
110
QPushButton *linHistoButton = new QPushButton( m_scaleBG );
111
111
QToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
112
112
m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
114
114
QString directory = KGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
115
115
linHistoButton->setPixmap( QPixmap( directory + "histogram-lin.png" ) );
116
116
linHistoButton->setToggleButton(true);
118
118
QPushButton *logHistoButton = new QPushButton( m_scaleBG );
119
119
QToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
120
120
m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
121
121
KGlobal::dirs()->addResourceType("histogram-log", KGlobal::dirs()->kde_default("data") + "digikam/data");
122
122
directory = KGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
123
123
logHistoButton->setPixmap( QPixmap( directory + "histogram-log.png" ) );
124
logHistoButton->setToggleButton(true);
124
logHistoButton->setToggleButton(true);
126
126
QHBoxLayout* l1 = new QHBoxLayout();
127
127
l1->addWidget(label1);
128
128
l1->addWidget(m_channelCB);
129
129
l1->addStretch(10);
130
130
l1->addWidget(m_scaleBG);
132
gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
134
132
// -------------------------------------------------------------
139
137
"of the selected image channel. It is "
140
138
"updated upon setting changes."));
141
139
QLabel *space = new QLabel(histoBox);
142
space->setFixedHeight(1);
143
m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, histoBox );
144
m_hGradient->setColors( QColor( "black" ), QColor( "white" ) );
146
gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
140
space->setFixedHeight(1);
141
m_hGradient = new Digikam::ColorGradientWidget(Digikam::ColorGradientWidget::Horizontal, 10, histoBox);
142
m_hGradient->setColors(QColor("black"), QColor("white"));
148
144
// -------------------------------------------------------------
155
151
"Low values will select more red color pixels (agressive correction), high "
156
152
"values less (mild correction). Use low value if eye have been selected "
157
153
"exactly. Use high value if other parts of the face are also selected."));
158
gridSettings->addMultiCellWidget(m_thresholdLabel, 3, 3, 0, 4);
159
gridSettings->addMultiCellWidget(m_redThreshold, 4, 4, 0, 4);
161
155
m_smoothLabel = new QLabel(i18n("Smooth:"), gboxSettings);
162
156
m_smoothLevel = new KIntNumInput(gboxSettings);
163
157
m_smoothLevel->setRange(0, 5, 1, true);
164
158
m_smoothLevel->setValue(1);
165
QWhatsThis::add(m_smoothLevel, i18n("<p>Sets the smoothness value to blur the border "
159
QWhatsThis::add(m_smoothLevel, i18n("<p>Sets the smoothness value when blurring the border "
166
160
"of the changed pixels. "
167
161
"This leads to a more naturally looking pupil."));
168
gridSettings->addMultiCellWidget(m_smoothLabel, 5, 5, 0, 4);
169
gridSettings->addMultiCellWidget(m_smoothLevel, 6, 6, 0, 4);
171
163
QLabel *label3 = new QLabel(i18n("Coloring Tint:"), gboxSettings);
172
164
m_HSSelector = new KHSSelector(gboxSettings);
174
166
m_HSSelector->setMinimumSize(200, 142);
175
167
m_VSelector->setMinimumSize(26, 142);
176
168
QWhatsThis::add(m_HSSelector, i18n("<p>Sets a custom color to re-colorize the eyes."));
177
gridSettings->addMultiCellWidget(label3, 7, 7, 0, 4);
178
gridSettings->addMultiCellWidget(m_HSSelector, 8, 8, 0, 3);
179
gridSettings->addMultiCellWidget(m_VSelector, 8, 8, 4, 4);
181
170
QLabel *label4 = new QLabel(i18n("Tint Level:"), gboxSettings);
182
171
m_tintLevel = new KIntNumInput(gboxSettings);
184
173
m_tintLevel->setValue(128);
185
174
QWhatsThis::add(m_tintLevel, i18n("<p>Set the tint level to adjust the luminosity of "
186
175
"the new color of the pupil."));
187
gridSettings->addMultiCellWidget(label4, 9, 9, 0, 4);
188
gridSettings->addMultiCellWidget(m_tintLevel, 10, 10, 0, 4);
190
gridSettings->setRowStretch(11, 10);
191
gridSettings->setColStretch(3, 10);
177
gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
178
gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
179
gridSettings->addMultiCellWidget(m_thresholdLabel, 3, 3, 0, 4);
180
gridSettings->addMultiCellWidget(m_redThreshold, 4, 4, 0, 4);
181
gridSettings->addMultiCellWidget(m_smoothLabel, 5, 5, 0, 4);
182
gridSettings->addMultiCellWidget(m_smoothLevel, 6, 6, 0, 4);
183
gridSettings->addMultiCellWidget(label3, 7, 7, 0, 4);
184
gridSettings->addMultiCellWidget(m_HSSelector, 8, 8, 0, 3);
185
gridSettings->addMultiCellWidget(m_VSelector, 8, 8, 4, 4);
186
gridSettings->addMultiCellWidget(label4, 9, 9, 0, 4);
187
gridSettings->addMultiCellWidget(m_tintLevel, 10, 10, 0, 4);
188
gridSettings->setRowStretch(11, 10);
189
gridSettings->setColStretch(3, 10);
192
190
setUserAreaWidget(gboxSettings);
194
192
// -------------------------------------------------------------
196
194
connect(m_channelCB, SIGNAL(activated(int)),
199
197
connect(m_scaleBG, SIGNAL(released(int)),
200
198
this, SLOT(slotScaleChanged(int)));
202
connect(m_previewWidget, SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const QPoint & )),
203
this, SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
200
connect(m_previewWidget, SIGNAL(spotPositionChangedFromTarget(const Digikam::DColor&, const QPoint&)),
201
this, SLOT(slotColorSelectedFromTarget(const Digikam::DColor&)));
205
203
connect(m_previewWidget, SIGNAL(signalResized()),
206
this, SLOT(slotEffect()));
204
this, SLOT(slotEffect()));
208
206
connect(m_redThreshold, SIGNAL(valueChanged(int)),
209
this, SLOT(slotTimer()));
207
this, SLOT(slotTimer()));
211
209
connect(m_smoothLevel, SIGNAL(valueChanged(int)),
212
this, SLOT(slotTimer()));
210
this, SLOT(slotTimer()));
214
212
connect(m_HSSelector, SIGNAL(valueChanged(int, int)),
215
213
this, SLOT(slotHSChanged(int, int)));
218
216
this, SLOT(slotTimer()));
220
218
connect(m_tintLevel, SIGNAL(valueChanged(int)),
221
this, SLOT(slotTimer()));
219
this, SLOT(slotTimer()));
224
222
ImageEffect_RedEye::~ImageEffect_RedEye()
251
249
m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
252
250
m_hGradient->setColors( QColor( "black" ), QColor( "white" ) );
256
254
m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
257
255
m_hGradient->setColors( QColor( "black" ), QColor( "red" ) );
261
259
m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
262
260
m_hGradient->setColors( QColor( "black" ), QColor( "green" ) );
266
264
m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
267
265
m_hGradient->setColors( QColor( "black" ), QColor( "blue" ) );
294
292
m_HSSelector->setYValue(config->readNumEntry("SatColoringTint", 0));
295
293
m_VSelector->setValue(config->readNumEntry("ValColoringTint", 0));
296
294
m_tintLevel->setValue(config->readNumEntry("TintLevel", 128));
298
296
slotHSChanged(m_HSSelector->xValue(), m_HSSelector->yValue());
299
297
slotChannelChanged(m_channelCB->currentItem());
300
298
slotScaleChanged(m_scaleBG->selectedId());
318
316
void ImageEffect_RedEye::resetValues()
320
m_redThreshold->blockSignals(true);
321
m_HSSelector->blockSignals(true);
322
m_VSelector->blockSignals(true);
323
m_tintLevel->blockSignals(true);
318
m_redThreshold->blockSignals(true);
319
m_HSSelector->blockSignals(true);
320
m_VSelector->blockSignals(true);
321
m_tintLevel->blockSignals(true);
325
323
m_redThreshold->setValue(20);
326
324
m_smoothLevel->setValue(1);
333
331
m_tintLevel->setValue(128);
335
m_redThreshold->blockSignals(false);
336
m_HSSelector->blockSignals(false);
333
m_redThreshold->blockSignals(false);
334
m_HSSelector->blockSignals(false);
337
335
m_VSelector->blockSignals(false);
338
m_tintLevel->blockSignals(false);
336
m_tintLevel->blockSignals(false);
341
339
void ImageEffect_RedEye::slotEffect()
343
kapp->setOverrideCursor( KCursor::waitCursor() );
341
kapp->setOverrideCursor(KCursor::waitCursor());
345
343
m_histogramWidget->stopHistogramComputation();
366
364
m_previewWidget->updatePreview();
368
366
// Update histogram.
370
368
memcpy(m_destinationPreviewData, selection.bits(), selection.numBytes());
371
369
m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
397
395
void ImageEffect_RedEye::redEyeFilter(Digikam::DImg& selection)
399
Digikam::DImg mask(selection.width(), selection.height(), selection.sixteenBit(), true,
397
Digikam::DImg mask(selection.width(), selection.height(), selection.sixteenBit(), true,
400
398
selection.bits(), true);
402
400
selection = mask.copy();
404
402
int hue = m_HSSelector->xValue();
405
403
int sat = m_HSSelector->yValue();
406
404
int val = m_VSelector->value();
407
QColor coloring(hue, sat, val, QColor::Hsv);
406
coloring.setHsv(hue, sat, val);
566
565
Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(Digikam::DColorComposer::PorterDuffSrcOver);
568
567
// NOTE: 'mask' is the Source image, 'selection' is the Destination image.
570
selection.bitBlendImage(composer, &mask,
569
selection.bitBlendImage(composer, &mask,
571
570
0, 0, mask.width(), mask.height(),