QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
Loading...
Searching...
No Matches
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 <cmath>
22
23#include "qgis_core.h"
24#include "qgis_sip.h"
25#include "qgsfeedback.h"
26
27#include <QColor>
28#include <QImage>
29
30class QgsColorRamp;
31class QgsFeedback;
32
47class CORE_EXPORT QgsImageOperation
48{
49 public:
60
69
76 static void convertToGrayscale( QImage &image, GrayscaleMode mode = GrayscaleLuminosity, QgsFeedback *feedback = nullptr );
77
89 static void adjustBrightnessContrast( QImage &image, int brightness, double contrast, QgsFeedback *feedback = nullptr );
90
100 static void adjustHueSaturation( QImage &image, double saturation, const QColor &colorizeColor = QColor(), double colorizeStrength = 1.0, QgsFeedback *feedback = nullptr );
101
108 static void multiplyOpacity( QImage &image, double factor, QgsFeedback *feedback = nullptr );
109
116 static void overlayColor( QImage &image, const QColor &color );
117
120 {
126 bool shadeExterior = true;
127
132 bool useMaxDistance = true;
133
138 double spread = 10.0;
139
143 QgsColorRamp *ramp = nullptr;
144 };
145
154 static void distanceTransform( QImage &image, const QgsImageOperation::DistanceTransformProperties &properties, QgsFeedback *feedback = nullptr );
155
166 static void stackBlur( QImage &image, int radius, bool alphaOnly = false, QgsFeedback *feedback = nullptr );
167
177 static QImage *gaussianBlur( QImage &image, int radius, QgsFeedback *feedback = nullptr ) SIP_FACTORY;
178
184 static void flipImage( QImage &image, FlipType type );
185
195 static QRect nonTransparentImageRect( const QImage &image, QSize minSize = QSize(), bool center = false );
196
205 static QImage cropTransparent( const QImage &image, QSize minSize = QSize(), bool center = false );
206
207 private:
208 //for blocked operations
209 enum LineOperationDirection
210 {
211 ByRow,
212 ByColumn
213 };
214 template<class BlockOperation> static void runBlockOperationInThreads( QImage &image, BlockOperation &operation, LineOperationDirection direction );
215 struct ImageBlock
216 {
217 unsigned int beginLine;
218 unsigned int endLine;
219 unsigned int lineLength;
220 QImage *image = nullptr;
221 };
222
223 //for rect operations
224 template<typename RectOperation> static void runRectOperation( QImage &image, RectOperation &operation );
225 template<class RectOperation> static void runRectOperationOnWholeImage( QImage &image, RectOperation &operation );
226
227 //for per pixel operations
228 template<class PixelOperation> static void runPixelOperation( QImage &image, PixelOperation &operation, QgsFeedback *feedback = nullptr );
229 template<class PixelOperation> static void runPixelOperationOnWholeImage( QImage &image, PixelOperation &operation, QgsFeedback *feedback = nullptr );
230 template<class PixelOperation> struct ProcessBlockUsingPixelOperation
231 {
232 explicit ProcessBlockUsingPixelOperation( PixelOperation &operation, QgsFeedback *feedback )
233 : mOperation( operation )
234 , mFeedback( feedback )
235 {}
236
237 typedef void result_type;
238
239 void operator()( ImageBlock &block )
240 {
241 for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
242 {
243 if ( mFeedback && mFeedback->isCanceled() )
244 break;
245
246 QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
247 for ( unsigned int x = 0; x < block.lineLength; ++x )
248 {
249 mOperation( ref[x], x, y );
250 }
251 }
252 }
253
254 PixelOperation &mOperation;
255 QgsFeedback *mFeedback = nullptr;
256 };
257
258 //for linear operations
259 template<typename LineOperation> static void runLineOperation( QImage &image, LineOperation &operation, QgsFeedback *feedback = nullptr );
260 template<class LineOperation> static void runLineOperationOnWholeImage( QImage &image, LineOperation &operation, QgsFeedback *feedback = nullptr );
261 template<class LineOperation> struct ProcessBlockUsingLineOperation
262 {
263 explicit ProcessBlockUsingLineOperation( LineOperation &operation )
264 : mOperation( operation )
265 {}
266
267 typedef void result_type;
268
269 void operator()( ImageBlock &block )
270 {
271 //do something with whole lines
272 int bpl = block.image->bytesPerLine();
273 if ( mOperation.direction() == ByRow )
274 {
275 for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
276 {
277 QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
278 mOperation( ref, block.lineLength, bpl );
279 }
280 }
281 else
282 {
283 //by column
284 unsigned char *ref = block.image->scanLine( 0 ) + 4 * block.beginLine;
285 for ( unsigned int x = block.beginLine; x < block.endLine; ++x, ref += 4 )
286 {
287 mOperation( reinterpret_cast< QRgb * >( ref ), block.lineLength, bpl );
288 }
289 }
290 }
291
292 LineOperation &mOperation;
293 };
294
295
296 //individual operation implementations
297
298 class GrayscalePixelOperation
299 {
300 public:
301 explicit GrayscalePixelOperation( const GrayscaleMode mode )
302 : mMode( mode )
303 {}
304
305 void operator()( QRgb &rgb, int x, int y ) const;
306
307 private:
308 GrayscaleMode mMode;
309 };
310 static void grayscaleLightnessOp( QRgb &rgb );
311 static void grayscaleLuminosityOp( QRgb &rgb );
312 static void grayscaleAverageOp( QRgb &rgb );
313
314
315 class BrightnessContrastPixelOperation
316 {
317 public:
318 BrightnessContrastPixelOperation( const int brightness, const double contrast )
319 : mBrightness( brightness )
320 , mContrast( contrast )
321 {}
322
323 void operator()( QRgb &rgb, int x, int y ) const;
324
325 private:
326 int mBrightness;
327 double mContrast;
328 };
329
330
331 class HueSaturationPixelOperation
332 {
333 public:
334 HueSaturationPixelOperation( const double saturation, const bool colorize, const int colorizeHue, const int colorizeSaturation, const double colorizeStrength )
335 : mSaturation( saturation )
336 , mColorize( colorize )
337 , mColorizeHue( colorizeHue )
338 , mColorizeSaturation( colorizeSaturation )
339 , mColorizeStrength( colorizeStrength )
340 {}
341
342 void operator()( QRgb &rgb, int x, int y ) const;
343
344 private:
345 double mSaturation; // [0, 2], 1 = no change
346 bool mColorize;
347 int mColorizeHue;
348 int mColorizeSaturation;
349 double mColorizeStrength; // [0,1]
350 };
351 static int adjustColorComponent( int colorComponent, int brightness, double contrastFactor );
352
353
354 class MultiplyOpacityPixelOperation
355 {
356 public:
357 explicit MultiplyOpacityPixelOperation( const double factor )
358 : mFactor( factor )
359 {}
360
361 void operator()( QRgb &rgb, int x, int y ) const;
362
363 private:
364 double mFactor;
365 };
366
367 class ConvertToArrayPixelOperation
368 {
369 public:
370 ConvertToArrayPixelOperation( const int width, double *array, const bool exterior = true )
371 : mWidth( width )
372 , mArray( array )
373 , mExterior( exterior )
374 {}
375
376 void operator()( QRgb &rgb, int x, int y );
377
378 private:
379 int mWidth;
380 double *mArray = nullptr;
381 bool mExterior;
382 };
383
384 class ShadeFromArrayOperation
385 {
386 public:
387 ShadeFromArrayOperation( const int width, double *array, const double spread, const DistanceTransformProperties &properties )
388 : mWidth( width )
389 , mArray( array )
390 , mSpread( spread )
391 , mProperties( properties )
392 {
393 mSpreadSquared = std::pow( mSpread, 2.0 );
394 }
395
396 void operator()( QRgb &rgb, int x, int y );
397
398 private:
399 int mWidth;
400 double *mArray = nullptr;
401 double mSpread;
402 double mSpreadSquared;
403 const DistanceTransformProperties &mProperties;
404 };
405 static void distanceTransform2d( double *im, int width, int height, QgsFeedback *feedback = nullptr );
406 static void distanceTransform1d( double *f, int n, int *v, double *z, double *d );
407 static double maxValueInDistanceTransformArray( const double *array, unsigned int size );
408
409
410 class StackBlurLineOperation
411 {
412 public:
413 StackBlurLineOperation( int alpha, LineOperationDirection direction, bool forwardDirection, int i1, int i2, QgsFeedback *feedback )
414 : mAlpha( alpha )
415 , mDirection( direction )
416 , mForwardDirection( forwardDirection )
417 , mi1( i1 )
418 , mi2( i2 )
419 , mFeedback( feedback )
420 {}
421
422 typedef void result_type;
423
424 LineOperationDirection direction() const { return mDirection; }
425
426 void operator()( QRgb *startRef, int lineLength, int bytesPerLine )
427 {
428 if ( mFeedback && mFeedback->isCanceled() )
429 return;
430
431 unsigned char *p = reinterpret_cast< unsigned char * >( startRef );
432 int rgba[4];
433 int increment = ( mDirection == QgsImageOperation::ByRow ) ? 4 : bytesPerLine;
434 if ( !mForwardDirection )
435 {
436 p += static_cast< std::size_t >( lineLength - 1 ) * increment;
437 increment = -increment;
438 }
439
440 for ( int i = mi1; i <= mi2; ++i )
441 {
442 rgba[i] = p[i] << 4;
443 }
444
445 p += increment;
446 for ( int j = 1; j < lineLength; ++j, p += increment )
447 {
448 if ( mFeedback && mFeedback->isCanceled() )
449 break;
450
451 for ( int i = mi1; i <= mi2; ++i )
452 {
453 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * mAlpha / 16 ) >> 4;
454 }
455 }
456 }
457
458 private:
459 int mAlpha;
460 LineOperationDirection mDirection;
461 bool mForwardDirection;
462 int mi1;
463 int mi2;
464 QgsFeedback *mFeedback = nullptr;
465 };
466
467 static double *createGaussianKernel( int radius );
468
469 class GaussianBlurOperation
470 {
471 public:
472 GaussianBlurOperation( int radius, LineOperationDirection direction, QImage *destImage, double *kernel, QgsFeedback *feedback )
473 : mRadius( radius )
474 , mDirection( direction )
475 , mDestImage( destImage )
476 , mDestImageBpl( destImage->bytesPerLine() )
477 , mKernel( kernel )
478 , mFeedback( feedback )
479 {}
480
481 typedef void result_type;
482
483 void operator()( ImageBlock &block );
484
485 private:
486 int mRadius;
487 LineOperationDirection mDirection;
488 QImage *mDestImage = nullptr;
489 int mDestImageBpl;
490 double *mKernel = nullptr;
491 QgsFeedback *mFeedback = nullptr;
492
493 inline QRgb gaussianBlurVertical( int posy, unsigned char *sourceFirstLine, int sourceBpl, int height ) const;
494 inline QRgb gaussianBlurHorizontal( int posx, unsigned char *sourceFirstLine, int width ) const;
495 };
496
497 //flip
498
499
500 class FlipLineOperation
501 {
502 public:
503 explicit FlipLineOperation( LineOperationDirection direction )
504 : mDirection( direction )
505 {}
506
507 typedef void result_type;
508
509 LineOperationDirection direction() const { return mDirection; }
510
511 void operator()( QRgb *startRef, int lineLength, int bytesPerLine ) const;
512
513 private:
514 LineOperationDirection mDirection;
515 };
516};
517
518#endif // QGSIMAGEOPERATION_H
Abstract base class for color ramps.
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.
static void distanceTransform(QImage &image, const QgsImageOperation::DistanceTransformProperties &properties, QgsFeedback *feedback=nullptr)
Performs a distance transform on the source image and shades the result using a color ramp.
FlipType
Flip operation types.
@ FlipHorizontal
Flip the image horizontally.
@ FlipVertical
Flip the image vertically.
static void flipImage(QImage &image, FlipType type)
Flips an image horizontally or vertically.
static QImage * gaussianBlur(QImage &image, int radius, QgsFeedback *feedback=nullptr)
Performs a gaussian blur on an image.
static QRect nonTransparentImageRect(const QImage &image, QSize minSize=QSize(), bool center=false)
Calculates the non-transparent region of an image.
static void stackBlur(QImage &image, int radius, bool alphaOnly=false, QgsFeedback *feedback=nullptr)
Performs a stack blur on an image.
static QImage cropTransparent(const QImage &image, QSize minSize=QSize(), bool center=false)
Crop any transparent border from around an image.
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:83
Struct for storing properties of a distance transform operation.
bool useMaxDistance
Set to true to automatically calculate the maximum distance in the transform to use as the spread val...
bool shadeExterior
Set to true to perform the distance transform on transparent pixels in the source image,...
double spread
Maximum distance (in pixels) for the distance transform shading to spread.
QgsColorRamp * ramp
Color ramp to use for shading the distance transform.