File indexing completed on 2025-03-09 03:50:32
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2004-07-09 0007 * Description : a tool to sharp an image 0008 * 0009 * SPDX-FileCopyrightText: 2004-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "sharpentool.h" 0016 0017 // C++ includes 0018 0019 #include <cmath> 0020 0021 // Qt includes 0022 0023 #include <QGridLayout> 0024 #include <QLabel> 0025 #include <QIcon> 0026 0027 // KDE includes 0028 0029 #include <ksharedconfig.h> 0030 #include <klocalizedstring.h> 0031 #include <kconfiggroup.h> 0032 0033 // Local includes 0034 0035 #include "digikam_config.h" 0036 #include "sharpsettings.h" 0037 #include "sharpenfilter.h" 0038 #include "unsharpmaskfilter.h" 0039 #include "editortoolsettings.h" 0040 #include "imageiface.h" 0041 #include "imageregionwidget.h" 0042 0043 #ifdef HAVE_EIGEN3 0044 # include "refocusfilter.h" 0045 #endif // HAVE_EIGEN3 0046 0047 namespace DigikamEditorSharpenToolPlugin 0048 { 0049 0050 class Q_DECL_HIDDEN SharpenTool::Private 0051 { 0052 0053 public: 0054 0055 explicit Private() 0056 : configGroupName(QLatin1String("sharpen Tool")), 0057 sharpSettings (nullptr), 0058 previewWidget (nullptr), 0059 gboxSettings (nullptr) 0060 { 0061 } 0062 0063 const QString configGroupName; 0064 0065 SharpSettings* sharpSettings; 0066 ImageRegionWidget* previewWidget; 0067 EditorToolSettings* gboxSettings; 0068 }; 0069 0070 SharpenTool::SharpenTool(QObject* const parent) 0071 : EditorToolThreaded(parent), 0072 d (new Private) 0073 { 0074 setObjectName(QLatin1String("sharpen")); 0075 setToolHelp(QLatin1String("blursharpentool.anchor")); 0076 0077 // ------------------------------------------------------------- 0078 0079 d->gboxSettings = new EditorToolSettings(nullptr); 0080 d->gboxSettings->setButtons(EditorToolSettings::Default| 0081 EditorToolSettings::Ok| 0082 EditorToolSettings::Cancel| 0083 EditorToolSettings::Load| 0084 EditorToolSettings::SaveAs| 0085 EditorToolSettings::Try); 0086 0087 d->previewWidget = new ImageRegionWidget; 0088 0089 d->sharpSettings = new SharpSettings(d->gboxSettings->plainPage()); 0090 setToolSettings(d->gboxSettings); 0091 setToolView(d->previewWidget); 0092 setPreviewModeMask(PreviewToolBar::AllPreviewModes); 0093 0094 connect(d->sharpSettings, SIGNAL(signalSettingsChanged()), 0095 this, SLOT(slotSettingsChanged())); 0096 } 0097 0098 SharpenTool::~SharpenTool() 0099 { 0100 delete d; 0101 } 0102 0103 void SharpenTool::slotSettingsChanged() 0104 { 0105 switch (d->sharpSettings->settings().method) 0106 { 0107 case SharpContainer::SimpleSharp: 0108 { 0109 d->gboxSettings->enableButton(EditorToolSettings::Load, false); 0110 d->gboxSettings->enableButton(EditorToolSettings::SaveAs, false); 0111 break; 0112 } 0113 case SharpContainer::UnsharpMask: 0114 { 0115 d->gboxSettings->enableButton(EditorToolSettings::Load, false); 0116 d->gboxSettings->enableButton(EditorToolSettings::SaveAs, false); 0117 break; 0118 } 0119 case SharpContainer::Refocus: 0120 { 0121 break; 0122 } 0123 } 0124 } 0125 0126 void SharpenTool::readSettings() 0127 { 0128 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0129 KConfigGroup group = config->group(d->configGroupName); 0130 d->sharpSettings->readSettings(group); 0131 } 0132 0133 void SharpenTool::writeSettings() 0134 { 0135 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0136 KConfigGroup group = config->group(d->configGroupName); 0137 d->sharpSettings->writeSettings(group); 0138 group.sync(); 0139 } 0140 0141 void SharpenTool::slotResetSettings() 0142 { 0143 d->sharpSettings->resetToDefault(); 0144 } 0145 0146 void SharpenTool::preparePreview() 0147 { 0148 SharpContainer settings = d->sharpSettings->settings(); 0149 0150 switch (settings.method) 0151 { 0152 case SharpContainer::SimpleSharp: 0153 { 0154 DImg img = d->previewWidget->getOriginalRegionImage(); 0155 double radius = settings.ssRadius/10.0; 0156 double sigma; 0157 0158 if (radius < 1.0) 0159 { 0160 sigma = radius; 0161 } 0162 else 0163 { 0164 sigma = sqrt(radius); 0165 } 0166 0167 setFilter(new SharpenFilter(&img, this, radius, sigma)); 0168 break; 0169 } 0170 0171 case SharpContainer::UnsharpMask: 0172 { 0173 DImg img = d->previewWidget->getOriginalRegionImage(); 0174 double r = settings.umRadius; 0175 double a = settings.umAmount; 0176 double th = settings.umThreshold; 0177 bool l = settings.umLumaOnly; 0178 0179 setFilter(new UnsharpMaskFilter(&img, this, r, a, th, l)); 0180 break; 0181 } 0182 0183 case SharpContainer::Refocus: 0184 { 0185 0186 #ifdef HAVE_EIGEN3 0187 DImg img = d->previewWidget->getOriginalRegionImage(); 0188 double r = settings.rfRadius; 0189 double c = settings.rfCorrelation; 0190 double n = settings.rfNoise; 0191 double g = settings.rfGauss; 0192 int ms = settings.rfMatrix; 0193 0194 setFilter(new RefocusFilter(&img, this, ms, r, g, c, n)); 0195 #endif // HAVE_EIGEN3 0196 0197 break; 0198 } 0199 } 0200 } 0201 0202 void SharpenTool::setPreviewImage() 0203 { 0204 DImg preview = filter()->getTargetImage(); 0205 d->previewWidget->setPreviewImage(preview); 0206 } 0207 0208 void SharpenTool::prepareFinal() 0209 { 0210 ImageIface iface; 0211 SharpContainer settings = d->sharpSettings->settings(); 0212 0213 switch (settings.method) 0214 { 0215 case SharpContainer::SimpleSharp: 0216 { 0217 double radius = settings.ssRadius/10.0; 0218 double sigma; 0219 0220 if (radius < 1.0) 0221 { 0222 sigma = radius; 0223 } 0224 else 0225 { 0226 sigma = sqrt(radius); 0227 } 0228 0229 setFilter(new SharpenFilter(iface.original(), this, radius, sigma)); 0230 break; 0231 } 0232 0233 case SharpContainer::UnsharpMask: 0234 { 0235 double r = settings.umRadius; 0236 double a = settings.umAmount; 0237 double th = settings.umThreshold; 0238 0239 setFilter(new UnsharpMaskFilter(iface.original(), this, r, a, th)); 0240 break; 0241 } 0242 0243 case SharpContainer::Refocus: 0244 { 0245 0246 #ifdef HAVE_EIGEN3 0247 double r = settings.rfRadius; 0248 double c = settings.rfCorrelation; 0249 double n = settings.rfNoise; 0250 double g = settings.rfGauss; 0251 int ms = settings.rfMatrix; 0252 0253 setFilter(new RefocusFilter(iface.original(), this, ms, r, g, c, n)); 0254 #endif // HAVE_EIGEN3 0255 0256 break; 0257 } 0258 } 0259 } 0260 0261 void SharpenTool::setFinalImage() 0262 { 0263 ImageIface iface; 0264 SharpContainer settings = d->sharpSettings->settings(); 0265 0266 switch (settings.method) 0267 { 0268 case SharpContainer::SimpleSharp: 0269 { 0270 iface.setOriginal(i18n("Sharpen"), filter()->filterAction(), filter()->getTargetImage()); 0271 break; 0272 } 0273 0274 case SharpContainer::UnsharpMask: 0275 { 0276 iface.setOriginal(i18n("Unsharp Mask"), filter()->filterAction(), filter()->getTargetImage()); 0277 break; 0278 } 0279 0280 case SharpContainer::Refocus: 0281 { 0282 0283 #ifdef HAVE_EIGEN3 0284 iface.setOriginal(i18n("Refocus"), filter()->filterAction(), filter()->getTargetImage()); 0285 #endif // HAVE_EIGEN3 0286 0287 break; 0288 } 0289 } 0290 } 0291 0292 void SharpenTool::renderingFinished() 0293 { 0294 slotSettingsChanged(); 0295 } 0296 0297 void SharpenTool::slotLoadSettings() 0298 { 0299 d->sharpSettings->loadSettings(); 0300 } 0301 0302 void SharpenTool::slotSaveAsSettings() 0303 { 0304 d->sharpSettings->saveAsSettings(); 0305 } 0306 0307 } // namespace DigikamEditorSharpenToolPlugin 0308 0309 #include "moc_sharpentool.cpp"