File indexing completed on 2024-05-12 15:58:15

0001 /*
0002  *  SPDX-FileCopyrightText: 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
0003  *  SPDX-FileCopyrightText: 2005 C. Boemann <cbo@boemann.dk>
0004  *  SPDX-FileCopyrightText: 2013 Juan Palacios <jpalaciosdev@gmail.com>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef KIS_FILTER_STRATEGY_H_
0010 #define KIS_FILTER_STRATEGY_H_
0011 
0012 #include <klocalizedstring.h>
0013 
0014 #include "KoGenericRegistry.h"
0015 #include "KoID.h"
0016 #include "kritaimage_export.h"
0017 #include <QSize>
0018 
0019 class KRITAIMAGE_EXPORT KisFilterStrategy
0020 {
0021 public:
0022     KisFilterStrategy(KoID id) : m_id(id) {}
0023     virtual ~KisFilterStrategy() {  }
0024 
0025     QString id() {
0026         return m_id.id();
0027     }
0028     QString name() {
0029         return m_id.name();
0030     }
0031     virtual qreal valueAt(qreal t, qreal weightsPositionScale) const {
0032         Q_UNUSED(t);
0033         Q_UNUSED(weightsPositionScale);
0034         return 0;
0035     }
0036     virtual qint32 intValueAt(qint32 t, qreal weightsPositionScale) const {
0037         return qint32(255*valueAt(t / 256.0, weightsPositionScale));
0038     }
0039     virtual qreal support(qreal weightsPositionScale) {
0040         Q_UNUSED(weightsPositionScale);
0041         return supportVal;
0042     }
0043     virtual qint32 intSupport(qreal weightsPositionScale) {
0044         Q_UNUSED(weightsPositionScale);
0045         return intSupportVal;
0046     }
0047     virtual QString description() {
0048         return QString();
0049     }
0050 
0051 protected:
0052     qreal supportVal {0.0};
0053     qint32 intSupportVal {0};
0054     KoID m_id;
0055 };
0056 
0057 class KRITAIMAGE_EXPORT KisHermiteFilterStrategy : public KisFilterStrategy
0058 {
0059 public:
0060     KisHermiteFilterStrategy() : KisFilterStrategy(KoID("Hermite", i18n("Hermite"))) {
0061         supportVal = 1.0; intSupportVal = 256;
0062     }
0063     ~KisHermiteFilterStrategy() override {}
0064 
0065     qint32 intValueAt(qint32 t, qreal weightsPositionScale) const override;
0066     qreal valueAt(qreal t, qreal weightsPositionScale) const override;
0067 };
0068 
0069 class KRITAIMAGE_EXPORT KisBicubicFilterStrategy : public KisFilterStrategy
0070 {
0071 public:
0072     KisBicubicFilterStrategy() : KisFilterStrategy(KoID("Bicubic", i18n("Bicubic"))) {
0073         supportVal = 2.0; intSupportVal = 512;
0074     }
0075     ~KisBicubicFilterStrategy() override {}
0076 
0077     QString description() override {
0078         return i18n("Adds pixels using the color of surrounding pixels. Produces smoother tonal gradations than Bilinear.");
0079     }
0080 
0081     qint32 intValueAt(qint32 t, qreal weightsPositionScale) const override;
0082 };
0083 class KRITAIMAGE_EXPORT KisBoxFilterStrategy : public KisFilterStrategy
0084 {
0085 public:
0086     KisBoxFilterStrategy() : KisFilterStrategy(KoID("NearestNeighbor", i18n("Nearest Neighbor"))) {
0087         // 0.5 and 128, but with a bit of margin to ensure the correct pixel will be used
0088         // even in case of calculation errors
0089         supportVal = 0.51; intSupportVal = 129;
0090     }
0091     ~KisBoxFilterStrategy() override {}
0092 
0093     QString description() override {
0094         return i18n("Replicate pixels in the image. Preserves all the original detail, but can produce jagged effects.");
0095     }
0096 
0097     virtual qreal support(qreal weightsPositionScale) override;
0098     virtual qint32 intSupport(qreal weightsPositionScale) override;
0099 
0100 
0101     qint32 intValueAt(qint32 t, qreal weightsPositionScale) const override;
0102     qreal valueAt(qreal t, qreal weightsPositionScale) const override;
0103 };
0104 
0105 class KRITAIMAGE_EXPORT KisBilinearFilterStrategy : public KisFilterStrategy
0106 {
0107 public:
0108     KisBilinearFilterStrategy() : KisFilterStrategy(KoID("Bilinear", i18n("Bilinear"))) {
0109         supportVal = 1.0; intSupportVal = 256;
0110     }
0111     ~KisBilinearFilterStrategy() override {}
0112 
0113     QString description() override {
0114         return i18n("Adds pixels averaging the color values of surrounding pixels. Produces medium quality results when the image is scaled from half to two times the original size.");
0115     }
0116 
0117     qint32 intValueAt(qint32 t, qreal weightsPositionScale) const override;
0118     qreal valueAt(qreal t, qreal weightsPositionScale) const override;
0119 };
0120 
0121 class KRITAIMAGE_EXPORT KisBellFilterStrategy : public KisFilterStrategy
0122 {
0123 public:
0124     KisBellFilterStrategy() : KisFilterStrategy(KoID("Bell", i18n("Bell"))) {
0125         supportVal = 1.5; intSupportVal = 128 + 256;
0126     }
0127     ~KisBellFilterStrategy() override {}
0128 
0129     qreal valueAt(qreal t, qreal weightsPositionScale) const override;
0130 };
0131 
0132 class KRITAIMAGE_EXPORT KisBSplineFilterStrategy : public KisFilterStrategy
0133 {
0134 public:
0135     KisBSplineFilterStrategy() : KisFilterStrategy(KoID("BSpline", i18n("BSpline"))) {
0136         supportVal = 2.0; intSupportVal = 512;
0137     }
0138     ~KisBSplineFilterStrategy() override {}
0139 
0140     qreal valueAt(qreal t, qreal weightsPositionScale) const override;
0141 };
0142 
0143 class KRITAIMAGE_EXPORT KisLanczos3FilterStrategy : public KisFilterStrategy
0144 {
0145 public:
0146     KisLanczos3FilterStrategy() : KisFilterStrategy(KoID("Lanczos3", i18n("Lanczos3"))) {
0147         supportVal = 3.0; intSupportVal = 768;
0148     }
0149     ~KisLanczos3FilterStrategy() override {}
0150 
0151     QString description() override {
0152         return i18n("Offers similar results than Bicubic, but maybe a little bit sharper. Can produce light and dark halos along strong edges.");
0153     }
0154 
0155     qreal valueAt(qreal t, qreal weightsPositionScale) const override;
0156 private:
0157     qreal sinc(qreal x) const;
0158 };
0159 
0160 class KRITAIMAGE_EXPORT  KisMitchellFilterStrategy : public KisFilterStrategy
0161 {
0162 public:
0163     KisMitchellFilterStrategy() : KisFilterStrategy(KoID("Mitchell", i18n("Mitchell"))) {
0164         supportVal = 2.0; intSupportVal = 256;
0165     }
0166     ~KisMitchellFilterStrategy() override {}
0167 
0168     qreal valueAt(qreal t, qreal weightsPositionScale) const override;
0169 };
0170 
0171 class KRITAIMAGE_EXPORT KisFilterStrategyRegistry : public KoGenericRegistry<KisFilterStrategy *>
0172 {
0173 
0174 public:
0175 
0176     KisFilterStrategyRegistry();
0177     ~KisFilterStrategyRegistry() override;
0178     static KisFilterStrategyRegistry* instance();
0179 
0180     /**
0181      * This function return a list of all the keys in KoID format by using the name() method
0182      * on the objects stored in the registry.
0183      */
0184     QList<KoID> listKeys() const;
0185 
0186     /**
0187      * This function return a string formatted in HTML that contains the descriptions of all objects
0188      * (with a non empty description) stored in the registry.
0189      */
0190     QString formattedDescriptions() const;
0191 
0192     /**
0193      * Try to select an appropriate image filtering strategy based on original and desired parameters.
0194      */
0195     KisFilterStrategy* autoFilterStrategy(QSize originalSize, QSize desiredSize) const;
0196 
0197 private:
0198 
0199     KisFilterStrategyRegistry(const KisFilterStrategyRegistry&);
0200     KisFilterStrategyRegistry operator=(const KisFilterStrategyRegistry&);
0201 
0202 };
0203 
0204 #endif // KIS_FILTER_STRATEGY_H_