~ubuntu-branches/ubuntu/intrepid/digikam/intrepid

« back to all changes in this revision

Viewing changes to digikam/imageplugins/coreplugin/imageeffect_redeye.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2008-07-17 20:25:39 UTC
  • mfrom: (1.2.15 upstream) (3.1.2 lenny)
  • Revision ID: james.westby@ubuntu.com-20080717202539-6n7dtirbkoo7qvhd
Tags: 2:0.9.4-1
* New upstream release
  - digiKam 0.9.4 Release Plan (KDE3) ~ 13 July 08 (Closes: #490144)
* DEB_CONFIGURE_EXTRA_FLAGS := --without-included-sqlite3
* Debhelper compatibility level V7
* Install pixmaps in debian/*.install
* Add debian/digikam.lintian-overrides

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 * Description : Red eyes correction tool for image editor
8
8
 *
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>
11
11
 *
12
12
 * This program is free software; you can redistribute it
13
13
 * and/or modify it under the terms of the GNU General
23
23
 * ============================================================ */
24
24
 
25
25
// Qt includes.
26
 
 
 
26
 
27
27
#include <qcolor.h>
28
28
#include <qhbox.h>
29
29
#include <qhgroupbox.h>
41
41
 
42
42
// KDE includes.
43
43
 
 
44
#include <kcolordialog.h>
44
45
#include <knuminput.h>
45
46
#include <klocale.h>
46
47
#include <kapplication.h>
68
69
{
69
70
 
70
71
ImageEffect_RedEye::ImageEffect_RedEye(QWidget* parent)
71
 
                  : Digikam::ImageDlgBase(parent, i18n("Red Eye Reduction"), 
72
 
                                          "redeye", false)
 
72
                  : Digikam::ImageDlgBase(parent, i18n("Red Eye Reduction"), "redeye", false)
73
73
{
74
 
    m_destinationPreviewData = 0L;
 
74
    m_destinationPreviewData = 0;
75
75
    setHelp("redeyecorrectiontool.anchor", "digikam");
76
76
 
77
77
    m_previewWidget = new Digikam::ImageWidget("redeye Tool Dialog", plainPage(),
81
81
    setPreviewAreaWidget(m_previewWidget); 
82
82
 
83
83
    // -------------------------------------------------------------
84
 
                
 
84
 
85
85
    QWidget *gboxSettings     = new QWidget(plainPage());
86
86
    QGridLayout* gridSettings = new QGridLayout(gboxSettings, 11, 4, spacingHint());
87
87
 
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."));
109
 
    
 
109
 
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);
117
 
    
 
117
 
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);
125
125
 
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);
131
 
    
132
 
    gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
133
131
 
134
132
    // -------------------------------------------------------------
135
133
 
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" ) );
145
 
    
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"));
147
143
 
148
144
    // -------------------------------------------------------------
149
145
 
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);
160
154
 
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);
170
162
 
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);
180
169
 
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);
189
176
 
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);
193
 
    
 
191
 
194
192
    // -------------------------------------------------------------
195
193
 
196
194
    connect(m_channelCB, SIGNAL(activated(int)),
199
197
    connect(m_scaleBG, SIGNAL(released(int)),
200
198
            this, SLOT(slotScaleChanged(int)));
201
199
 
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&)));
204
202
 
205
203
    connect(m_previewWidget, SIGNAL(signalResized()),
206
 
            this, SLOT(slotEffect()));    
207
 
            
 
204
            this, SLOT(slotEffect()));
 
205
 
208
206
    connect(m_redThreshold, SIGNAL(valueChanged(int)),
209
 
            this, SLOT(slotTimer()));   
 
207
            this, SLOT(slotTimer()));
210
208
 
211
209
    connect(m_smoothLevel, SIGNAL(valueChanged(int)),
212
 
            this, SLOT(slotTimer()));   
 
210
            this, SLOT(slotTimer()));
213
211
 
214
212
    connect(m_HSSelector, SIGNAL(valueChanged(int, int)),
215
213
            this, SLOT(slotHSChanged(int, int)));
218
216
            this, SLOT(slotTimer()));
219
217
 
220
218
    connect(m_tintLevel, SIGNAL(valueChanged(int)),
221
 
            this, SLOT(slotTimer()));  
 
219
            this, SLOT(slotTimer()));
222
220
}
223
221
 
224
222
ImageEffect_RedEye::~ImageEffect_RedEye()
227
225
 
