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

0001 /*
0002  *  SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #ifndef KIS_CONVOLUTION_PAINTER_H_
0007 #define KIS_CONVOLUTION_PAINTER_H_
0008 
0009 #include "kis_types.h"
0010 #include "kis_painter.h"
0011 #include "kis_image.h"
0012 #include "kritaimage_export.h"
0013 
0014 template<class factory> class KisConvolutionWorker;
0015 
0016 
0017 enum KisConvolutionBorderOp {
0018     BORDER_IGNORE = 0, // read the pixels outside of the application rect
0019     BORDER_REPEAT = 1  // Use the border for the missing pixels
0020 };
0021 
0022 /**
0023  * @brief The KisConvolutionPainter class applies a convolution kernel to a paint device.
0024  *
0025  *
0026  * Note: https://bugs.kde.org/show_bug.cgi?id=220310 shows that there's something here
0027  * that we need to fix...
0028  */
0029 class KRITAIMAGE_EXPORT KisConvolutionPainter : public KisPainter
0030 {
0031 
0032 public:
0033 
0034     KisConvolutionPainter();
0035     KisConvolutionPainter(KisPaintDeviceSP device);
0036     KisConvolutionPainter(KisPaintDeviceSP device, KisSelectionSP selection);
0037 
0038     enum EnginePreference {
0039         NONE,
0040         SPATIAL,
0041         FFTW
0042     };
0043 
0044 
0045     KisConvolutionPainter(KisPaintDeviceSP device, EnginePreference enginePreference);
0046 
0047     void setEnginePreference(EnginePreference value);
0048 
0049     /**
0050      * Convolve all channels in src using the specified kernel; there is only one kernel for all
0051      * channels possible.
0052      *
0053      * WARNING: The painter will read **more** pixels than you pass in \p areaSize.
0054      *          The actual processing area will be:
0055      *          QRect(x - kernel.width() / 2,
0056      *                y - kernel.height() / 2,
0057      *                w + 2 * (kernel.width() / 2),
0058      *                h + 2 * (kernel.height() / 2))
0059      *
0060      * The border op decides what to do with pixels too close to the edge of the rect as defined above.
0061      *
0062      * The channels flag determines which set out of color channels, alpha channels.
0063      * channels we convolve.
0064      *
0065      * Note that we do not (currently) support different kernels for
0066      * different channels _or_ channel types.
0067      *
0068      * If you want to convolve a subset of the channels in a pixel,
0069      * set those channels with KisPainter::setChannelFlags();
0070      */
0071     void applyMatrix(const KisConvolutionKernelSP kernel, const KisPaintDeviceSP src, QPoint srcPos, QPoint dstPos, QSize areaSize,
0072                      KisConvolutionBorderOp borderOp = BORDER_REPEAT);
0073 
0074     /**
0075      * The caller should ask if the painter needs an explicit transaction iff
0076      * the source and destination devices coincide. Otherwise, the transaction is
0077      * just not needed.
0078      */
0079     bool needsTransaction(const KisConvolutionKernelSP kernel) const;
0080 
0081     static bool supportsFFTW();
0082 
0083 protected:
0084     friend class KisConvolutionPainterTest;
0085 
0086 
0087 
0088 private:
0089     template<class factory>
0090         KisConvolutionWorker<factory>* createWorker(const KisConvolutionKernelSP kernel,
0091                                                     KisPainter *painter,
0092                                                     KoUpdater *progress);
0093 
0094      bool useFFTImplementation(const KisConvolutionKernelSP kernel) const;
0095 
0096 private:
0097     EnginePreference m_enginePreference;
0098 };
0099 #endif //KIS_CONVOLUTION_PAINTER_H_