File indexing completed on 2024-05-12 15:58:42
0001 /* 0002 * SPDX-FileCopyrightText: 2005 Michael Thaler 0003 * SPDX-FileCopyrightText: 2011 Dmitry Kazakov <dimula73@gmail.com> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 0009 #ifndef KIS_SELECTION_FILTERS_H 0010 #define KIS_SELECTION_FILTERS_H 0011 0012 #include "kis_types.h" 0013 #include "kritaimage_export.h" 0014 #include "kis_default_bounds_base.h" 0015 0016 #include <QRect> 0017 #include <QString> 0018 0019 class KUndo2MagicString; 0020 0021 0022 class KRITAIMAGE_EXPORT KisSelectionFilter 0023 { 0024 public: 0025 virtual ~KisSelectionFilter(); 0026 0027 virtual void process(KisPixelSelectionSP pixelSelection, 0028 const QRect &rect) = 0; 0029 0030 virtual KUndo2MagicString name(); 0031 virtual QRect changeRect(const QRect &rect, KisDefaultBoundsBaseSP defaultBounds); 0032 0033 protected: 0034 void computeBorder(qint32 *circ, qint32 xradius, qint32 yradius); 0035 0036 void rotatePointers(quint8 **p, quint32 n); 0037 0038 void computeTransition(quint8* transition, quint8** buf, qint32 width); 0039 }; 0040 0041 class KRITAIMAGE_EXPORT KisErodeSelectionFilter : public KisSelectionFilter 0042 { 0043 public: 0044 KUndo2MagicString name() override; 0045 0046 QRect changeRect(const QRect &rect, KisDefaultBoundsBaseSP defaultBounds) override; 0047 0048 void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override; 0049 }; 0050 0051 class KRITAIMAGE_EXPORT KisDilateSelectionFilter : public KisSelectionFilter 0052 { 0053 public: 0054 KUndo2MagicString name() override; 0055 0056 QRect changeRect(const QRect &rect, KisDefaultBoundsBaseSP defaultBounds) override; 0057 0058 void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override; 0059 }; 0060 0061 class KRITAIMAGE_EXPORT KisBorderSelectionFilter : public KisSelectionFilter 0062 { 0063 public: 0064 KisBorderSelectionFilter(qint32 xRadius, qint32 yRadius, bool fade); 0065 0066 KUndo2MagicString name() override; 0067 0068 QRect changeRect(const QRect &rect, KisDefaultBoundsBaseSP defaultBounds) override; 0069 0070 void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override; 0071 0072 private: 0073 qint32 m_xRadius; 0074 qint32 m_yRadius; 0075 bool m_antialiasing; 0076 }; 0077 0078 class KRITAIMAGE_EXPORT KisFeatherSelectionFilter : public KisSelectionFilter 0079 { 0080 public: 0081 KisFeatherSelectionFilter(qint32 radius); 0082 0083 KUndo2MagicString name() override; 0084 0085 QRect changeRect(const QRect &rect, KisDefaultBoundsBaseSP defaultBounds) override; 0086 0087 void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override; 0088 private: 0089 qint32 m_radius; 0090 }; 0091 0092 class KRITAIMAGE_EXPORT KisGrowSelectionFilter : public KisSelectionFilter 0093 { 0094 public: 0095 KisGrowSelectionFilter(qint32 xRadius, qint32 yRadius); 0096 0097 KUndo2MagicString name() override; 0098 0099 QRect changeRect(const QRect &rect, KisDefaultBoundsBaseSP defaultBounds) override; 0100 0101 void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override; 0102 0103 private: 0104 qint32 m_xRadius; 0105 qint32 m_yRadius; 0106 }; 0107 0108 class KRITAIMAGE_EXPORT KisShrinkSelectionFilter : public KisSelectionFilter 0109 { 0110 public: 0111 KisShrinkSelectionFilter(qint32 xRadius, qint32 yRadius, bool edgeLock); 0112 0113 KUndo2MagicString name() override; 0114 0115 QRect changeRect(const QRect &rect, KisDefaultBoundsBaseSP defaultBounds) override; 0116 0117 void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override; 0118 0119 private: 0120 qint32 m_xRadius; 0121 qint32 m_yRadius; 0122 qint32 m_edgeLock; 0123 }; 0124 0125 class KRITAIMAGE_EXPORT KisSmoothSelectionFilter : public KisSelectionFilter 0126 { 0127 public: 0128 KUndo2MagicString name() override; 0129 0130 QRect changeRect(const QRect &rect, KisDefaultBoundsBaseSP defaultBounds) override; 0131 0132 void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override; 0133 }; 0134 0135 class KRITAIMAGE_EXPORT KisInvertSelectionFilter : public KisSelectionFilter 0136 { 0137 public: 0138 KUndo2MagicString name() override; 0139 0140 QRect changeRect(const QRect &rect, KisDefaultBoundsBaseSP defaultBounds) override; 0141 0142 void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override; 0143 }; 0144 0145 /** 0146 * @brief AntiAlias filter for selections inspired by FXAA 0147 */ 0148 class KRITAIMAGE_EXPORT KisAntiAliasSelectionFilter : public KisSelectionFilter 0149 { 0150 public: 0151 KUndo2MagicString name() override; 0152 void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override; 0153 0154 private: 0155 /** 0156 * @brief Edges with gradient less than this value will not be antiAliasied 0157 */ 0158 static constexpr qint32 edgeThreshold {4}; 0159 /** 0160 * @brief Number of steps to jump when searching for one of the ends of the 0161 * antiAliased span. 0162 */ 0163 static constexpr qint32 numSteps {30}; 0164 /** 0165 * @brief This array of @ref numSteps size holds the number of pixels to 0166 * jump in each step. 0167 */ 0168 static constexpr qint32 offsets[numSteps] { 0169 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0170 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0171 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 0172 }; 0173 /** 0174 * @brief The size of the border added internally to the left and right of 0175 * the scanline buffer so that we can read outside the selection rect 0176 * without problems. It must be equal to the largest value in @ref offsets. 0177 */ 0178 static constexpr qint32 horizontalBorderSize {2}; 0179 /** 0180 * @brief The size of the border added internally to the top and bottom of 0181 * the scanline buffer so that we can read outside the selection rect 0182 * without problems. It must be equal to the sum of all values in @ref offsets. 0183 */ 0184 static constexpr qint32 verticalBorderSize {40}; 0185 /** 0186 * @brief Number of scanlines in the internal buffer. 0187 */ 0188 static constexpr qint32 numberOfScanlines {2 * verticalBorderSize + 1}; 0189 /** 0190 * @brief Offset of the current scanline in the buffer (The middle scanline). 0191 */ 0192 static constexpr qint32 currentScanlineIndex {verticalBorderSize}; 0193 /** 0194 * @brief Get a interpolation value to linearly interpolate the current 0195 * pixel with its edge neighbor. 0196 * @return true if we must apply the interpolation. false otherwise. 0197 */ 0198 bool getInterpolationValue(qint32 negativeSpanEndDistance, qint32 positiveSpanEndDistance, 0199 qint32 negativePixelDiff, qint32 positivePixelDiff, qint32 currentPixelDiff, 0200 bool negativeSpanExtremeValid, bool positiveSpanExtremeValid, 0201 qint32 *interpolationValue) const; 0202 /** 0203 * @brief Get the extreme point of the span for the current pixel in the 0204 * given direction 0205 */ 0206 void findSpanExtreme(quint8 **scanlines, qint32 x, qint32 pixelOffset, 0207 qint32 rowMultiplier, qint32 colMultiplier, qint32 direction, 0208 qint32 pixelAvg, qint32 scaledGradient, qint32 currentPixelDiff, 0209 qint32 *spanEndDistance, qint32 *pixelDiff, bool *spanExtremeValidType) const; 0210 /** 0211 * @brief Get the extreme points of the span for the current pixel 0212 */ 0213 void findSpanExtremes(quint8 **scanlines, qint32 x, qint32 pixelOffset, 0214 qint32 rowMultiplier, qint32 colMultiplier, 0215 qint32 pixelAvg, qint32 scaledGradient, qint32 currentPixelDiff, 0216 qint32 *negativeSpanEndDistance, qint32 *positiveSpanEndDistance, 0217 qint32 *negativePixelDiff, qint32 *positivePixelDiff, 0218 bool *negativeSpanExtremeValid, bool *positiveSpanExtremeValid) const; 0219 }; 0220 0221 #endif // KIS_SELECTION_FILTERS_H