228
226
    if (m_destinationPreviewData) 
229
227
       delete [] m_destinationPreviewData;
230
 
       
 
228
 
231
229
    delete m_histogramWidget;
232
230
    delete m_previewWidget;
233
231
}
239
237
    m_VSelector->setSaturation(s);
240
238
    m_VSelector->updateContents();
241
239
    m_VSelector->repaint(false);
242
 
    m_VSelector->blockSignals(false);  
 
240
    m_VSelector->blockSignals(false);
243
241
    slotTimer();
244
242
}
245
243
 
251
249
            m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
252
250
            m_hGradient->setColors( QColor( "black" ), QColor( "white" ) );
253
251
            break;
254
 
    
 
252
 
255
253
        case RedChannel:
256
254
            m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
257
255
            m_hGradient->setColors( QColor( "black" ), QColor( "red" ) );
258
256
            break;
259
 
    
260
 
        case GreenChannel:         
 
257
 
 
258
        case GreenChannel:
261
259
            m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
262
260
            m_hGradient->setColors( QColor( "black" ), QColor( "green" ) );
263
261
            break;
264
 
    
265
 
        case BlueChannel:         
 
262
 
 
263
        case BlueChannel:
266
264
            m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
267
265
            m_hGradient->setColors( QColor( "black" ), QColor( "blue" ) );
268
266
            break;
277
275
    m_histogramWidget->repaint(false);
278
276
}
279
277
 
280
 
void ImageEffect_RedEye::slotColorSelectedFromTarget( const Digikam::DColor &color )
 
278
void ImageEffect_RedEye::slotColorSelectedFromTarget(const Digikam::DColor& color)
281
279
{
282
280
    m_histogramWidget->setHistogramGuideByColor(color);
283
281
}
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));
297
 
    
 
295
 
298
296
    slotHSChanged(m_HSSelector->xValue(), m_HSSelector->yValue());
299
297
    slotChannelChanged(m_channelCB->currentItem());
300
298
    slotScaleChanged(m_scaleBG->selectedId());
317
315
 
318
316
void ImageEffect_RedEye::resetValues()
319
317
{
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);
324
322
 
325
323
    m_redThreshold->setValue(20);
326
324
    m_smoothLevel->setValue(1);
332
330
 
333
331
    m_tintLevel->setValue(128);
334
332
 
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);
339
337
340
338
 
341
339
void ImageEffect_RedEye::slotEffect()
342
340
{
343
 
    kapp->setOverrideCursor( KCursor::waitCursor() );
 
341
    kapp->setOverrideCursor(KCursor::waitCursor());
344
342
 
345
343
    m_histogramWidget->stopHistogramComputation();
346
344
 
366
364
    m_previewWidget->updatePreview();
367
365
 
368
366
    // Update histogram.
369
 
   
 
367
 
370
368
    memcpy(m_destinationPreviewData, selection.bits(), selection.numBytes());
371
369
    m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
372
370
 
396
394
 
397
395
void ImageEffect_RedEye::redEyeFilter(Digikam::DImg& selection)
398
396
{
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);
401
399
 
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);
 
405
    KColor coloring;
 
406
    coloring.setHsv(hue, sat, val);
408
407
 
409
408
    struct channel
410
409
    {
526
525
    {
527
526
        uchar* mptr  = mask.bits();
528
527
        uchar* mptr2 = mask2.bits();
529
 
        
 
528
 
530
529
        for (uint i = 0 ; i < mask2.width() * mask2.height() ; i++)
531
530
        {
532
531
            if (mptr2[3] < 255)
545
544
    {
546
545
        unsigned short* mptr  = (unsigned short*)mask.bits();
547
546
        unsigned short* mptr2 = (unsigned short*)mask2.bits();
548
 
        
 
547
 
549
548
        for (uint i = 0 ; i < mask2.width() * mask2.height() ; i++)
550
549
        {
551
550
            if (mptr2[3] < 65535)
566
565
    Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(Digikam::DColorComposer::PorterDuffSrcOver);
567
566
 
568
567
    // NOTE: 'mask' is the Source image, 'selection' is the Destination image.
569
 
 
570
 
    selection.bitBlendImage(composer, &mask,           
 
568
 
 
569
    selection.bitBlendImage(composer, &mask,
571
570
                            0, 0, mask.width(), mask.height(),
572
571
                            0, 0);
573
572
}