File indexing completed on 2024-05-26 04:33:07

0001 /*
0002  * This file is part of the KDE project
0003  *
0004  * SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net>
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "kis_wavelet_noise_reduction.h"
0009 
0010 
0011 #include <cmath>
0012 
0013 #include <KoUpdater.h>
0014 
0015 #include <kis_layer.h>
0016 #include <kis_math_toolbox.h>
0017 #include <widgets/kis_multi_double_filter_widget.h>
0018 #include <widgets/kis_multi_integer_filter_widget.h>
0019 #include <kis_paint_device.h>
0020 #include <filter/kis_filter_category_ids.h>
0021 #include <filter/kis_filter_configuration.h>
0022 #include <kis_processing_information.h>
0023 #include "kis_global.h"
0024 
0025 KisWaveletNoiseReduction::KisWaveletNoiseReduction()
0026     : KisFilter(id(), FiltersCategoryEnhanceId, i18n("&Wavelet Noise Reducer..."))
0027 {
0028     setSupportsPainting(false);
0029     setSupportsThreading(false);
0030 }
0031 
0032 
0033 KisWaveletNoiseReduction::~KisWaveletNoiseReduction()
0034 {
0035 }
0036 
0037 KisConfigWidget * KisWaveletNoiseReduction::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP, bool) const
0038 {
0039     vKisDoubleWidgetParam param;
0040     param.push_back(KisDoubleWidgetParam(0.0, 256.0, BEST_WAVELET_THRESHOLD_VALUE, i18n("Threshold"), "threshold"));
0041     return new KisMultiDoubleFilterWidget(id().id(), parent, id().id(), param);
0042 }
0043 
0044 KisFilterConfigurationSP KisWaveletNoiseReduction::defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const
0045 {
0046     KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
0047     config->setProperty("threshold", BEST_WAVELET_THRESHOLD_VALUE);
0048     return config;
0049 }
0050 
0051 void KisWaveletNoiseReduction::processImpl(KisPaintDeviceSP device,
0052                                            const QRect& applyRect,
0053                                            const KisFilterConfigurationSP config,
0054                                            KoUpdater* progressUpdater
0055                                            ) const
0056 {
0057     Q_ASSERT(device);
0058 
0059     KIS_SAFE_ASSERT_RECOVER_RETURN(config);
0060     const float threshold = config->getDouble("threshold", BEST_WAVELET_THRESHOLD_VALUE);
0061 
0062     KisMathToolbox mathToolbox;
0063 
0064     //     dbgFilters << size <<"" << maxrectsize <<"" << srcTopLeft.x() <<"" << srcTopLeft.y();
0065 
0066     //     dbgFilters <<"Transforming...";
0067     KisMathToolbox::KisWavelet* buff = 0;
0068     KisMathToolbox::KisWavelet* wav = 0;
0069 
0070     try {
0071         buff = mathToolbox.initWavelet(device, applyRect);
0072     } catch (const std::bad_alloc&) {
0073         if (buff) delete buff;
0074         return;
0075     }
0076     try {
0077         wav = mathToolbox.fastWaveletTransformation(device, applyRect, buff);
0078     } catch (const std::bad_alloc&) {
0079         if (wav) delete wav;
0080         return;
0081     }
0082 
0083     float* const fin = wav->coeffs + wav->depth * pow2(wav->size);
0084     float* const begin = wav->coeffs + wav->depth;
0085 
0086     const int size = fin - begin;
0087     const int progressOffset = int(std::ceil(std::log2(size / 100)));
0088     const int progressMask = (1 << progressOffset) - 1;
0089     const int numProgressSteps = size >> progressOffset;
0090     int pointsProcessed = 0;
0091 
0092     progressUpdater->setRange(0, numProgressSteps);
0093 
0094     for (float* it = begin; it < fin; it++) {
0095         if (*it > threshold) {
0096             *it -= threshold;
0097         } else if (*it < -threshold) {
0098             *it += threshold;
0099         } else {
0100             *it = 0.;
0101         }
0102 
0103         if (!(pointsProcessed & progressMask)) {
0104             progressUpdater->setValue(pointsProcessed >> progressOffset);
0105         }
0106         pointsProcessed++;
0107     }
0108 
0109     mathToolbox.fastWaveletUntransformation(device, applyRect, wav, buff);
0110 
0111     delete wav;
0112     delete buff;
0113 }