LCOV - code coverage report
Current view: top level - core/effects - qgsimageoperation.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 97 0.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                            qgsimageoperation.h
       3                 :            :                            --------------------
       4                 :            :     begin                : January 2015
       5                 :            :     copyright            : (C) 2015 by Nyall Dawson
       6                 :            :     email                : nyall.dawson@gmail.com
       7                 :            :  ***************************************************************************/
       8                 :            : 
       9                 :            : /***************************************************************************
      10                 :            :  *                                                                         *
      11                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      12                 :            :  *   it under the terms of the GNU General Public License as published by  *
      13                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      14                 :            :  *   (at your option) any later version.                                   *
      15                 :            :  *                                                                         *
      16                 :            :  ***************************************************************************/
      17                 :            : 
      18                 :            : #ifndef QGSIMAGEOPERATION_H
      19                 :            : #define QGSIMAGEOPERATION_H
      20                 :            : 
      21                 :            : #include <QImage>
      22                 :            : #include "qgis_sip.h"
      23                 :            : #include <QColor>
      24                 :            : 
      25                 :            : #include "qgis_core.h"
      26                 :            : #include <cmath>
      27                 :            : 
      28                 :            : class QgsColorRamp;
      29                 :            : 
      30                 :            : /**
      31                 :            :  * \ingroup core
      32                 :            :  * \class QgsImageOperation
      33                 :            :  * \brief Contains operations and filters which apply to QImages
      34                 :            :  *
      35                 :            :  * A set of optimised pixel manipulation operations and filters which can be applied
      36                 :            :  * to QImages. All operations only apply to ARGB32 format images, and it is left up
      37                 :            :  * to the calling procedure to ensure that any passed images are of the correct
      38                 :            :  * format.
      39                 :            :  *
      40                 :            :  * Operations are written to either modify an image in place or return a new image, depending
      41                 :            :  * on which is faster for the particular operation.
      42                 :            :  *
      43                 :            :  * \since QGIS 2.7
      44                 :            :  */
      45                 :            : class CORE_EXPORT QgsImageOperation
      46                 :            : {
      47                 :            : 
      48                 :            :   public:
      49                 :            : 
      50                 :            :     /**
      51                 :            :      * Modes for converting a QImage to grayscale
      52                 :            :      */
      53                 :            :     enum GrayscaleMode
      54                 :            :     {
      55                 :            :       GrayscaleLightness, //!< Keep the lightness of the color, drops the saturation
      56                 :            :       GrayscaleLuminosity, //!< Grayscale by perceptual luminosity (weighted sum of color RGB components)
      57                 :            :       GrayscaleAverage, //!< Grayscale by taking average of color RGB components
      58                 :            :       GrayscaleOff //!< No change
      59                 :            :     };
      60                 :            : 
      61                 :            :     /**
      62                 :            :      * Flip operation types
      63                 :            :      */
      64                 :            :     enum FlipType
      65                 :            :     {
      66                 :            :       FlipHorizontal, //!< Flip the image horizontally
      67                 :            :       FlipVertical //!< Flip the image vertically
      68                 :            :     };
      69                 :            : 
      70                 :            :     /**
      71                 :            :      * Convert a QImage to a grayscale image. Alpha channel is preserved.
      72                 :            :      * \param image QImage to convert
      73                 :            :      * \param mode mode to use during grayscale conversion
      74                 :            :      */
      75                 :            :     static void convertToGrayscale( QImage &image, GrayscaleMode mode = GrayscaleLuminosity );
      76                 :            : 
      77                 :            :     /**
      78                 :            :      * Alter the brightness or contrast of a QImage.
      79                 :            :      * \param image QImage to alter
      80                 :            :      * \param brightness brightness value, in the range -255 to 255. A brightness value of 0 indicates
      81                 :            :      * no change to brightness, a negative value will darken the image, and a positive value will brighten
      82                 :            :      * the image.
      83                 :            :      * \param contrast contrast value. Must be a positive or zero value. A value of 1.0 indicates no change
      84                 :            :      * to the contrast, a value of 0 represents an image with 0 contrast, and a value > 1.0 will increase the
      85                 :            :      * contrast of the image.
      86                 :            :      */
      87                 :            :     static void adjustBrightnessContrast( QImage &image, int brightness, double contrast );
      88                 :            : 
      89                 :            :     /**
      90                 :            :      * Alter the hue or saturation of a QImage.
      91                 :            :      * \param image QImage to alter
      92                 :            :      * \param saturation double between 0 and 2 inclusive, where 0 = desaturate and 1.0 = no change
      93                 :            :      * \param colorizeColor color to use for colorizing image. Set to an invalid QColor to disable
      94                 :            :      * colorization.
      95                 :            :      * \param colorizeStrength double between 0 and 1, where 0 = no colorization and 1.0 = full colorization
      96                 :            :      */
      97                 :            :     static void adjustHueSaturation( QImage &image, double saturation, const QColor &colorizeColor = QColor(),
      98                 :            :                                      double colorizeStrength = 1.0 );
      99                 :            : 
     100                 :            :     /**
     101                 :            :      * Multiplies opacity of image pixel values by a factor.
     102                 :            :      * \param image QImage to alter
     103                 :            :      * \param factor factor to multiple pixel's opacity by
     104                 :            :      */
     105                 :            :     static void multiplyOpacity( QImage &image, double factor );
     106                 :            : 
     107                 :            :     /**
     108                 :            :      * Overlays a color onto an image. This operation retains the alpha channel of the
     109                 :            :      * original image, but replaces all image pixel colors with the specified color.
     110                 :            :      * \param image QImage to alter
     111                 :            :      * \param color color to overlay (any alpha component of the color is ignored)
     112                 :            :      */
     113                 :            :     static void overlayColor( QImage &image, const QColor &color );
     114                 :            : 
     115                 :            :     //! Struct for storing properties of a distance transform operation
     116                 :          0 :     struct DistanceTransformProperties
     117                 :            :     {
     118                 :            : 
     119                 :            :       /**
     120                 :            :        * Set to TRUE to perform the distance transform on transparent pixels
     121                 :            :        * in the source image, set to FALSE to perform the distance transform
     122                 :            :        * on opaque pixels
     123                 :            :        */
     124                 :          0 :       bool shadeExterior = true;
     125                 :            : 
     126                 :            :       /**
     127                 :            :        * Set to TRUE to automatically calculate the maximum distance in the
     128                 :            :        * transform to use as the spread value
     129                 :            :        */
     130                 :          0 :       bool useMaxDistance = true;
     131                 :            : 
     132                 :            :       /**
     133                 :            :        * Maximum distance (in pixels) for the distance transform shading to
     134                 :            :        * spread
     135                 :            :        */
     136                 :          0 :       double spread = 10.0;
     137                 :            : 
     138                 :            :       /**
     139                 :            :        * Color ramp to use for shading the distance transform
     140                 :            :        */
     141                 :          0 :       QgsColorRamp *ramp = nullptr;
     142                 :            :     };
     143                 :            : 
     144                 :            :     /**
     145                 :            :      * Performs a distance transform on the source image and shades the result
     146                 :            :      * using a color ramp.
     147                 :            :      * \param image QImage to alter
     148                 :            :      * \param properties DistanceTransformProperties object with parameters
     149                 :            :      * for the distance transform operation
     150                 :            :      */
     151                 :            :     static void distanceTransform( QImage &image, const QgsImageOperation::DistanceTransformProperties &properties );
     152                 :            : 
     153                 :            :     /**
     154                 :            :      * Performs a stack blur on an image. Stack blur represents a good balance between
     155                 :            :      * speed and blur quality.
     156                 :            :      * \param image QImage to blur
     157                 :            :      * \param radius blur radius in pixels, maximum value of 16
     158                 :            :      * \param alphaOnly set to TRUE to blur only the alpha component of the image
     159                 :            :      * \note for fastest operation, ensure the source image is ARGB32_Premultiplied if
     160                 :            :      * alphaOnly is set to FALSE, or ARGB32 if alphaOnly is TRUE
     161                 :            :      */
     162                 :            :     static void stackBlur( QImage &image, int radius, bool alphaOnly = false );
     163                 :            : 
     164                 :            :     /**
     165                 :            :      * Performs a gaussian blur on an image. Gaussian blur is slower but results in a high
     166                 :            :      * quality blur.
     167                 :            :      * \param image QImage to blur
     168                 :            :      * \param radius blur radius in pixels
     169                 :            :      * \returns blurred image
     170                 :            :      * \note for fastest operation, ensure the source image is ARGB32_Premultiplied
     171                 :            :      */
     172                 :            :     static QImage *gaussianBlur( QImage &image, int radius ) SIP_FACTORY;
     173                 :            : 
     174                 :            :     /**
     175                 :            :      * Flips an image horizontally or vertically
     176                 :            :      * \param image QImage to flip
     177                 :            :      * \param type type of flip to perform (horizontal or vertical)
     178                 :            :      */
     179                 :            :     static void flipImage( QImage &image, FlipType type );
     180                 :            : 
     181                 :            :     /**
     182                 :            :      * Calculates the non-transparent region of an image.
     183                 :            :      * \param image source image
     184                 :            :      * \param minSize minimum size for returned region, if desired. If the
     185                 :            :      * non-transparent region of the image is smaller than this minimum size,
     186                 :            :      * it will be centered in the returned rectangle.
     187                 :            :      * \param center return rectangle will be centered on the center of the original image if set to TRUE
     188                 :            :      * \see cropTransparent
     189                 :            :      * \since QGIS 2.9
     190                 :            :      */
     191                 :            :     static QRect nonTransparentImageRect( const QImage &image, QSize minSize = QSize(), bool center = false );
     192                 :            : 
     193                 :            :     /**
     194                 :            :      * Crop any transparent border from around an image.
     195                 :            :      * \param image source image
     196                 :            :      * \param minSize minimum size for cropped image, if desired. If the
     197                 :            :      * cropped image is smaller than the minimum size, it will be centered
     198                 :            :      * in the returned image.
     199                 :            :      * \param center cropped image will be centered on the center of the original image if set to TRUE
     200                 :            :      * \since QGIS 2.9
     201                 :            :      */
     202                 :            :     static QImage cropTransparent( const QImage &image, QSize minSize = QSize(), bool center = false );
     203                 :            : 
     204                 :            :   private:
     205                 :            : 
     206                 :            :     //for blocked operations
     207                 :            :     enum LineOperationDirection
     208                 :            :     {
     209                 :            :       ByRow,
     210                 :            :       ByColumn
     211                 :            :     };
     212                 :            :     template <class BlockOperation> static void runBlockOperationInThreads( QImage &image, BlockOperation &operation, LineOperationDirection direction );
     213                 :          0 :     struct ImageBlock
     214                 :            :     {
     215                 :            :       unsigned int beginLine;
     216                 :            :       unsigned int endLine;
     217                 :            :       unsigned int lineLength;
     218                 :          0 :       QImage *image = nullptr;
     219                 :            :     };
     220                 :            : 
     221                 :            :     //for rect operations
     222                 :            :     template <typename RectOperation> static void runRectOperation( QImage &image, RectOperation &operation );
     223                 :            :     template <class RectOperation> static void runRectOperationOnWholeImage( QImage &image, RectOperation &operation );
     224                 :            : 
     225                 :            :     //for per pixel operations
     226                 :            :     template <class PixelOperation> static void runPixelOperation( QImage &image, PixelOperation &operation );
     227                 :            :     template <class PixelOperation> static void runPixelOperationOnWholeImage( QImage &image, PixelOperation &operation );
     228                 :            :     template <class PixelOperation>
     229                 :            :     struct ProcessBlockUsingPixelOperation
     230                 :            :     {
     231                 :          0 :       explicit ProcessBlockUsingPixelOperation( PixelOperation &operation )
     232                 :          0 :         : mOperation( operation ) { }
     233                 :            : 
     234                 :            :       typedef void result_type;
     235                 :            : 
     236                 :          0 :       void operator()( ImageBlock &block )
     237                 :            :       {
     238                 :          0 :         for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
     239                 :            :         {
     240                 :          0 :           QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
     241                 :          0 :           for ( unsigned int x = 0; x < block.lineLength; ++x )
     242                 :            :           {
     243                 :          0 :             mOperation( ref[x], x, y );
     244                 :          0 :           }
     245                 :          0 :         }
     246                 :          0 :       }
     247                 :            : 
     248                 :            :       PixelOperation &mOperation;
     249                 :            :     };
     250                 :            : 
     251                 :            :     //for linear operations
     252                 :            :     template <typename LineOperation> static void runLineOperation( QImage &image, LineOperation &operation );
     253                 :            :     template <class LineOperation> static void runLineOperationOnWholeImage( QImage &image, LineOperation &operation );
     254                 :            :     template <class LineOperation>
     255                 :            :     struct ProcessBlockUsingLineOperation
     256                 :            :     {
     257                 :          0 :       explicit ProcessBlockUsingLineOperation( LineOperation &operation )
     258                 :          0 :         : mOperation( operation ) { }
     259                 :            : 
     260                 :            :       typedef void result_type;
     261                 :            : 
     262                 :          0 :       void operator()( ImageBlock &block )
     263                 :            :       {
     264                 :            :         //do something with whole lines
     265                 :          0 :         int bpl = block.image->bytesPerLine();
     266                 :          0 :         if ( mOperation.direction() == ByRow )
     267                 :            :         {
     268                 :          0 :           for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
     269                 :            :           {
     270                 :          0 :             QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
     271                 :          0 :             mOperation( ref, block.lineLength, bpl );
     272                 :          0 :           }
     273                 :          0 :         }
     274                 :            :         else
     275                 :            :         {
     276                 :            :           //by column
     277                 :          0 :           unsigned char *ref = block.image->scanLine( 0 ) + 4 * block.beginLine;
     278                 :          0 :           for ( unsigned int x = block.beginLine; x < block.endLine; ++x, ref += 4 )
     279                 :            :           {
     280                 :          0 :             mOperation( reinterpret_cast< QRgb * >( ref ), block.lineLength, bpl );
     281                 :          0 :           }
     282                 :            :         }
     283                 :          0 :       }
     284                 :            : 
     285                 :            :       LineOperation &mOperation;
     286                 :            :     };
     287                 :            : 
     288                 :            : 
     289                 :            :     //individual operation implementations
     290                 :            : 
     291                 :            :     class GrayscalePixelOperation
     292                 :            :     {
     293                 :            :       public:
     294                 :          0 :         explicit GrayscalePixelOperation( const GrayscaleMode mode )
     295                 :          0 :           : mMode( mode )
     296                 :          0 :         {  }
     297                 :            : 
     298                 :            :         void operator()( QRgb &rgb, int x, int y );
     299                 :            : 
     300                 :            :       private:
     301                 :            :         GrayscaleMode mMode;
     302                 :            :     };
     303                 :            :     static void grayscaleLightnessOp( QRgb &rgb );
     304                 :            :     static void grayscaleLuminosityOp( QRgb &rgb );
     305                 :            :     static void grayscaleAverageOp( QRgb &rgb );
     306                 :            : 
     307                 :            : 
     308                 :            :     class BrightnessContrastPixelOperation
     309                 :            :     {
     310                 :            :       public:
     311                 :          0 :         BrightnessContrastPixelOperation( const int brightness, const double contrast )
     312                 :          0 :           : mBrightness( brightness )
     313                 :          0 :           , mContrast( contrast )
     314                 :          0 :         {  }
     315                 :            : 
     316                 :            :         void operator()( QRgb &rgb, int x, int y );
     317                 :            : 
     318                 :            :       private:
     319                 :            :         int mBrightness;
     320                 :            :         double mContrast;
     321                 :            :     };
     322                 :            : 
     323                 :            : 
     324                 :            :     class HueSaturationPixelOperation
     325                 :            :     {
     326                 :            :       public:
     327                 :          0 :         HueSaturationPixelOperation( const double saturation, const bool colorize,
     328                 :            :                                      const int colorizeHue, const int colorizeSaturation,
     329                 :            :                                      const double colorizeStrength )
     330                 :          0 :           : mSaturation( saturation )
     331                 :          0 :           , mColorize( colorize )
     332                 :          0 :           , mColorizeHue( colorizeHue )
     333                 :          0 :           , mColorizeSaturation( colorizeSaturation )
     334                 :          0 :           , mColorizeStrength( colorizeStrength )
     335                 :          0 :         {  }
     336                 :            : 
     337                 :            :         void operator()( QRgb &rgb, int x, int y );
     338                 :            : 
     339                 :            :       private:
     340                 :            :         double mSaturation; // [0, 2], 1 = no change
     341                 :            :         bool mColorize;
     342                 :            :         int mColorizeHue;
     343                 :            :         int mColorizeSaturation;
     344                 :            :         double mColorizeStrength; // [0,1]
     345                 :            :     };
     346                 :            :     static int adjustColorComponent( int colorComponent, int brightness, double contrastFactor );
     347                 :            : 
     348                 :            : 
     349                 :            :     class MultiplyOpacityPixelOperation
     350                 :            :     {
     351                 :            :       public:
     352                 :          0 :         explicit MultiplyOpacityPixelOperation( const double factor )
     353                 :          0 :           : mFactor( factor )
     354                 :          0 :         { }
     355                 :            : 
     356                 :            :         void operator()( QRgb &rgb, int x, int y );
     357                 :            : 
     358                 :            :       private:
     359                 :            :         double mFactor;
     360                 :            :     };
     361                 :            : 
     362                 :            :     class ConvertToArrayPixelOperation
     363                 :            :     {
     364                 :            :       public:
     365                 :          0 :         ConvertToArrayPixelOperation( const int width, double *array, const bool exterior = true )
     366                 :          0 :           : mWidth( width )
     367                 :          0 :           , mArray( array )
     368                 :          0 :           , mExterior( exterior )
     369                 :            :         {
     370                 :          0 :         }
     371                 :            : 
     372                 :            :         void operator()( QRgb &rgb, int x, int y );
     373                 :            : 
     374                 :            :       private:
     375                 :            :         int mWidth;
     376                 :            :         double *mArray = nullptr;
     377                 :            :         bool mExterior;
     378                 :            :     };
     379                 :            : 
     380                 :            :     class ShadeFromArrayOperation
     381                 :            :     {
     382                 :            :       public:
     383                 :          0 :         ShadeFromArrayOperation( const int width, double *array, const double spread,
     384                 :            :                                  const DistanceTransformProperties &properties )
     385                 :          0 :           : mWidth( width )
     386                 :          0 :           , mArray( array )
     387                 :          0 :           , mSpread( spread )
     388                 :          0 :           , mProperties( properties )
     389                 :            :         {
     390                 :          0 :           mSpreadSquared = std::pow( mSpread, 2.0 );
     391                 :          0 :         }
     392                 :            : 
     393                 :            :         void operator()( QRgb &rgb, int x, int y );
     394                 :            : 
     395                 :            :       private:
     396                 :            :         int mWidth;
     397                 :            :         double *mArray = nullptr;
     398                 :            :         double mSpread;
     399                 :            :         double mSpreadSquared;
     400                 :            :         const DistanceTransformProperties &mProperties;
     401                 :            :     };
     402                 :            :     static void distanceTransform2d( double *im, int width, int height );
     403                 :            :     static void distanceTransform1d( double *f, int n, int *v, double *z, double *d );
     404                 :            :     static double maxValueInDistanceTransformArray( const double *array, unsigned int size );
     405                 :            : 
     406                 :            : 
     407                 :            :     class StackBlurLineOperation
     408                 :            :     {
     409                 :            :       public:
     410                 :          0 :         StackBlurLineOperation( int alpha, LineOperationDirection direction, bool forwardDirection, int i1, int i2 )
     411                 :          0 :           : mAlpha( alpha )
     412                 :          0 :           , mDirection( direction )
     413                 :          0 :           , mForwardDirection( forwardDirection )
     414                 :          0 :           , mi1( i1 )
     415                 :          0 :           , mi2( i2 )
     416                 :          0 :         { }
     417                 :            : 
     418                 :            :         typedef void result_type;
     419                 :            : 
     420                 :          0 :         LineOperationDirection direction() { return mDirection; }
     421                 :            : 
     422                 :          0 :         void operator()( QRgb *startRef, int lineLength, int bytesPerLine )
     423                 :            :         {
     424                 :          0 :           unsigned char *p = reinterpret_cast< unsigned char * >( startRef );
     425                 :            :           int rgba[4];
     426                 :          0 :           int increment = ( mDirection == QgsImageOperation::ByRow ) ? 4 : bytesPerLine;
     427                 :          0 :           if ( !mForwardDirection )
     428                 :            :           {
     429                 :          0 :             p += ( lineLength - 1 ) * increment;
     430                 :          0 :             increment = -increment;
     431                 :          0 :           }
     432                 :            : 
     433                 :          0 :           for ( int i = mi1; i <= mi2; ++i )
     434                 :            :           {
     435                 :          0 :             rgba[i] = p[i] << 4;
     436                 :          0 :           }
     437                 :            : 
     438                 :          0 :           p += increment;
     439                 :          0 :           for ( int j = 1; j < lineLength; ++j, p += increment )
     440                 :            :           {
     441                 :          0 :             for ( int i = mi1; i <= mi2; ++i )
     442                 :            :             {
     443                 :          0 :               p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * mAlpha / 16 ) >> 4;
     444                 :          0 :             }
     445                 :          0 :           }
     446                 :          0 :         }
     447                 :            : 
     448                 :            :       private:
     449                 :            :         int mAlpha;
     450                 :            :         LineOperationDirection mDirection;
     451                 :            :         bool mForwardDirection;
     452                 :            :         int mi1;
     453                 :            :         int mi2;
     454                 :            :     };
     455                 :            : 
     456                 :            :     static double *createGaussianKernel( int radius );
     457                 :            : 
     458                 :            :     class GaussianBlurOperation
     459                 :            :     {
     460                 :            :       public:
     461                 :          0 :         GaussianBlurOperation( int radius, LineOperationDirection direction, QImage *destImage, double *kernel )
     462                 :          0 :           : mRadius( radius )
     463                 :          0 :           , mDirection( direction )
     464                 :          0 :           , mDestImage( destImage )
     465                 :          0 :           , mDestImageBpl( destImage->bytesPerLine() )
     466                 :          0 :           , mKernel( kernel )
     467                 :          0 :         {}
     468                 :            : 
     469                 :            :         typedef void result_type;
     470                 :            : 
     471                 :            :         void operator()( ImageBlock &block );
     472                 :            : 
     473                 :            :       private:
     474                 :            :         int mRadius;
     475                 :            :         LineOperationDirection mDirection;
     476                 :            :         QImage *mDestImage = nullptr;
     477                 :            :         int mDestImageBpl;
     478                 :            :         double *mKernel = nullptr;
     479                 :            : 
     480                 :            :         inline QRgb gaussianBlurVertical( int posy, unsigned char *sourceFirstLine, int sourceBpl, int height );
     481                 :            :         inline QRgb gaussianBlurHorizontal( int posx, unsigned char *sourceFirstLine, int width );
     482                 :            :     };
     483                 :            : 
     484                 :            :     //flip
     485                 :            : 
     486                 :            : 
     487                 :            :     class FlipLineOperation
     488                 :            :     {
     489                 :            :       public:
     490                 :          0 :         explicit FlipLineOperation( LineOperationDirection direction )
     491                 :          0 :           : mDirection( direction )
     492                 :          0 :         { }
     493                 :            : 
     494                 :            :         typedef void result_type;
     495                 :            : 
     496                 :          0 :         LineOperationDirection direction() { return mDirection; }
     497                 :            : 
     498                 :            :         void operator()( QRgb *startRef, int lineLength, int bytesPerLine );
     499                 :            : 
     500                 :            :       private:
     501                 :            :         LineOperationDirection mDirection;
     502                 :            :     };
     503                 :            : 
     504                 :            : 
     505                 :            : };
     506                 :            : 
     507                 :            : #endif // QGSIMAGEOPERATION_H
     508                 :            : 

Generated by: LCOV version 1.14