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

« back to all changes in this revision

Viewing changes to digikam/imageplugins/imageeffect_redeye.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2008-07-17 20:25:39 UTC
  • mfrom: (1.3.2 upstream) (37 hardy)
  • mto: This revision was merged to the branch mainline in revision 39.
  • Revision ID: james.westby@ubuntu.com-20080717202539-1bw3w3nrsso7yj4z
* 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:
1
 
/* ============================================================
2
 
 * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
3
 
 * Date  : 2004-06-06
4
 
 * Description :
5
 
 *
6
 
 * Copyright 2004 by Renchi Raju
7
 
 
8
 
 * This program is free software; you can redistribute it
9
 
 * and/or modify it under the terms of the GNU General
10
 
 * Public License as published by the Free Software Foundation;
11
 
 * either version 2, or (at your option)
12
 
 * any later version.
13
 
 *
14
 
 * This program is distributed in the hope that it will be useful,
15
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
 * GNU General Public License for more details.
18
 
 *
19
 
 * ============================================================ */
20
 
 
21
 
// C++ includes.
22
 
 
23
 
#include <cstring>
24
 
 
25
 
// Imlib2 includes.
26
 
 
27
 
#define X_DISPLAY_MISSING 1
28
 
#include <Imlib2.h>
29
 
 
30
 
// Qt includes.
31
 
 
32
 
#include <qvbuttongroup.h>
33
 
#include <qradiobutton.h>
34
 
#include <qlayout.h>
35
 
 
36
 
// KDE includes.
37
 
 
38
 
#include <kdialogbase.h>
39
 
#include <klocale.h>
40
 
#include <kapplication.h>
41
 
#include <kconfig.h>
42
 
#include <kcursor.h>
43
 
#include <kpassivepopup.h>
44
 
#include <kdebug.h>
45
 
 
46
 
// Digikam includes.
47
 
 
48
 
#include <imageiface.h>
49
 
 
50
 
// Local includes.
51
 
 
52
 
#include "imageeffect_redeye.h"
53
 
 
54
 
class RedEyePassivePopup : public KPassivePopup
55
 
{
56
 
public:
57
 
 
58
 
    RedEyePassivePopup(QWidget* parent)
59
 
        : KPassivePopup(parent), m_parent(parent)          
60
 
    {
61
 
    }
62
 
 
63
 
protected:
64
 
 
65
 
    virtual void positionSelf()
66
 
    {
67
 
        move(m_parent->x() + 30, m_parent->y() + 30);
68
 
    }
69
 
 
70
 
private:
71
 
 
72
 
    QWidget* m_parent;
73
 
};
74
 
 
75
 
void ImageEffect_RedEye::removeRedEye(QWidget* parent)
76
 
