QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsimageoperation.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsimageoperation.h
3  --------------------
4  begin : January 2015
5  copyright : (C) 2015 by Nyall Dawson
6  email : [email protected]
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.h"
23 #include <QColor>
24 
25 #include "qgis_core.h"
26 
27 class QgsColorRamp;
28 
44 class CORE_EXPORT QgsImageOperation
45 {
46 
47  public:
48 
53  {
57  GrayscaleOff
58  };
59 
63  enum FlipType
64  {
66  FlipVertical
67  };
68 
74  static void convertToGrayscale( QImage &image, GrayscaleMode mode = GrayscaleLuminosity );
75 
86  static void adjustBrightnessContrast( QImage &image, int brightness, double contrast );
87 
96  static void adjustHueSaturation( QImage &image, double saturation, const QColor &colorizeColor = QColor(),
97  double colorizeStrength = 1.0 );
98 
104  static void multiplyOpacity( QImage &image, double factor );
105 
112  static void overlayColor( QImage &image, const QColor &color );
113 
116  {
117 
123  bool shadeExterior = true;
124 
129  bool useMaxDistance = true;
130 
135  double spread = 10.0;
136 
140  QgsColorRamp *ramp = nullptr;
141  };
142 
150  static void distanceTransform( QImage &image, const QgsImageOperation::DistanceTransformProperties &properties );
151 
161  static void stackBlur( QImage &image, int radius, bool alphaOnly = false );
162 
171  static QImage *gaussianBlur( QImage &image, int radius ) SIP_FACTORY;
172 
178  static void flipImage( QImage &image, FlipType type );
179 
190  static QRect nonTransparentImageRect( const QImage &image, QSize minSize = QSize(), bool center = false );
191 
201  static QImage cropTransparent( const QImage &image, QSize minSize = QSize(), bool center = false );
202 
203  private:
204 
205  //for blocked operations
206  enum LineOperationDirection
207  {
208  ByRow,
209  ByColumn
210  };
211  template <class BlockOperation> static void runBlockOperationInThreads( QImage &image, BlockOperation &operation, LineOperationDirection direction );
212  struct ImageBlock
213  {
214  unsigned int beginLine;
215  unsigned int endLine;
216  unsigned int lineLength;
217  QImage *image = nullptr;
218  };
219 
220  //for rect operations
221  template <typename RectOperation> static void runRectOperation( QImage &image, RectOperation &operation );
222  template <class RectOperation> static void runRectOperationOnWholeImage( QImage &image, RectOperation &operation );
223 
224  //for per pixel operations
225  template <class PixelOperation> static void runPixelOperation( QImage &image, PixelOperation &operation );
226  template <class PixelOperation> static void runPixelOperationOnWholeImage( QImage &image, PixelOperation &operation );
227  template <class PixelOperation>
228  struct ProcessBlockUsingPixelOperation
229  {
230  explicit ProcessBlockUsingPixelOperation( PixelOperation &operation )
231  : mOperation( operation ) { }
232 
233  typedef void result_type;
234 
235  void operator()( ImageBlock &block )
236  {
237  for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
238  {
239  QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
240  for ( unsigned int x = 0; x < block.lineLength; ++x )
241  {
242  mOperation( ref[x], x, y );
243  }
244  }
245  }
246 
247  PixelOperation &mOperation;
248  };
249 
250  //for linear operations
251  template <typename LineOperation> static void runLineOperation( QImage &image, LineOperation &operation );
252  template <class LineOperation> static void runLineOperationOnWholeImage( QImage &image, LineOperation &operation );
253  template <class LineOperation>
254  struct ProcessBlockUsingLineOperation
255  {
256  explicit ProcessBlockUsingLineOperation( LineOperation &operation )
257  : mOperation( operation ) { }
258 
259  typedef void result_type;
260 
261  void operator()( ImageBlock &block )
262  {
263  //do something with whole lines
264  int bpl = block.image->bytesPerLine();
265  if ( mOperation.direction() == ByRow )
266  {
267  for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
268  {
269  QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
270  mOperation( ref, block.lineLength, bpl );
271  }
272  }
273  else
274  {
275  //by column
276  unsigned char *ref = block.image->scanLine( 0 ) + 4 * block.beginLine;
277  for ( unsigned int x = block.beginLine; x < block.endLine; ++x, ref += 4 )
278  {
279  mOperation( reinterpret_cast< QRgb * >( ref ), block.lineLength, bpl );
280  }
281  }
282  }
283 
284  LineOperation &mOperation;
285  };
286 
287 
288  //individual operation implementations
289 
290  class GrayscalePixelOperation
291  {
292  public:
293  explicit GrayscalePixelOperation( const GrayscaleMode mode )
294  : mMode( mode )
295  { }
296 
297  void operator()( QRgb &rgb, int x, int y );
298 
299  private:
300  GrayscaleMode mMode;
301  };
302  static void grayscaleLightnessOp( QRgb &rgb );
303  static void grayscaleLuminosityOp( QRgb &rgb );
304  static void grayscaleAverageOp( QRgb &rgb );
305 
306 
307  class BrightnessContrastPixelOperation
308  {
309  public:
310  BrightnessContrastPixelOperation( const int brightness, const double contrast )
311  : mBrightness( brightness )
312  , mContrast( contrast )
313  { }
314 
315  void operator()( QRgb &rgb, int x, int y );
316 
317  private:
318  int mBrightness;
319  double mContrast;
320  };
321 
322 
323  class HueSaturationPixelOperation
324  {
325  public:
326  HueSaturationPixelOperation( const double saturation, const bool colorize,
327  const int colorizeHue, const int colorizeSaturation,
328  const double colorizeStrength )
329  : mSaturation( saturation )
330  , mColorize( colorize )
331  , mColorizeHue( colorizeHue )
332  , mColorizeSaturation( colorizeSaturation )
333  , mColorizeStrength( colorizeStrength )
334  { }
335 
336  void operator()( QRgb &rgb, int x, int y );
337 
338  private:
339  double mSaturation; // [0, 2], 1 = no change
340  bool mColorize;
341  int mColorizeHue;
342  int mColorizeSaturation;
343  double mColorizeStrength; // [0,1]
344  };
345  static int adjustColorComponent( int colorComponent, int brightness, double contrastFactor );
346 
347 
348  class MultiplyOpacityPixelOperation
349  {
350  public:
351  explicit MultiplyOpacityPixelOperation( const double factor )
352  : mFactor( factor )
353  { }
354 
355  void operator()( QRgb &rgb, int x, int y );
356 
357  private:
358  double mFactor;
359  };
360 
361  class ConvertToArrayPixelOperation
362  {
363  public:
364  ConvertToArrayPixelOperation( const int width, double *array, const bool exterior = true )
365  : mWidth( width )
366  , mArray( array )
367  , mExterior( exterior )
368  {
369  }
370 
371  void operator()( QRgb &rgb, int x, int y );
372 
373  private:
374  int mWidth;
375  double *mArray = nullptr;
376  bool mExterior;
377  };
378 
379  class ShadeFromArrayOperation
380  {
381  public:
382  ShadeFromArrayOperation( const int width, double *array, const double spread,
383  const DistanceTransformProperties &properties )
384  : mWidth( width )
385  , mArray( array )
386  , mSpread( spread )
387  , mProperties( properties )
388  {
389  mSpreadSquared = std::pow( mSpread, 2.0 );
390  }
391 
392  void operator()( QRgb &rgb, int x, int y );
393 
394  private:
395  int mWidth;
396  double *mArray = nullptr;
397  double mSpread;
398  double mSpreadSquared;
399  const DistanceTransformProperties &mProperties;
400  };
401  static void distanceTransform2d( double *im, int width, int height );
402  static void distanceTransform1d( double *f, int n, int *v, double *z, double *d );
403  static double maxValueInDistanceTransformArray( const double *array, unsigned int size );
404 
405 
406  class StackBlurLineOperation
407  {
408  public:
409  StackBlurLineOperation( int alpha, LineOperationDirection direction, bool forwardDirection, int i1, int i2 )
410  : mAlpha( alpha )
411  , mDirection( direction )
412  , mForwardDirection( forwardDirection )
413  , mi1( i1 )
414  , mi2( i2 )
415  { }
416 
417  typedef void result_type;
418 
419  LineOperationDirection direction() { return mDirection; }
420 
421  void operator()( QRgb *startRef, int lineLength, int bytesPerLine );
422 
423  private:
424  int mAlpha;
425  LineOperationDirection mDirection;
426  bool mForwardDirection;
427  int mi1;
428  int mi2;
429  };
430 
431  static double *createGaussianKernel( int radius );
432 
433  class GaussianBlurOperation
434  {
435  public:
436  GaussianBlurOperation( int radius, LineOperationDirection direction, QImage *destImage, double *kernel )
437  : mRadius( radius )
438  , mDirection( direction )
439  , mDestImage( destImage )
440  , mDestImageBpl( destImage->bytesPerLine() )
441  , mKernel( kernel )
442  {}
443 
444  typedef void result_type;
445 
446  void operator()( ImageBlock &block );
447 
448  private:
449  int mRadius;
450  LineOperationDirection mDirection;
451  QImage *mDestImage = nullptr;
452  int mDestImageBpl;
453  double *mKernel = nullptr;
454 
455  inline QRgb gaussianBlurVertical( int posy, unsigned char *sourceFirstLine, int sourceBpl, int height );
456  inline QRgb gaussianBlurHorizontal( int posx, unsigned char *sourceFirstLine, int width );
457  };
458 
459  //flip
460 
461 
462  class FlipLineOperation
463  {
464  public:
465  explicit FlipLineOperation( LineOperationDirection direction )
466  : mDirection( direction )
467  { }
468 
469  typedef void result_type;
470 
471  LineOperationDirection direction() { return mDirection; }
472 
473  void operator()( QRgb *startRef, int lineLength, int bytesPerLine );
474 
475  private:
476  LineOperationDirection mDirection;
477  };
478 
479 
480 };
481 
482 #endif // QGSIMAGEOPERATION_H
483 
Flip the image horizontally.
Contains operations and filters which apply to QImages.
Keep the lightness of the color, drops the saturation.
Abstract base class for color ramps.
Definition: qgscolorramp.h:31
FlipType
Flip operation types.
Grayscale by perceptual luminosity (weighted sum of color RGB components)
Grayscale by taking average of color RGB components.
#define SIP_FACTORY
Definition: qgis_sip.h:69
GrayscaleMode
Modes for converting a QImage to grayscale.
Struct for storing properties of a distance transform operation.