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

0001 /*
0002  *  SPDX-FileCopyrightText: 2017 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef KIS_EDGE_DETECTION_KERNEL_H
0008 #define KIS_EDGE_DETECTION_KERNEL_H
0009 
0010 #include "kritaimage_export.h"
0011 #include "kis_types.h"
0012 
0013 #include <Eigen/Core>
0014 #include <boost/optional.hpp>
0015 
0016 class QRect;
0017 
0018 class KRITAIMAGE_EXPORT KisEdgeDetectionKernel
0019 {
0020 public:
0021     KisEdgeDetectionKernel();
0022 
0023     enum FilterType {
0024         Simple, //A weird simple method used in our old sobel filter
0025         Prewit, //The simpler prewitt detection, which doesn't smooth.
0026         SobelVector //Sobel does smooth. The creation of bigger kernels is based on an approach regarding vectors.
0027     };
0028 
0029     enum FilterOutput {
0030         pythagorean,
0031         xGrowth,
0032         xFall,
0033         yGrowth,
0034         yFall,
0035         radian
0036     };
0037 
0038     /**
0039      * @brief createHorizontalMatrix
0040      * @param radius the radius. 1 makes a 3x3 kernel.
0041      * @param type One of the entries in the enum Filtertype
0042      * @param reverse which direction the gradient goes.
0043      * The horizontal gradient by default detects the rightmost edges.
0044      * Reversed it selects the leftmost edges.
0045      * @return
0046      */
0047 
0048     static Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic>
0049         createHorizontalMatrix(qreal radius, FilterType type, bool reverse = false);
0050     /**
0051      * @brief createVerticalMatrix
0052      * @param radius the radius. 1 makes a 3x3 kernel.
0053      * @param type One of the entries in the enum Filtertype
0054      * @param reverse which direction the gradient goes.
0055      * The vertical gradient by default detects the topmost edges.
0056      * Reversed it selects the bottommost edges.
0057      * @return
0058      */
0059     static Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic>
0060         createVerticalMatrix(qreal radius, FilterType type, bool reverse = false);
0061 
0062     static KisConvolutionKernelSP
0063         createHorizontalKernel(qreal radius, FilterType type, bool denormalize = true, bool reverse = false);
0064 
0065     static KisConvolutionKernelSP
0066         createVerticalKernel(qreal radius, FilterType type, bool denormalize = true, bool reverse = false);
0067 
0068     static int kernelSizeFromRadius(qreal radius);
0069     static qreal sigmaFromRadius(qreal radius);
0070 
0071     /**
0072      * @brief applyEdgeDetection
0073      * This applies the edge detection filter to the device.
0074      * @param device the device to apply to.
0075      * @param rect the affected rect.
0076      * @param xRadius the radius of the horizontal sampling, radius of 0 is effectively disabling it.
0077      * @param yRadius the radius of the vertical sampling, refius of 0 is effectively disabling it.
0078      * @param type the type can be prewitt, sobel or simple, each of which
0079      * have a different sampling for the eventual edge detection.
0080      * @param channelFlags the affected channels.
0081      * @param progressUpdater the progress updater if it exists.
0082      * @param output the output mode.
0083      * @param writeToAlpha whether or not to have the result applied to the transparency than the color channels,
0084      * this is useful for fringe effects.
0085      */
0086     static void applyEdgeDetection(KisPaintDeviceSP device,
0087                               const QRect& rect,
0088                               qreal xRadius, qreal yRadius,
0089                               FilterType type,
0090                               const QBitArray &channelFlags,
0091                               KoUpdater *progressUpdater,
0092                               FilterOutput output = pythagorean,
0093                               bool writeToAlpha = false);
0094     /**
0095      * @brief converToNormalMap
0096      * Convert a channel of the device to a normal map. The channel will be interpreted as a heightmap.
0097      * @param device the device
0098      * @param rect the rectangle to apply this to.
0099      * @param xRadius the xradius
0100      * @param yRadius the yradius
0101      * @param type the edge detection filter.
0102      * @param channelToConvert the channel to use as a grayscale.
0103      * @param channelOrder the order in which the xyz coordinates ought to be written to the pixels.
0104      * @param channelFlip whether to flip the channels
0105      * @param channelFlags the channel flags
0106      * @param progressUpdater
0107      */
0108     static void convertToNormalMap(KisPaintDeviceSP device,
0109                                   const QRect & rect,
0110                                   qreal xRadius,
0111                                   qreal yRadius,
0112                                   FilterType type,
0113                                   int channelToConvert,
0114                                   QVector<int> channelOrder,
0115                                   QVector<bool> channelFlip,
0116                                   const QBitArray &channelFlags,
0117                                   KoUpdater *progressUpdater,
0118                                   boost::optional<bool> useFftw = boost::none);
0119 };
0120 
0121 #endif // KIS_EDGE_DETECTION_KERNEL_H