~ubuntu-branches/ubuntu/saucy/digikam/saucy

« back to all changes in this revision

Viewing changes to utilities/queuemanager/basetools/enhance/sharpen.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christian Mangold
  • Date: 2010-04-09 21:30:01 UTC
  • mfrom: (1.2.28 upstream)
  • Revision ID: james.westby@ubuntu.com-20100409213001-4bfyibrd359rn7o3
Tags: 2:1.2.0-0ubuntu1
* New upstream release (LP: #560576)
* Remove all patches, fixed upstream
  - Remove quilt build-depend

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 * http://www.digikam.org
5
5
 *
6
6
 * Date        : 2009-05-02
7
 
 * Description : image sharpen batch tool.
 
7
 * Description : sharpen image batch tool.
8
8
 *
9
9
 * Copyright (C) 2009 by Matthias Welwarsky <matze at welwarsky dot de>
 
10
 * Copyright (C) 2010 by Gilles Caulier <caulier dot gilles at gmail dot com>
10
11
 *
11
12
 * This program is free software; you can redistribute it
12
13
 * and/or modify it under the terms of the GNU General
26
27
// Qt includes
27
28
 
28
29
#include <QLabel>
29
 
#include <QScrollArea>
30
 
#include <QStackedWidget>
31
30
#include <QWidget>
32
31
 
33
32
// KDE includes
36
35
#include <klocale.h>
37
36
#include <kvbox.h>
38
37
 
39
 
// LibKDcraw includes
40
 
 
41
 
#include <libkdcraw/rcombobox.h>
42
 
#include <libkdcraw/rnuminput.h>
43
 
 
44
38
// Local includes
45
39
 
46
40
#include "dimg.h"
47
 
#include "dimgimagefilters.h"
48
 
#include "dimgrefocus.h"
49
 
#include "dimgsharpen.h"
50
 
#include "dimgunsharpmask.h"
51
 
 
52
 
using namespace KDcrawIface;
 
41
#include "refocusfilter.h"
 
42
#include "sharpenfilter.h"
 
43
#include "unsharpmaskfilter.h"
 
44
#include "sharpsettings.h"
53
45
 
54
46
namespace Digikam
55
47
{
56
48
 
57
 
Sharpen::Sharpen(QObject *parent)
58
 
       : BatchTool("Sharpen", BaseTool, parent)
 
49
Sharpen::Sharpen(QObject* parent)
 
50
       : BatchTool("Sharpen", EnhanceTool, parent)
59
51
{
60
52
    setToolTitle(i18n("Sharpen Image"));
61
53
    setToolDescription(i18n("A tool to sharpen images"));
62
54
    setToolIcon(KIcon(SmallIcon("sharpenimage")));
63
55
 
64
 
    /* Settings widget is a KVBox, containing the
65
 
     * sharpen method settings, ...
66
 
     */
67
 
    KVBox *vbox = new KVBox;
68
 
    new QLabel(i18n("Method:"), vbox);
69
 
 
70
 
    m_sharpMethod = new RComboBox(vbox);
71
 
    m_sharpMethod->addItem(i18n("Simple sharp"));
72
 
    m_sharpMethod->addItem(i18n("Unsharp mask"));
73
 
    m_sharpMethod->addItem(i18n("Refocus"));
74
 
    m_sharpMethod->setDefaultIndex(SimpleSharp);
75
 
    m_sharpMethod->setWhatsThis( i18n("Select the sharpening method to apply to the image."));
76
 
 
77
 
    connect(m_sharpMethod, SIGNAL(activated(int)),
78
 
            this, SLOT(slotSharpMethodChanged(int)));
79
 
 
80
 
    /* ... and then a widget stack, ... */
81
 
    m_stack = new QStackedWidget(vbox);
82
 
 
83
 
    /* ... which in turn contains the settings for SimpleSharp ... */
84
 
    KVBox *simpleSharpSettings = new KVBox(m_stack);
85
 
    new QLabel(i18n("Sharpness:"), simpleSharpSettings);
86
 
    m_radiusInput = new RIntNumInput(simpleSharpSettings);
87
 
    m_radiusInput->setRange(0, 100, 1);
88
 
    m_radiusInput->setSliderEnabled(true);
89
 
    m_radiusInput->setDefaultValue(0);
90
 
    m_radiusInput->setWhatsThis( i18n("A sharpness of 0 has no effect, "
91
 
                                      "1 and above determine the sharpen matrix radius "
92
 
                                      "that determines how much to sharpen the image."));
93
 
    QLabel *space = new QLabel(simpleSharpSettings);
94
 
    simpleSharpSettings->setStretchFactor(space, 10);
95
 
 
96
 
    connect(m_radiusInput, SIGNAL(valueChanged(int)),
97
 
            this, SLOT(slotSettingsChanged()));
98
 
 
99
 
    m_stack->insertWidget(SimpleSharp, simpleSharpSettings);
100
 
 
101
 
    /* ... settings for UnsharpMask ... */
102
 
    KVBox *unsharpMaskSettings = new KVBox(m_stack);
103
 
    new QLabel(i18n("Radius:"), unsharpMaskSettings);
104
 
    m_radiusInput2 = new RIntNumInput(unsharpMaskSettings);
105
 
    m_radiusInput2->setRange(1, 120, 1);
106
 
    m_radiusInput2->setSliderEnabled(true);
107
 
    m_radiusInput2->setDefaultValue(1);
108
 
    m_radiusInput2->setWhatsThis( i18n("Radius value is the Gaussian blur matrix radius value "
109
 
                                       "used to determines how much to blur the image.") );
110
 
 
111
 
    connect(m_radiusInput2, SIGNAL(valueChanged(int)),
112
 
            this, SLOT(slotSettingsChanged()));
113
 
 
114
 
    new QLabel(i18n("Amount:"), unsharpMaskSettings);
115
 
    m_amountInput  = new RDoubleNumInput(unsharpMaskSettings);
116
 
    m_amountInput->setDecimals(1);
117
 
    m_amountInput->input()->setRange(0.0, 5.0, 0.1, true);
118
 
    m_amountInput->setDefaultValue(1.0);
119
 
    m_amountInput->setWhatsThis( i18n("The value of the difference between the "
120
 
                                      "original and the blur image that is added back into the original.") );
121
 
 
122
 
    connect(m_amountInput, SIGNAL(valueChanged(double)),
123
 
            this, SLOT(slotSettingsChanged()));
124
 
 
125
 
    new QLabel(i18n("Threshold:"), unsharpMaskSettings);
126
 
    m_thresholdInput = new RDoubleNumInput(unsharpMaskSettings);
127
 
    m_thresholdInput->setDecimals(2);
128
 
    m_thresholdInput->input()->setRange(0.0, 1.0, 0.01, true);
129
 
    m_thresholdInput->setDefaultValue(0.05);
130
 
    m_thresholdInput->setWhatsThis( i18n("The threshold, as a fraction of the maximum "
131
 
                                         "luminosity value, needed to apply the difference amount.") );
132
 
 
133
 
    connect(m_thresholdInput, SIGNAL(valueChanged(double)),
134
 
            this, SLOT(slotSettingsChanged()));
135
 
 
136
 
    QLabel *space2 = new QLabel(unsharpMaskSettings);
137
 
    unsharpMaskSettings->setStretchFactor(space2, 10);
138
 
 
139
 
    m_stack->insertWidget(UnsharpMask, unsharpMaskSettings);
140
 
 
141
 
    /* ... Refocus settings ... */
142
 
    KVBox *refocusSettings = new KVBox(m_stack);
143
 
    new QLabel(i18n("Circular sharpness:"), refocusSettings);
144
 
    m_radius       = new RDoubleNumInput(refocusSettings);
145
 
    m_radius->setDecimals(2);
146
 
    m_radius->input()->setRange(0.0, 5.0, 0.01, true);
147
 
    m_radius->setDefaultValue(1.0);
148
 
    m_radius->setWhatsThis( i18n("This is the radius of the circular convolution. It is the most important "
149
 
                                 "parameter for using this plugin. For most images the default value of 1.0 "
150
 
                                 "should give good results. Select a higher value when your image is very blurred."));
151
 
 
152
 
    connect(m_radius, SIGNAL(valueChanged(double)),
153
 
            this, SLOT(slotSettingsChanged()));
154
 
 
155
 
    new QLabel(i18n("Correlation:"), refocusSettings);
156
 
    m_correlation  = new RDoubleNumInput(refocusSettings);
157
 
    m_correlation->setDecimals(2);
158
 
    m_correlation->input()->setRange(0.0, 1.0, 0.01, true);
159
 
    m_correlation->setDefaultValue(0.5);
160
 
    m_correlation->setWhatsThis( i18n("Increasing the correlation may help to reduce artifacts. The correlation can "
161
 
                                      "range from 0-1. Useful values are 0.5 and values close to 1, e.g. 0.95 and 0.99. "
162
 
                                      "Using a high value for the correlation will reduce the sharpening effect of the "
163
 
                                      "plugin."));
164
 
 
165
 
    connect(m_correlation, SIGNAL(valueChanged(double)),
166
 
            this, SLOT(slotSettingsChanged()));
167
 
 
168
 
    new QLabel(i18n("Noise filter:"), refocusSettings);
169
 
    m_noise        = new RDoubleNumInput(refocusSettings);
170
 
    m_noise->setDecimals(3);
171
 
    m_noise->input()->setRange(0.0, 1.0, 0.001, true);
172
 
    m_noise->setDefaultValue(0.03);
173
 
    m_noise->setWhatsThis( i18n("Increasing the noise filter parameter may help to reduce artifacts. The noise filter "
174
 
                                "can range from 0-1 but values higher than 0.1 are rarely helpful. When the noise filter "
175
 
                                "value is too low, e.g. 0.0 the image quality will be very poor. A useful value is 0.01. "
176
 
                                "Using a high value for the noise filter will reduce the sharpening "
177
 
                                "effect of the plugin."));
178
 
 
179
 
    connect(m_noise, SIGNAL(valueChanged(double)),
180
 
            this, SLOT(slotSettingsChanged()));
181
 
 
182
 
    new QLabel(i18n("Gaussian sharpness:"), refocusSettings);
183
 
    m_gauss        = new RDoubleNumInput(refocusSettings);
184
 
    m_gauss->setDecimals(2);
185
 
    m_gauss->input()->setRange(0.0, 1.0, 0.01, true);
186
 
    m_gauss->setDefaultValue(0.0);
187
 
    m_gauss->setWhatsThis( i18n("This is the sharpness for the Gaussian convolution. Use this parameter when your "
188
 
                                "blurring is of a Gaussian type. In most cases you should set this parameter to 0, because "
189
 
                                "it causes nasty artifacts. When you use non-zero values, you will probably also have to "
190
 
                                "increase the correlation and/or noise filter parameters."));
191
 
 
192
 
    connect(m_gauss, SIGNAL(valueChanged(double)),
193
 
            this, SLOT(slotSettingsChanged()));
194
 
 
195
 
    new QLabel(i18n("Matrix size:"), refocusSettings);
196
 
    m_matrixSize   = new RIntNumInput(refocusSettings);
197
 
    m_matrixSize->setRange(0, DImgRefocus::maxMatrixSize(), 1);
198
 
    m_matrixSize->setSliderEnabled(true);
199
 
    m_matrixSize->setDefaultValue(5);
200
 
    m_matrixSize->setWhatsThis( i18n("This parameter determines the size of the transformation matrix. "
201
 
                                     "Increasing the matrix width may give better results, especially when you have "
202
 
                                     "chosen large values for circular or Gaussian sharpness."));
203
 
 
204
 
    connect(m_matrixSize, SIGNAL(valueChanged(int)),
205
 
            this, SLOT(slotSettingsChanged()));
206
 
 
207
 
    m_stack->insertWidget(Refocus, refocusSettings);
208
 
 
209
 
    /* finally tell the batchtool about its settings widget */
210
 
    setSettingsWidget(vbox);
211
 
 
 
56
    QWidget* box   = new QWidget;
 
57
    m_settingsView = new SharpSettings(box);
 
58
    setSettingsWidget(box);
 
59
 
 
60
    connect(m_settingsView, SIGNAL(signalSettingsChanged()),
 
61
            this, SLOT(slotSettingsChanged()));
212
62
}
213
63
 
214
64
Sharpen::~Sharpen()
218
68
BatchToolSettings Sharpen::defaultSettings()
219
69
{
220
70
    BatchToolSettings settings;
 
71
    SharpContainer defaultPrm = m_settingsView->defaultSettings();
221
72
 
222
73
    // sharpen method
223
 
    settings.insert("SharpenFilterType", SimpleSharp);
 
74
    settings.insert("SharpenFilterType",    (int)defaultPrm.method);
224
75
 
225
76
    // simple sharp
226
 
    settings.insert("SimpleSharpRadius", 2);
 
77
    settings.insert("SimpleSharpRadius",    (int)defaultPrm.ssRadius);
227
78
 
228
79
    // unsharp mask
229
 
    settings.insert("UnsharpMaskRadius",    (int)1);
230
 
    settings.insert("UnsharpMaskAmount",    (double)1.0);
231
 
    settings.insert("UnsharpMaskThreshold", (double)0.05);
 
80
    settings.insert("UnsharpMaskRadius",    (double)defaultPrm.umRadius);
 
81
    settings.insert("UnsharpMaskAmount",    (double)defaultPrm.umAmount);
 
82
    settings.insert("UnsharpMaskThreshold", (double)defaultPrm.umThreshold);
232
83
 
233
84
    // refocus
234
 
    settings.insert("RefocusMatrixSize",  (int)5);
235
 
    settings.insert("RefocusRadius",      (double)0.9);
236
 
    settings.insert("RefocusGauss",       (double)0.0);
237
 
    settings.insert("RefocusCorrelation", (double)0.5);
238
 
    settings.insert("RefocusNoise",       (double)0.01);
 
85
    settings.insert("RefocusRadius",        (double)defaultPrm.rfRadius);
 
86
    settings.insert("RefocusCorrelation",   (double)defaultPrm.rfCorrelation);
 
87
    settings.insert("RefocusNoise",         (double)defaultPrm.rfNoise);
 
88
    settings.insert("RefocusGauss",         (double)defaultPrm.rfGauss);
 
89
    settings.insert("RefocusMatrixSize",    (int)defaultPrm.rfMatrix);
239
90
 
240
91
    return settings;
241
92
}
242
93
 
243
94
void Sharpen::slotAssignSettings2Widget()
244
95
{
 
96
    SharpContainer prm;
 
97
 
245
98
    // sharpen method
246
 
    int w = settings()["SharpenFilterType"].toInt();
247
 
    m_sharpMethod->setCurrentIndex(w);
248
 
    m_stack->setCurrentWidget(m_stack->widget(w));
 
99
    prm.method        = settings()["SharpenFilterType"].toInt();
249
100
 
250
101
    // simple sharp
251
 
    m_radiusInput->setValue(settings()["SimpleSharpRadius"].toInt());
 
102
    prm.ssRadius      = settings()["SimpleSharpRadius"].toInt();
252
103
 
253
104
    // unsharp mask
254
 
    m_radiusInput2->setValue(settings()["UnsharpMaskRadius"].toInt());
255
 
    m_amountInput->setValue(settings()["UnsharpMaskAmount"].toDouble());
256
 
    m_thresholdInput->setValue(settings()["UnsharpMaskThreshold"].toDouble());
 
105
    prm.umRadius      = settings()["UnsharpMaskRadius"].toDouble();
 
106
    prm.umAmount      = settings()["UnsharpMaskAmount"].toDouble();
 
107
    prm.umThreshold   = settings()["UnsharpMaskThreshold"].toDouble();
257
108
 
258
109
    // refocus
259
 
    m_radius->setValue(settings()["RefocusRadius"].toDouble());
260
 
    m_gauss->setValue(settings()["RefocusGauss"].toDouble());
261
 
    m_correlation->setValue(settings()["RefocusCorrelation"].toDouble());
262
 
    m_noise->setValue(settings()["RefocusNoise"].toDouble());
263
 
    m_matrixSize->setValue(settings()["RefocusMatrixSize"].toInt());
 
110
    prm.rfRadius      = settings()["RefocusRadius"].toDouble();
 
111
    prm.rfCorrelation = settings()["RefocusCorrelation"].toDouble();
 
112
    prm.rfNoise       = settings()["RefocusNoise"].toDouble();
 
113
    prm.rfGauss       = settings()["RefocusGauss"].toDouble();
 
114
    prm.rfMatrix      = settings()["RefocusMatrixSize"].toInt();
 
115
 
 
116
    m_settingsView->setSettings(prm);
264
117
}
265
118
 
266
119
void Sharpen::slotSettingsChanged()
267
120
{
268
121
    BatchToolSettings settings;
 
122
    SharpContainer prm = m_settingsView->settings();
269
123
 
270
 
    // sharpen type
271
 
    settings.insert("SharpenFilterType", (int)m_sharpMethod->currentIndex());
 
124
    // sharpen method
 
125
    settings.insert("SharpenFilterType",    (int)prm.method);
272
126
 
273
127
    // simple sharp
274
 
    settings.insert("SimpleSharpRadius", (int)m_radiusInput->value());
 
128
    settings.insert("SimpleSharpRadius",    (int)prm.ssRadius);
275
129
 
276
130
    // unsharp mask
277
 
    settings.insert("UnsharpMaskRadius",    (int)m_radiusInput2->value());
278
 
    settings.insert("UnsharpMaskAmount",    (double)m_amountInput->value());
279
 
    settings.insert("UnsharpMaskThreshold", (double)m_thresholdInput->value());
 
131
    settings.insert("UnsharpMaskRadius",    (double)prm.umRadius);
 
132
    settings.insert("UnsharpMaskAmount",    (double)prm.umAmount);
 
133
    settings.insert("UnsharpMaskThreshold", (double)prm.umThreshold);
280
134
 
281
135
    // refocus
282
 
    settings.insert("RefocusRadius",      (double)m_radius->value());
283
 
    settings.insert("RefocusCorrelation", (double)m_correlation->value());
284
 
    settings.insert("RefocusNoise",       (double)m_noise->value());
285
 
    settings.insert("RefocusGauss",       (double)m_gauss->value());
286
 
    settings.insert("RefocusMatrixSize",  (double)m_matrixSize->value());
287
 
 
288
 
    setSettings(settings);
289
 
}
290
 
 
291
 
void Sharpen::slotSharpMethodChanged(int w)
292
 
{
293
 
    m_stack->setCurrentWidget(m_stack->widget(w));
294
 
    slotSettingsChanged();
 
136
    settings.insert("RefocusRadius",        (double)prm.rfRadius);
 
137
    settings.insert("RefocusCorrelation",   (double)prm.rfCorrelation);
 
138
    settings.insert("RefocusNoise",         (double)prm.rfNoise);
 
139
    settings.insert("RefocusGauss",         (double)prm.rfGauss);
 
140
    settings.insert("RefocusMatrixSize",    (int)prm.rfMatrix);
 
141
 
 
142
    BatchTool::slotSettingsChanged(settings);
295
143
}
296
144
 
297
145
bool Sharpen::toolOperations()
301
149
 
302
150
    int filterType  = settings()["SharpenFilterType"].toInt();
303
151
 
304
 
    uint width      = image().width();
305
 
    uint height     = image().height();
306
 
    uchar *data     = image().bits();
307
 
    bool sixteenBit = image().sixteenBit();
308
 
 
309
152
    switch (filterType)
310
153
    {
311
 
        case SimpleSharp:
 
154
        case SharpContainer::SimpleSharp:
312
155
        {
313
156
            double radius = settings()["SimpleSharpRadius"].toInt() / 10.0;
314
157
            double sigma;
318
161
            else
319
162
                sigma = sqrt(radius);
320
163
 
321
 
            DImg orgImage(width, height, sixteenBit, true, data);
322
 
            DImgSharpen *filter = new DImgSharpen(&orgImage, 0L, radius, sigma);
323
 
            filter->startFilterDirectly();
324
 
            DImg imDest = filter->getTargetImage();
325
 
            memcpy( data, imDest.bits(), imDest.numBytes() );
326
 
            delete filter;
 
164
            SharpenFilter filter(&image(), 0L, radius, sigma);
 
165
            filter.startFilterDirectly();
 
166
            image().putImageData(filter.getTargetImage().bits());
327
167
            break;
328
168
        }
329
169
 
330
 
        case UnsharpMask:
 
170
        case SharpContainer::UnsharpMask:
331
171
        {
332
 
            int r = settings()["UnsharpMaskRadius"].toInt();
333
 
            double a = settings()["UnsharpMaskAmount"].toDouble();
 
172
            int r     = (int)settings()["UnsharpMaskRadius"].toDouble();
 
173
            double a  = settings()["UnsharpMaskAmount"].toDouble();
334
174
            double th = settings()["UnsharpMaskThreshold"].toDouble();
335
175
 
336
 
            DImg orgImage(width, height, sixteenBit, true, data);
337
 
            DImgUnsharpMask *filter = new DImgUnsharpMask(&orgImage, 0L, r, a, th);
338
 
            filter->startFilterDirectly();
339
 
            DImg imDest = filter->getTargetImage();
340
 
            memcpy( data, imDest.bits(), imDest.numBytes());
341
 
            delete filter;
 
176
            UnsharpMaskFilter filter(&image(), 0L, r, a, th);
 
177
            filter.startFilterDirectly();
 
178
            image().putImageData(filter.getTargetImage().bits());
342
179
            break;
343
180
        }
344
181
 
345
 
        case Refocus:
 
182
        case SharpContainer::Refocus:
346
183
        {
347
 
            int matrixSize     = settings()["RefocusMatrixSize"].toInt();
348
184
            double radius      = settings()["RefocusRadius"].toDouble();
349
 
            double gauss       = settings()["RefocusGauss"].toDouble();
350
185
            double correlation = settings()["RefocusCorrelation"].toDouble();
351
186
            double noise       = settings()["RefocusNoise"].toDouble();
 
187
            double gauss       = settings()["RefocusGauss"].toDouble();
 
188
            int matrixSize     = settings()["RefocusMatrixSize"].toInt();
352
189
 
353
 
            DImg orgImage(width, height, sixteenBit, true, data);
354
 
            DImgRefocus *filter = new DImgRefocus(&orgImage, 0L, matrixSize,
355
 
                                                  radius, gauss, correlation, noise);
356
 
            filter->startFilterDirectly();
357
 
            DImg imDest = filter->getTargetImage();
358
 
            memcpy( data, imDest.bits(), imDest.numBytes());
359
 
            delete filter;
 
190
            RefocusFilter filter(&image(), 0L, matrixSize, radius, gauss, correlation, noise);
 
191
            filter.startFilterDirectly();
 
192
            image().putImageData(filter.getTargetImage().bits());
360
193
            break;
361
194
        }
362
195
    }