QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 <QColor>
23 #include <QtCore/qmath.h>
24 
26 
41 class CORE_EXPORT QgsImageOperation
42 {
43 
44  public:
45 
49  {
50  GrayscaleLightness, /*< keep the lightness of the color, drops the saturation */
51  GrayscaleLuminosity, /*< grayscale by perceptual luminosity (weighted sum of color RGB components) */
52  GrayscaleAverage /*< grayscale by taking average of color RGB components */
53  };
54 
57  enum FlipType
58  {
59  FlipHorizontal, /*< flip the image horizontally */
60  FlipVertical /*< flip the image vertically */
61  };
62 
67  static void convertToGrayscale( QImage &image, const GrayscaleMode mode = GrayscaleLuminosity );
68 
78  static void adjustBrightnessContrast( QImage &image, const int brightness, const double contrast );
79 
87  static void adjustHueSaturation( QImage &image, const double saturation, const QColor& colorizeColor = QColor(),
88  const double colorizeStrength = 1.0 );
89 
94  static void multiplyOpacity( QImage &image, const double factor );
95 
101  static void overlayColor( QImage &image, const QColor& color );
102 
105  {
107  : shadeExterior( true )
108  , useMaxDistance( true )
109  , spread( 10.0 )
110  , ramp( NULL )
111  { }
112 
125  double spread;
129  };
130 
137  static void distanceTransform( QImage &image, const DistanceTransformProperties& properties );
138 
147  static void stackBlur( QImage &image, const int radius, const bool alphaOnly = false );
148 
156  static QImage* gaussianBlur( QImage &image, const int radius );
157 
162  static void flipImage( QImage &image, FlipType type );
163 
164  private:
165 
166  //for blocked operations
167  enum LineOperationDirection
168  {
169  ByRow,
170  ByColumn
171  };
172  template <class BlockOperation> static void runBlockOperationInThreads( QImage &image, BlockOperation& operation, LineOperationDirection direction );
173  struct ImageBlock
174  {
175  unsigned int beginLine;
176  unsigned int endLine;
177  unsigned int lineLength;
178  QImage* image;
179  };
180 
181  //for rect operations
182  template <typename RectOperation> static void runRectOperation( QImage &image, RectOperation& operation );
183  template <class RectOperation> static void runRectOperationOnWholeImage( QImage &image, RectOperation& operation );
184 
185  //for per pixel operations
186  template <class PixelOperation> static void runPixelOperation( QImage &image, PixelOperation& operation );
187  template <class PixelOperation> static void runPixelOperationOnWholeImage( QImage &image, PixelOperation& operation );
188  template <class PixelOperation>
189  struct ProcessBlockUsingPixelOperation
190  {
191  ProcessBlockUsingPixelOperation( PixelOperation& operation )
192  : mOperation( operation ) { }
193 
194  typedef void result_type;
195 
196  void operator()( ImageBlock& block )
197  {
198  for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
199  {
200  QRgb* ref = ( QRgb* )block.image->scanLine( y );
201  for ( unsigned int x = 0; x < block.lineLength; ++x )
202  {
203  mOperation( ref[x], x, y );
204  }
205  }
206  }
207 
208  PixelOperation& mOperation;
209  };
210 
211  //for linear operations
212  template <typename LineOperation> static void runLineOperation( QImage &image, LineOperation& operation );
213  template <class LineOperation> static void runLineOperationOnWholeImage( QImage &image, LineOperation& operation );
214  template <class LineOperation>
215  struct ProcessBlockUsingLineOperation
216  {
217  ProcessBlockUsingLineOperation( LineOperation& operation )
218  : mOperation( operation ) { }
219 
220  typedef void result_type;
221 
222  void operator()( ImageBlock& block )
223  {
224  //do something with whole lines
225  int bpl = block.image->bytesPerLine();
226  if ( mOperation.direction() == ByRow )
227  {
228  for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
229  {
230  QRgb* ref = ( QRgb* )block.image->scanLine( y );
231  mOperation( ref, block.lineLength, bpl );
232  }
233  }
234  else
235  {
236  //by column
237  unsigned char* ref = block.image->scanLine( 0 ) + 4 * block.beginLine;
238  for ( unsigned int x = block.beginLine; x < block.endLine; ++x, ref += 4 )
239  {
240  mOperation(( QRgb* )ref, block.lineLength, bpl );
241  }
242  }
243  }
244 
245  LineOperation& mOperation;
246  };
247 
248 
249  //individual operation implementations
250 
251  class GrayscalePixelOperation
252  {
253  public:
254  GrayscalePixelOperation( const GrayscaleMode mode )
255  : mMode( mode )
256  { }
257 
258  void operator()( QRgb& rgb, const int x, const int y );
259 
260  private:
261  GrayscaleMode mMode;
262  };
263  static void grayscaleLightnessOp( QRgb& rgb );
264  static void grayscaleLuminosityOp( QRgb& rgb );
265  static void grayscaleAverageOp( QRgb& rgb );
266 
267 
268  class BrightnessContrastPixelOperation
269  {
270  public:
271  BrightnessContrastPixelOperation( const int brightness, const double contrast )
272  : mBrightness( brightness )
273  , mContrast( contrast )
274  { }
275 
276  void operator()( QRgb& rgb, const int x, const int y );
277 
278  private:
279  int mBrightness;
280  double mContrast;
281  };
282 
283 
284  class HueSaturationPixelOperation
285  {
286  public:
287  HueSaturationPixelOperation( const double saturation, const bool colorize,
288  const int colorizeHue, const int colorizeSaturation,
289  const double colorizeStrength )
290  : mSaturation( saturation )
291  , mColorize( colorize )
292  , mColorizeHue( colorizeHue )
293  , mColorizeSaturation( colorizeSaturation )
294  , mColorizeStrength( colorizeStrength )
295  { }
296 
297  void operator()( QRgb& rgb, const int x, const int y );
298 
299  private:
300  double mSaturation; // [0, 2], 1 = no change
301  bool mColorize;
302  int mColorizeHue;
303  int mColorizeSaturation;
304  double mColorizeStrength; // [0,1]
305  };
306  static int adjustColorComponent( int colorComponent, int brightness, double contrastFactor );
307 
308 
309  class MultiplyOpacityPixelOperation
310  {
311  public:
312  MultiplyOpacityPixelOperation( const double factor )
313  : mFactor( factor )
314  { }
315 
316  void operator()( QRgb& rgb, const int x, const int y );
317 
318  private:
319  double mFactor;
320  };
321 
322  class ConvertToArrayPixelOperation
323  {
324  public:
325  ConvertToArrayPixelOperation( const int width, double * array, const bool exterior = true, const int alphaThreshold = 255 )
326  : mWidth( width )
327  , mArray( array )
328  , mExterior( exterior )
329  , mAlphaThreshold( alphaThreshold )
330  {
331  }
332 
333  void operator()( QRgb& rgb, const int x, const int y );
334 
335  private:
336  int mWidth;
337  double * mArray;
338  bool mExterior;
339  int mAlphaThreshold;
340  };
341 
342  class ShadeFromArrayOperation
343  {
344  public:
345  ShadeFromArrayOperation( const int width, double* array, const double spread,
346  const DistanceTransformProperties& properties )
347  : mWidth( width )
348  , mArray( array )
349  , mSpread( spread )
350  , mProperties( properties )
351  {
352  mSpreadSquared = qPow( mSpread, 2.0 );
353  }
354 
355  void operator()( QRgb& rgb, const int x, const int y );
356 
357  private:
358  int mWidth;
359  double * mArray;
360  double mSpread;
361  double mSpreadSquared;
362  const DistanceTransformProperties& mProperties;
363  };
364  static void distanceTransform2d( double *im, int width, int height );
365  static void distanceTransform1d( double *f, int n, int *v, double *z, double *d );
366  static double maxValueInDistanceTransformArray( const double *array, const unsigned int size );
367 
368 
369  class StackBlurLineOperation
370  {
371  public:
372  StackBlurLineOperation( int alpha, LineOperationDirection direction, bool forwardDirection, int i1, int i2 )
373  : mAlpha( alpha )
374  , mDirection( direction )
375  , mForwardDirection( forwardDirection )
376  , mi1( i1 )
377  , mi2( i2 )
378  { }
379 
380  typedef void result_type;
381 
382  LineOperationDirection direction() { return mDirection; }
383 
384  void operator()( QRgb* startRef, const int lineLength, const int bytesPerLine );
385 
386  private:
387  int mAlpha;
388  LineOperationDirection mDirection;
389  bool mForwardDirection;
390  int mi1;
391  int mi2;
392  };
393 
394  static double *createGaussianKernel( const int radius );
395 
396  class GaussianBlurOperation
397  {
398  public:
399  GaussianBlurOperation( int radius, LineOperationDirection direction, QImage* destImage, double* kernel )
400  : mRadius( radius )
401  , mDirection( direction )
402  , mDestImage( destImage )
403  , mDestImageBpl( destImage->bytesPerLine() )
404  , mKernel( kernel )
405  {}
406 
407  typedef void result_type;
408 
409  void operator()( ImageBlock& block );
410 
411  private:
412  int mRadius;
413  LineOperationDirection mDirection;
414  QImage* mDestImage;
415  int mDestImageBpl;
416  double* mKernel;
417 
418  inline QRgb gaussianBlurVertical( const int posy, unsigned char *sourceFirstLine, const int sourceBpl, const int height );
419  inline QRgb gaussianBlurHorizontal( const int posx, unsigned char *sourceFirstLine, const int width );
420  };
421 
422  //flip
423 
424 
425  class FlipLineOperation
426  {
427  public:
428  FlipLineOperation( LineOperationDirection direction )
429  : mDirection( direction )
430  { }
431 
432  typedef void result_type;
433 
434  LineOperationDirection direction() { return mDirection; }
435 
436  void operator()( QRgb* startRef, const int lineLength, const int bytesPerLine );
437 
438  private:
439  LineOperationDirection mDirection;
440  };
441 
442 
443 };
444 
445 #endif // QGSIMAGEOPERATION_H
446