1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2004-09-30
7 * Description : a tool to add rain drop over an image
8 *
9 * Copyright (C) 2004-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 * Copyright (C) 2006-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "raindroptool.h"
26
27 // Qt includes
28
29 #include <QFrame>
30 #include <QGridLayout>
31 #include <QImage>
32 #include <QLabel>
33 #include <QIcon>
34
35 // KDE includes
36
37 #include <ksharedconfig.h>
38 #include <kconfiggroup.h>
39 #include <klocalizedstring.h>
40
41 // Local includes
42
43 #include "dnuminput.h"
44 #include "editortoolsettings.h"
45 #include "imageiface.h"
46 #include "imageguidewidget.h"
47 #include "raindropfilter.h"
48
49 namespace DigikamEditorRainDropToolPlugin
50 {
51
52 class Q_DECL_HIDDEN RainDropTool::Private
53 {
54 public:
55
Private()56 explicit Private()
57 : dropInput (nullptr),
58 amountInput (nullptr),
59 coeffInput (nullptr),
60 previewWidget (nullptr),
61 gboxSettings (nullptr)
62 {
63 }
64
65 static const QString configGroupName;
66 static const QString configDropAdjustmentEntry;
67 static const QString configAmountAdjustmentEntry;
68 static const QString configCoeffAdjustmentEntry;
69
70 DIntNumInput* dropInput;
71 DIntNumInput* amountInput;
72 DIntNumInput* coeffInput;
73
74 ImageGuideWidget* previewWidget;
75 EditorToolSettings* gboxSettings;
76 };
77
78 const QString RainDropTool::Private::configGroupName(QLatin1String("raindrops Tool"));
79 const QString RainDropTool::Private::configDropAdjustmentEntry(QLatin1String("DropAdjustment"));
80 const QString RainDropTool::Private::configAmountAdjustmentEntry(QLatin1String("AmountAdjustment"));
81 const QString RainDropTool::Private::configCoeffAdjustmentEntry(QLatin1String("CoeffAdjustment"));
82
83 // --------------------------------------------------------
84
RainDropTool(QObject * const parent)85 RainDropTool::RainDropTool(QObject* const parent)
86 : EditorToolThreaded(parent),
87 d (new Private)
88 {
89 setObjectName(QLatin1String("raindrops"));
90
91 d->previewWidget = new ImageGuideWidget(nullptr, false, ImageGuideWidget::HVGuideMode);
92 d->previewWidget->setWhatsThis(i18n("This is the preview of the Raindrop effect."
93 "<p>Note: if you have previously selected an area in the editor, "
94 "this will be unaffected by the filter. You can use this method to "
95 "disable the Raindrops effect on a human face, for example.</p>"));
96
97 setToolView(d->previewWidget);
98 setPreviewModeMask(PreviewToolBar::AllPreviewModes);
99
100 // -------------------------------------------------------------
101
102 d->gboxSettings = new EditorToolSettings(nullptr);
103 d->gboxSettings->setButtons(EditorToolSettings::Default|
104 EditorToolSettings::Ok|
105 EditorToolSettings::Try|
106 EditorToolSettings::Cancel);
107
108
109 // -------------------------------------------------------------
110
111 QLabel* label1 = new QLabel(i18n("Drop size:"));
112 d->dropInput = new DIntNumInput;
113 d->dropInput->setRange(0, 200, 1);
114 d->dropInput->setDefaultValue(80);
115 d->dropInput->setWhatsThis( i18n("Set here the raindrops' size."));
116
117 // -------------------------------------------------------------
118
119 QLabel* label2 = new QLabel(i18n("Number:"));
120 d->amountInput = new DIntNumInput;
121 d->amountInput->setRange(1, 500, 1);
122 d->amountInput->setDefaultValue(150);
123 d->amountInput->setWhatsThis( i18n("This value controls the maximum number of raindrops."));
124
125 // -------------------------------------------------------------
126
127 QLabel* label3 = new QLabel(i18n("Fish eyes:"));
128 d->coeffInput = new DIntNumInput;
129 d->coeffInput->setRange(1, 100, 1);
130 d->coeffInput->setDefaultValue(30);
131 d->coeffInput->setWhatsThis( i18n("This value is the fish-eye-effect optical "
132 "distortion coefficient."));
133
134 // -------------------------------------------------------------
135
136 const int spacing = d->gboxSettings->spacingHint();
137
138 QGridLayout* mainLayout = new QGridLayout;
139 mainLayout->addWidget(label1, 0, 0, 1, 3);
140 mainLayout->addWidget(d->dropInput, 1, 0, 1, 3);
141 mainLayout->addWidget(label2, 2, 0, 1, 3);
142 mainLayout->addWidget(d->amountInput, 3, 0, 1, 3);
143 mainLayout->addWidget(label3, 4, 0, 1, 3);
144 mainLayout->addWidget(d->coeffInput, 5, 0, 1, 3);
145 mainLayout->setRowStretch(6, 10);
146 mainLayout->setContentsMargins(spacing, spacing, spacing, spacing);
147 mainLayout->setSpacing(spacing);
148 d->gboxSettings->plainPage()->setLayout(mainLayout);
149
150 // -------------------------------------------------------------
151
152 setToolSettings(d->gboxSettings);
153 }
154
~RainDropTool()155 RainDropTool::~RainDropTool()
156 {
157 delete d;
158 }
159
readSettings()160 void RainDropTool::readSettings()
161 {
162 KSharedConfig::Ptr config = KSharedConfig::openConfig();
163 KConfigGroup group = config->group(d->configGroupName);
164
165 blockWidgetSignals(true);
166
167 d->dropInput->setValue(group.readEntry(d->configDropAdjustmentEntry, d->dropInput->defaultValue()));
168 d->amountInput->setValue(group.readEntry(d->configAmountAdjustmentEntry, d->amountInput->defaultValue()));
169 d->coeffInput->setValue(group.readEntry(d->configCoeffAdjustmentEntry, d->coeffInput->defaultValue()));
170
171 blockWidgetSignals(false);
172 }
173
writeSettings()174 void RainDropTool::writeSettings()
175 {
176 KSharedConfig::Ptr config = KSharedConfig::openConfig();
177 KConfigGroup group = config->group(d->configGroupName);
178 group.writeEntry(d->configDropAdjustmentEntry, d->dropInput->value());
179 group.writeEntry(d->configAmountAdjustmentEntry, d->amountInput->value());
180 group.writeEntry(d->configCoeffAdjustmentEntry, d->coeffInput->value());
181
182 group.sync();
183 }
184
slotResetSettings()185 void RainDropTool::slotResetSettings()
186 {
187 blockWidgetSignals(true);
188
189 d->dropInput->slotReset();
190 d->amountInput->slotReset();
191 d->coeffInput->slotReset();
192
193 blockWidgetSignals(false);
194
195 slotPreview();
196 }
197
preparePreview()198 void RainDropTool::preparePreview()
199 {
200 int drop = d->dropInput->value();
201 int amount = d->amountInput->value();
202 int coeff = d->coeffInput->value();
203
204 ImageIface* const iface = d->previewWidget->imageIface();
205
206 // Selected data from the image
207 QRect selection = iface->selectionRect();
208
209 setFilter(new RainDropFilter(iface->original(), this, drop, amount, coeff, selection));
210 }
211
prepareFinal()212 void RainDropTool::prepareFinal()
213 {
214 int drop = d->dropInput->value();
215 int amount = d->amountInput->value();
216 int coeff = d->coeffInput->value();
217
218 ImageIface iface;
219
220 // Selected data from the image
221 QRect selection = iface.selectionRect();
222
223 setFilter(new RainDropFilter(iface.original(), this, drop, amount, coeff, selection));
224 }
225
setPreviewImage()226 void RainDropTool::setPreviewImage()
227 {
228 ImageIface* const iface = d->previewWidget->imageIface();
229 DImg imDest = filter()->getTargetImage().smoothScale(iface->previewSize());
230 iface->setPreview(imDest);
231
232 d->previewWidget->updatePreview();
233 }
234
setFinalImage()235 void RainDropTool::setFinalImage()
236 {
237 ImageIface iface;
238 iface.setOriginal(i18n("RainDrop"), filter()->filterAction(), filter()->getTargetImage());
239 }
240
blockWidgetSignals(bool b)241 void RainDropTool::blockWidgetSignals(bool b)
242 {
243 d->dropInput->blockSignals(b);
244 d->amountInput->blockSignals(b);
245 d->coeffInput->blockSignals(b);
246 }
247
248 } // namespace DigikamEditorRainDropToolPlugin
249