{
77
 
    // -- check if we actually have a selection --------------------
78
 
 
79
 
    Digikam::ImageIface iface(0, 0);
80
 
 
81
 
    uint* data = iface.getSelectedData();
82
 
    int   w    = iface.selectedWidth();
83
 
    int   h    = iface.selectedHeight();
84
 
 
85
 
    if (!data || !w || !h)
86
 
    {
87
 
        RedEyePassivePopup* popup = new RedEyePassivePopup(parent);
88
 
        popup->setView(i18n("Red-Eye Correction Tool"),
89
 
                       i18n("You need to select a region including the eyes to use "
90
 
                            "the red-eye correction tool"));
91
 
        popup->setAutoDelete(true);
92
 
        popup->setTimeout(2500);
93
 
        popup->show();
94
 
        return;
95
 
    }
96
 
 
97
 
    // -- run the dlg ----------------------------------------------
98
 
 
99
 
    ImageEffect_RedEyeDlg dlg(parent);
100
 
 
101
 
    if (dlg.exec() != QDialog::Accepted)
102
 
        return;
103
 
 
104
 
    // -- save settings ----------------------------------------------
105
 
 
106
 
    bool aggressive = (dlg.result() == ImageEffect_RedEyeDlg::Aggressive);
107
 
    KConfig *config = kapp->config();
108
 
    config->setGroup("ImageViewer Settings");
109
 
    config->writeEntry("Red Eye Correction Plugin (Mild)",
110
 
                       !aggressive);
111
 
    config->sync();
112
 
 
113
 
    // -- do the actual operations -----------------------------------
114
 
 
115
 
    parent->setCursor( KCursor::waitCursor() );
116
 
 
117
 
    uint* newData = new uint[w*h];
118
 
    memcpy(newData, data, w*h*sizeof(unsigned int));
119
 
 
120
 
    int   r,g,b,a;
121
 
 
122
 
    struct channel {
123
 
        float red_gain;
124
 
        float green_gain;
125
 
        float blue_gain;
126
 
    };
127
 
    channel red_chan, green_chan, blue_chan;
128
 
 
129
 
    red_chan.red_gain   = 0.1;
130
 
    red_chan.green_gain = 0.6;
131
 
    red_chan.blue_gain  = 0.3;
132
 
 
133
 
    green_chan.red_gain   = 0.0;
134
 
    green_chan.green_gain = 1.0;
135
 
    green_chan.blue_gain  = 0.0;
136
 
 
137
 
    blue_chan.red_gain   = 0.0;
138
 
    blue_chan.green_gain = 0.0;
139
 
    blue_chan.blue_gain  = 1.0;
140
 
 
141
 
    float red_norm, green_norm, blue_norm;
142
 
 
143
 
    red_norm = 1.0/(red_chan.red_gain + red_chan.green_gain + red_chan.blue_gain);
144
 
    green_norm = 1.0/(green_chan.red_gain + green_chan.green_gain + green_chan.blue_gain);
145
 
    blue_norm = 1.0/(blue_chan.red_gain + blue_chan.green_gain + blue_chan.blue_gain);
146
 
 
147
 
    uint* ptr  = data;
148
 
    uint* nptr = newData;
149
 
 
150
 
    int r1, g1, b1;
151
 
 
152
 
    for (int i=0; i<w*h; i++) {
153
 
 
154
 
        a = (*ptr >> 24) & 0xff;
155
 
        r = (*ptr >> 16) & 0xff;
156
 
        g = (*ptr >> 8)  & 0xff;
157
 
        b = (*ptr)       & 0xff;
158
 
 
159
 
        if ( aggressive || r >= ( 2 * g) )
160
 
        {
161
 
            r1 = (int) QMIN(255, red_norm * (red_chan.red_gain   * r +
162
 
                                       red_chan.green_gain * g +
163
 
                                       red_chan.blue_gain  * b));
164
 
            b1 = (int) QMIN(255, green_norm * (green_chan.red_gain   * r +
165
 
                                         green_chan.green_gain * g +
166
 
                                         green_chan.blue_gain  * b));
167
 
            g1 = (int) QMIN(255, blue_norm * (blue_chan.red_gain   * r +
168
 
                                        blue_chan.green_gain * g +
169
 
                                        blue_chan.blue_gain  * b));
170
 
 
171
 
            *nptr = QMIN(int((r-g)/150.0*255.0),255) << 24 | r1 << 16 | g1 << 8 | b1;
172
 
        }
173
 
 
174
 
        ptr++;
175
 
        nptr++;
176
 
    }
177
 
 
178
 
    Imlib_Context context = imlib_context_new();
179
 
    imlib_context_push(context);
180
 
 
181
 
    Imlib_Image imTop = imlib_create_image_using_copied_data(w, h, newData);
182
 
    imlib_context_set_image(imTop);
183
 
    imlib_image_set_has_alpha(1);
184
 
 
185
 
    // blurring usually gives better results, but users might complain
186
 
    // about loss of sharpness
187
 
    //imlib_image_blur(1);
188
 
 
189
 
    Imlib_Image imBot = imlib_create_image_using_copied_data(w, h, data);
190
 
    imlib_context_set_image(imBot);
191
 
 
192
 
    imlib_blend_image_onto_image(imTop, 0, 0, 0, w, h, 0, 0, w, h);
193
 
 
194
 
    ptr = imlib_image_get_data_for_reading_only();
195
 
    memcpy(data, ptr, w*h*sizeof(unsigned int));
196
 
 
197
 
    imlib_context_set_image(imTop);
198
 
    imlib_free_image_and_decache();
199
 
 
200
 
    imlib_context_set_image(imBot);
201
 
    imlib_free_image_and_decache();
202
 
 
203
 
    imlib_context_pop();
204
 
    imlib_context_free(context);
205
 
 
206
 
    delete [] newData;
207
 
 
208
 
    iface.putSelectedData(data);
209
 
 
210
 
    delete [] data;
211
 
    parent->setCursor( KCursor::arrowCursor() );
212
 
}
213
 
 
214
 
ImageEffect_RedEyeDlg::ImageEffect_RedEyeDlg(QWidget* parent)
215
 
    : KDialogBase(Plain, i18n("Red Eye Correction"),
216
 
                  Help|Ok|Cancel, Ok, parent, 0, true, true)
217
 
{
218
 
    setHelp("redeyecorrectiontool.anchor", "digikam");
219
 
    QVBoxLayout *topLayout = new QVBoxLayout( plainPage(),
220
 
                                              0, spacingHint());
221
 
 
222
 
    QVButtonGroup* buttonGroup =
223
 
        new QVButtonGroup( i18n("Level of Red-Eye Correction"),
224
 
                           plainPage() );
225
 
    buttonGroup->setRadioButtonExclusive( true );
226
 
 
227
 
    QRadioButton* mildBtn =
228
 
        new QRadioButton( i18n("Mild (use if other parts of the face are also selected)"),
229
 
                          buttonGroup );
230
 
    QRadioButton* aggrBtn =
231
 
        new QRadioButton( i18n("Aggressive (use if eye(s) have been selected exactly)" ),
232
 
                          buttonGroup );
233
 
 
234
 
    topLayout->addWidget( buttonGroup );
235
 
    
236
 
    connect( buttonGroup, SIGNAL(clicked(int)),
237
 
             SLOT(slotClicked(int)) );
238
 
 
239
 
    bool mild;
240
 
 
241
 
    KConfig *config = kapp->config();
242
 
    config->setGroup("ImageViewer Settings");
243
 
    mild = config->readBoolEntry("Red Eye Correction Plugin (Mild)", true);
244
 
 
245
 
    if (mild)
246
 
    {
247
 
        mildBtn->setChecked(true);
248
 
        m_selectedId = 0;
249
 
    }
250
 
    else
251
 
    {
252
 
        aggrBtn->setChecked(true);
253
 
        m_selectedId = 1;
254
 
    }
255
 
}
256
 
 
257
 
ImageEffect_RedEyeDlg::Result ImageEffect_RedEyeDlg::result() const
258
 
{
259
 
    return (Result)m_selectedId;
260
 
}
261
 
 
262
 
void ImageEffect_RedEyeDlg::slotClicked(int id)
263
 
{
264
 
    m_selectedId = id;
265
 
}
266
 
 
267
 
#include "imageeffect_redeye.moc"