QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
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 "qgsfeedback.h"
27#include <cmath>
28
29class QgsColorRamp;
30class QgsFeedback;
31
46class CORE_EXPORT QgsImageOperation
47{
48
49 public:
50
55 {
59 GrayscaleOff
60 };
61
66 {
68 FlipVertical
69 };
70
77 static void convertToGrayscale( QImage &image, GrayscaleMode mode = GrayscaleLuminosity, QgsFeedback *feedback = nullptr );
78
90 static void adjustBrightnessContrast( QImage &image, int brightness, double contrast, QgsFeedback *feedback = nullptr );
91
101 static void adjustHueSaturation( QImage &image, double saturation, const QColor &colorizeColor = QColor(),
102 double colorizeStrength = 1.0, QgsFeedback *feedback = nullptr );
103
110 static void multiplyOpacity( QImage &image, double factor, QgsFeedback *feedback = nullptr );
111
118 static void overlayColor( QImage &image, const QColor &color );
119
122 {
123
129 bool shadeExterior = true;
130
135 bool useMaxDistance = true;
136
141 double spread = 10.0;
142
146 QgsColorRamp *ramp = nullptr;
147 };
148
157 static void distanceTransform( QImage &image, const QgsImageOperation::DistanceTransformProperties &properties, QgsFeedback *feedback = nullptr );
158
169 static void stackBlur( QImage &image, int radius, bool alphaOnly = false, QgsFeedback *feedback = nullptr );
170
180 static QImage *gaussianBlur( QImage &image, int radius, QgsFeedback *feedback = nullptr ) SIP_FACTORY;
181
187 static void flipImage( QImage &image, FlipType type );
188
198 static QRect nonTransparentImageRect( const QImage &image, QSize minSize = QSize(), bool center = false );
199
208 static QImage cropTransparent( const QImage &image, QSize minSize = QSize(), bool center = false );
209
210 private:
211
212 //for blocked operations
213 enum LineOperationDirection
214 {
215 ByRow,
216 ByColumn
217 };
218 template <class BlockOperation> static void runBlockOperationInThreads( QImage &image, BlockOperation &operation, LineOperationDirection direction );
219 struct ImageBlock
220 {
221 unsigned int beginLine;
222 unsigned int endLine;
223 unsigned int lineLength;
224 QImage *image = nullptr;
225 };
226
227 //for rect operations
228 template <typename RectOperation> static void runRectOperation( QImage &image, RectOperation &operation );
229 template <class RectOperation> static void runRectOperationOnWholeImage( QImage &image, RectOperation &operation );
230
231 //for per pixel operations
232 template <class PixelOperation> static void runPixelOperation( QImage &image, PixelOperation &operation, QgsFeedback *feedback = nullptr );
233 template <class PixelOperation> static void runPixelOperationOnWholeImage( QImage &image, PixelOperation &operation, QgsFeedback *feedback = nullptr );
234 template <class PixelOperation>
235 struct ProcessBlockUsingPixelOperation
236 {
237 explicit ProcessBlockUsingPixelOperation( PixelOperation &operation, QgsFeedback *feedback )
238 : mOperation( operation )
239 , mFeedback( feedback )
240 { }
241
242 typedef void result_type;
243
244 void operator()( ImageBlock &block )
245 {
246 for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
247 {
248 if ( mFeedback && mFeedback->isCanceled() )
249 break;
250
251 QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
252 for ( unsigned int x = 0; x < block.lineLength; ++x )
253 {
254 mOperation( ref[x], x, y );
255 }
256 }
257 }
258
259 PixelOperation &mOperation;
260 QgsFeedback *mFeedback = nullptr;
261 };
262
263 //for linear operations
264 template <typename LineOperation> static void runLineOperation( QImage &image, LineOperation &operation, QgsFeedback *feedback = nullptr );
265 template <class LineOperation> static void runLineOperationOnWholeImage( QImage &image, LineOperation &operation, QgsFeedback *feedback = nullptr );
266 template <class LineOperation>
267 struct ProcessBlockUsingLineOperation
268 {
269 explicit ProcessBlockUsingLineOperation( LineOperation &operation )
270 : mOperation( operation ) { }
271
272 typedef void result_type;
273
274 void operator()( ImageBlock &block )
275 {
276 //do something with whole lines
277 int bpl = block.image->bytesPerLine();
278 if ( mOperation.direction() == ByRow )
279 {
280 for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
281 {
282 QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
283 mOperation( ref, block.lineLength, bpl );
284 }
285 }
286 else
287 {
288 //by column
289 unsigned char *ref = block.image->scanLine( 0 ) + 4 * block.beginLine;
290 for ( unsigned int x = block.beginLine; x < block.endLine; ++x, ref += 4 )
291 {
292 mOperation( reinterpret_cast< QRgb * >( ref ), block.lineLength, bpl );
293 }
294 }
295 }
296
297 LineOperation &mOperation;
298 };
299
300
301 //individual operation implementations
302
303 class GrayscalePixelOperation
304 {
305 public:
306 explicit GrayscalePixelOperation( const GrayscaleMode mode )
307 : mMode( mode )
308 { }
309
310 void operator()( QRgb &rgb, int x, int y ) const;
311
312 private:
313 GrayscaleMode mMode;
314 };
315 static void grayscaleLightnessOp( QRgb &rgb );
316 static void grayscaleLuminosityOp( QRgb &rgb );
317 static void grayscaleAverageOp( QRgb &rgb );
318
319
320 class BrightnessContrastPixelOperation
321 {
322 public:
323 BrightnessContrastPixelOperation( const int brightness, const double contrast )
324 : mBrightness( brightness )
325 , mContrast( contrast )
326 { }
327
328 void operator()( QRgb &rgb, int x, int y );
329
330 private:
331 int mBrightness;
332 double mContrast;
333 };
334
335
336 class HueSaturationPixelOperation
337 {
338 public:
339 HueSaturationPixelOperation( const double saturation, const bool colorize,
340 const int colorizeHue, const int colorizeSaturation,
341 const double colorizeStrength )
342 : mSaturation( saturation )
343 , mColorize( colorize )
344 , mColorizeHue( colorizeHue )
345 , mColorizeSaturation( colorizeSaturation )
346 , mColorizeStrength( colorizeStrength )
347 { }
348
349 void operator()( QRgb &rgb, int x, int y );
350
351 private:
352 double mSaturation; // [0, 2], 1 = no change
353 bool mColorize;
354 int mColorizeHue;
355 int mColorizeSaturation;
356 double mColorizeStrength; // [0,1]
357 };
358 static int adjustColorComponent( int colorComponent, int brightness, double contrastFactor );
359
360
361 class MultiplyOpacityPixelOperation
362 {
363 public:
364 explicit MultiplyOpacityPixelOperation( const double factor )
365 : mFactor( factor )
366 { }
367
368 void operator()( QRgb &rgb, int x, int y );
369
370 private:
371 double mFactor;
372 };
373
374 class ConvertToArrayPixelOperation
375 {
376 public:
377 ConvertToArrayPixelOperation( const int width, double *array, const bool exterior = true )
378 : mWidth( width )
379 , mArray( array )
380 , mExterior( exterior )
381 {
382 }
383
384 void operator()( QRgb &rgb, int x, int y );
385
386 private:
387 int mWidth;
388 double *mArray = nullptr;
389 bool mExterior;
390 };
391
392 class ShadeFromArrayOperation
393 {
394 public:
395 ShadeFromArrayOperation( const int width, double *array, const double spread,
396 const DistanceTransformProperties &properties )
397 : mWidth( width )
398 , mArray( array )
399 , mSpread( spread )
400 , mProperties( properties )
401 {
402 mSpreadSquared = std::pow( mSpread, 2.0 );
403 }
404
405 void operator()( QRgb &rgb, int x, int y );
406
407 private:
408 int mWidth;
409 double *mArray = nullptr;
410 double mSpread;
411 double mSpreadSquared;
412 const DistanceTransformProperties &mProperties;
413 };
414 static void distanceTransform2d( double *im, int width, int height, QgsFeedback *feedback = nullptr );
415 static void distanceTransform1d( double *f, int n, int *v, double *z, double *d );
416 static double maxValueInDistanceTransformArray( const double *array, unsigned int size );
417
418
419 class StackBlurLineOperation
420 {
421 public:
422 StackBlurLineOperation( int alpha, LineOperationDirection direction, bool forwardDirection, int i1, int i2, QgsFeedback *feedback )
423 : mAlpha( alpha )
424 , mDirection( direction )
425 , mForwardDirection( forwardDirection )
426 , mi1( i1 )
427 , mi2( i2 )
428 , mFeedback( feedback )
429 { }
430
431 typedef void result_type;
432
433 LineOperationDirection direction() const { return mDirection; }
434
435 void operator()( QRgb *startRef, int lineLength, int bytesPerLine )
436 {
437 if ( mFeedback && mFeedback->isCanceled() )
438 return;
439
440 unsigned char *p = reinterpret_cast< unsigned char * >( startRef );
441 int rgba[4];
442 int increment = ( mDirection == QgsImageOperation::ByRow ) ? 4 : bytesPerLine;
443 if ( !mForwardDirection )
444 {
445 p += static_cast< std::size_t >( lineLength - 1 ) * increment;
446 increment = -increment;
447 }
448
449 for ( int i = mi1; i <= mi2; ++i )
450 {
451 rgba[i] = p[i] << 4;
452 }
453
454 p += increment;
455 for ( int j = 1; j < lineLength; ++j, p += increment )
456 {
457 if ( mFeedback && mFeedback->isCanceled() )
458 break;
459
460 for ( int i = mi1; i <= mi2; ++i )
461 {
462 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * mAlpha / 16 ) >> 4;
463 }
464 }
465 }
466
467 private:
468 int mAlpha;
469 LineOperationDirection mDirection;
470 bool mForwardDirection;
471 int mi1;
472 int mi2;
473 QgsFeedback *mFeedback = nullptr;
474 };
475
476 static double *createGaussianKernel( int radius );
477
478 class GaussianBlurOperation
479 {
480 public:
481 GaussianBlurOperation( int radius, LineOperationDirection direction, QImage *destImage, double *kernel, QgsFeedback *feedback )
482 : mRadius( radius )
483 , mDirection( direction )
484 , mDestImage( destImage )
485 , mDestImageBpl( destImage->bytesPerLine() )
486 , mKernel( kernel )
487 , mFeedback( feedback )
488 {}
489
490 typedef void result_type;
491
492 void operator()( ImageBlock &block );
493
494 private:
495 int mRadius;
496 LineOperationDirection mDirection;
497 QImage *mDestImage = nullptr;
498 int mDestImageBpl;
499 double *mKernel = nullptr;
500 QgsFeedback *mFeedback = nullptr;
501
502 inline QRgb gaussianBlurVertical( int posy, unsigned char *sourceFirstLine, int sourceBpl, int height ) const;
503 inline QRgb gaussianBlurHorizontal( int posx, unsigned char *sourceFirstLine, int width ) const;
504 };
505
506 //flip
507
508
509 class FlipLineOperation
510 {
511 public:
512 explicit FlipLineOperation( LineOperationDirection direction )
513 : mDirection( direction )
514 { }
515
516 typedef void result_type;
517
518 LineOperationDirection direction() const { return mDirection; }
519
520 void operator()( QRgb *startRef, int lineLength, int bytesPerLine ) const;
521
522 private:
523 LineOperationDirection mDirection;
524 };
525
526
527};
528
529#endif // QGSIMAGEOPERATION_H
530
Abstract base class for color ramps.
Definition: qgscolorramp.h:29
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
Contains operations and filters which apply to QImages.
FlipType
Flip operation types.
@ FlipHorizontal
Flip the image horizontally.
GrayscaleMode
Modes for converting a QImage to grayscale.
@ GrayscaleLightness
Keep the lightness of the color, drops the saturation.
@ GrayscaleLuminosity
Grayscale by perceptual luminosity (weighted sum of color RGB components)
@ GrayscaleAverage
Grayscale by taking average of color RGB components.
#define SIP_FACTORY
Definition: qgis_sip.h:76
Struct for storing properties of a distance transform operation.