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"