File indexing completed on 2024-12-22 04:15:26
0001 /* 0002 * This file is part of the KDE project 0003 * 0004 * SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "wavefilter.h" 0010 #include <stdlib.h> 0011 #include <vector> 0012 #include <math.h> 0013 #include <QPoint> 0014 0015 #include <kis_debug.h> 0016 #include <kpluginfactory.h> 0017 0018 #include <klocalizedstring.h> 0019 0020 #include <KoUpdater.h> 0021 0022 #include <kis_image.h> 0023 #include <filter/kis_filter_registry.h> 0024 #include <kis_global.h> 0025 #include <kis_layer.h> 0026 #include <kis_random_sub_accessor.h> 0027 #include <kis_selection.h> 0028 #include <kis_types.h> 0029 #include <kis_paint_device.h> 0030 #include <filter/kis_filter_category_ids.h> 0031 #include <filter/kis_filter_configuration.h> 0032 #include <kis_processing_information.h> 0033 #include "kis_wdg_wave.h" 0034 #include "ui_wdgwaveoptions.h" 0035 #include <kis_iterator_ng.h> 0036 #include <KisSequentialIteratorProgress.h> 0037 0038 K_PLUGIN_FACTORY_WITH_JSON(KritaWaveFilterFactory, "kritawavefilter.json", registerPlugin<KritaWaveFilter>();) 0039 0040 class KisWaveCurve 0041 { 0042 public: 0043 virtual ~KisWaveCurve() {} 0044 virtual double valueAt(int x, int y) = 0; 0045 }; 0046 0047 class KisSinusoidalWaveCurve : public KisWaveCurve 0048 { 0049 public: 0050 0051 KisSinusoidalWaveCurve(int amplitude, int wavelength, int shift) 0052 : m_amplitude(amplitude) 0053 , m_shift(shift) 0054 { 0055 m_wavelength = wavelength == 0 ? 1 : wavelength; 0056 } 0057 0058 ~KisSinusoidalWaveCurve() override {} 0059 0060 double valueAt(int x, int y) override { 0061 KIS_ASSERT(m_wavelength != 0); 0062 return y + m_amplitude * cos((double)(m_shift + x) / m_wavelength); 0063 } 0064 private: 0065 int m_amplitude, m_wavelength, m_shift; 0066 }; 0067 0068 class KisTriangleWaveCurve : public KisWaveCurve 0069 { 0070 public: 0071 0072 KisTriangleWaveCurve(int amplitude, int wavelength, int shift) 0073 : m_amplitude(amplitude) 0074 , m_shift(shift) 0075 { 0076 m_wavelength = wavelength == 0 ? 1 : wavelength; 0077 } 0078 0079 ~KisTriangleWaveCurve() override {} 0080 0081 double valueAt(int x, int y) override { 0082 KIS_ASSERT(m_wavelength != 0); 0083 return y + m_amplitude * pow(-1.0, (m_shift + x) / m_wavelength) *(0.5 - (double)((m_shift + x) % m_wavelength) / m_wavelength); 0084 } 0085 private: 0086 int m_amplitude, m_wavelength, m_shift; 0087 }; KritaWaveFilter::KritaWaveFilter(QObject *parent, const QVariantList &) 0088 : QObject(parent) 0089 { 0090 KisFilterRegistry::instance()->add(new KisFilterWave()); 0091 } 0092 0093 KritaWaveFilter::~KritaWaveFilter() 0094 { 0095 } 0096 0097 KisFilterWave::KisFilterWave() : KisFilter(id(), FiltersCategoryOtherId, i18n("&Wave...")) 0098 { 0099 setColorSpaceIndependence(FULLY_INDEPENDENT); 0100 setSupportsPainting(false); 0101 setSupportsAdjustmentLayers(true); 0102 } 0103 0104 KisFilterConfigurationSP KisFilterWave::defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const 0105 { 0106 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface); 0107 config->setProperty("horizontalwavelength", 50); 0108 config->setProperty("horizontalshift", 50); 0109 config->setProperty("horizontalamplitude", 4); 0110 config->setProperty("horizontalshape", 0); 0111 config->setProperty("verticalwavelength", 50); 0112 config->setProperty("verticalshift", 50); 0113 config->setProperty("verticalamplitude", 4); 0114 config->setProperty("verticalshape", 0); 0115 return config; 0116 } 0117 0118 KisConfigWidget * KisFilterWave::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP, bool) const 0119 { 0120 return new KisWdgWave((KisFilter*)this, (QWidget*)parent); 0121 } 0122 0123 void KisFilterWave::processImpl(KisPaintDeviceSP device, 0124 const QRect& applyRect, 0125 const KisFilterConfigurationSP config, 0126 KoUpdater* progressUpdater 0127 ) const 0128 { 0129 Q_ASSERT(device.data() != 0); 0130 0131 QVariant value; 0132 int horizontalwavelength = (config && config->getProperty("horizontalwavelength", value)) ? value.toInt() : 50; 0133 int horizontalshift = (config && config->getProperty("horizontalshift", value)) ? value.toInt() : 50; 0134 int horizontalamplitude = (config && config->getProperty("horizontalamplitude", value)) ? value.toInt() : 4; 0135 int horizontalshape = (config && config->getProperty("horizontalshape", value)) ? value.toInt() : 0; 0136 int verticalwavelength = (config && config->getProperty("verticalwavelength", value)) ? value.toInt() : 50; 0137 int verticalshift = (config && config->getProperty("verticalshift", value)) ? value.toInt() : 50; 0138 int verticalamplitude = (config && config->getProperty("verticalamplitude", value)) ? value.toInt() : 4; 0139 int verticalshape = (config && config->getProperty("verticalshape", value)) ? value.toInt() : 0; 0140 0141 KisWaveCurve* verticalWave; 0142 if (verticalshape == 1) 0143 verticalWave = new KisTriangleWaveCurve(verticalamplitude, verticalwavelength, verticalshift); 0144 else 0145 verticalWave = new KisSinusoidalWaveCurve(verticalamplitude, verticalwavelength, verticalshift); 0146 0147 KisWaveCurve* horizontalWave; 0148 if (horizontalshape == 1) 0149 horizontalWave = new KisTriangleWaveCurve(horizontalamplitude, horizontalwavelength, horizontalshift); 0150 else 0151 horizontalWave = new KisSinusoidalWaveCurve(horizontalamplitude, horizontalwavelength, horizontalshift); 0152 0153 KisSequentialIteratorProgress destination(device, applyRect, progressUpdater); 0154 KisRandomSubAccessorSP source = device->createRandomSubAccessor(); 0155 0156 while (destination.nextPixel()) { 0157 double xv = horizontalWave->valueAt(destination.y(), destination.x()); 0158 double yv = verticalWave->valueAt(destination.x(), destination.y()); 0159 source->moveTo(QPointF(xv, yv)); 0160 source->sampledOldRawData(destination.rawData()); 0161 } 0162 0163 delete verticalWave; 0164 delete horizontalWave; 0165 } 0166 0167 QRect KisFilterWave::changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const 0168 { 0169 Q_UNUSED(lod); 0170 0171 QVariant value; 0172 int horizontalamplitude = (config && config->getProperty("horizontalamplitude", value)) ? value.toInt() : 4; 0173 int verticalamplitude = (config && config->getProperty("verticalamplitude", value)) ? value.toInt() : 4; 0174 return rect.adjusted(-horizontalamplitude, -verticalamplitude, horizontalamplitude, verticalamplitude); 0175 } 0176 0177 QRect KisFilterWave::neededRect(const QRect& rect, const KisFilterConfigurationSP config, int lod) const 0178 { 0179 return changedRect(rect, config, lod); 0180 } 0181 0182 #include "wavefilter.moc"