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 }