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"