QGIS API Documentation 4.1.0-Master (467af3bbe65)
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
216 static QImage floodFill( const QImage &image, const QPoint &startPoint, const QColor &newColor, int tolerance = 0, QgsFeedback *feedback = nullptr );
217
218 private:
219 //for blocked operations
220 enum LineOperationDirection
221 {
222 ByRow,
223 ByColumn
224 };
225 template<class BlockOperation> static void runBlockOperationInThreads( QImage &image, BlockOperation &operation, LineOperationDirection direction );
226 struct ImageBlock
227 {
228 unsigned int beginLine;
229 unsigned int endLine;
230 unsigned int lineLength;
231 QImage *image = nullptr;
232 };
233
234 //for rect operations
235 template<typename RectOperation> static void runRectOperation( QImage &image, RectOperation &operation );
236 template<class RectOperation> static void runRectOperationOnWholeImage( QImage &image, RectOperation &operation );
237
238 //for per pixel operations
239 template<class PixelOperation> static void runPixelOperation( QImage &image, PixelOperation &operation, QgsFeedback *feedback = nullptr );
240 template<class PixelOperation> static void runPixelOperationOnWholeImage( QImage &image, PixelOperation &operation, QgsFeedback *feedback = nullptr );
241 template<class PixelOperation> struct ProcessBlockUsingPixelOperation
242 {
243 explicit ProcessBlockUsingPixelOperation( PixelOperation &operation, QgsFeedback *feedback )
244 : mOperation( operation )
245 , mFeedback( feedback )
246 {}
247
248 typedef void result_type;
249
250 void operator()( ImageBlock &block )
251 {
252 for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
253 {
254 if ( mFeedback && mFeedback->isCanceled() )
255 break;
256
257 QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
258 for ( unsigned int x = 0; x < block.lineLength; ++x )
259 {
260 mOperation( ref[x], x, y );
261 }
262 }
263 }
264
265 PixelOperation &mOperation;
266 QgsFeedback *mFeedback = nullptr;
267 };
268
269 //for linear operations
270 template<typename LineOperation> static void runLineOperation( QImage &image, LineOperation &operation, QgsFeedback *feedback = nullptr );
271 template<class LineOperation> static void runLineOperationOnWholeImage( QImage &image, LineOperation &operation, QgsFeedback *feedback = nullptr );
272 template<class LineOperation> struct ProcessBlockUsingLineOperation
273 {
274 explicit ProcessBlockUsingLineOperation( LineOperation &operation )
275 : mOperation( operation )
276 {}
277
278 typedef void result_type;
279
280 void operator()( ImageBlock &block )
281 {
282 //do something with whole lines
283 int bpl = block.image->bytesPerLine();
284 if ( mOperation.direction() == ByRow )
285 {
286 for ( unsigned int y = block.beginLine; y < block.endLine; ++y )
287 {
288 QRgb *ref = reinterpret_cast< QRgb * >( block.image->scanLine( y ) );
289 mOperation( ref, block.lineLength, bpl );
290 }
291 }
292 else
293 {
294 //by column
295 unsigned char *ref = block.image->scanLine( 0 ) + 4 * block.beginLine;
296 for ( unsigned int x = block.beginLine; x < block.endLine; ++x, ref += 4 )
297 {
298 mOperation( reinterpret_cast< QRgb * >( ref ), block.lineLength, bpl );
299 }
300 }
301 }
302
303 LineOperation &mOperation;
304 };
305
306
307 //individual operation implementations
308
309 class GrayscalePixelOperation
310 {
311 public:
312 explicit GrayscalePixelOperation( const GrayscaleMode mode )
313 : mMode( mode )
314 {}
315
316 void operator()( QRgb &rgb, int x, int y ) const;
317
318 private:
319 GrayscaleMode mMode;
320 };
321 static void grayscaleLightnessOp( QRgb &rgb );
322 static void grayscaleLuminosityOp( QRgb &rgb );
323 static void grayscaleAverageOp( QRgb &rgb );
324
325
326 class BrightnessContrastPixelOperation
327 {
328 public:
329 BrightnessContrastPixelOperation( const int brightness, const double contrast )
330 : mBrightness( brightness )
331 , mContrast( contrast )
332 {}
333
334 void operator()( QRgb &rgb, int x, int y ) const;
335
336 private:
337 int mBrightness;
338 double mContrast;
339 };
340
341
342 class HueSaturationPixelOperation
343 {
344 public:
345 HueSaturationPixelOperation( const double saturation, const bool colorize, const int colorizeHue, const int colorizeSaturation, const double colorizeStrength )
346 : mSaturation( saturation )
347 , mColorize( colorize )
348 , mColorizeHue( colorizeHue )
349 , mColorizeSaturation( colorizeSaturation )
350 , mColorizeStrength( colorizeStrength )
351 {}
352
353 void operator()( QRgb &rgb, int x, int y ) const;
354
355 private:
356 double mSaturation; // [0, 2], 1 = no change
357 bool mColorize;
358 int mColorizeHue;
359 int mColorizeSaturation;
360 double mColorizeStrength; // [0,1]
361 };
362 static int adjustColorComponent( int colorComponent, int brightness, double contrastFactor );
363
364
365 class MultiplyOpacityPixelOperation
366 {
367 public:
368 explicit MultiplyOpacityPixelOperation( const double factor )
369 : mFactor( factor )
370 {}
371
372 void operator()( QRgb &rgb, int x, int y ) const;
373
374 private:
375 double mFactor;
376 };
377
378 class ConvertToArrayPixelOperation
379 {
380 public:
381 ConvertToArrayPixelOperation( const int width, double *array, const bool exterior = true )
382 : mWidth( width )
383 , mArray( array )
384 , mExterior( exterior )
385 {}
386
387 void operator()( QRgb &rgb, int x, int y );
388
389 private:
390 int mWidth;
391 double *mArray = nullptr;
392 bool mExterior;
393 };
394
395 class ShadeFromArrayOperation
396 {
397 public:
398 ShadeFromArrayOperation( const int width, double *array, const double spread, const DistanceTransformProperties &properties )
399 : mWidth( width )
400 , mArray( array )
401 , mSpread( spread )
402 , mProperties( properties )
403 {
404 mSpreadSquared = std::pow( mSpread, 2.0 );
405 }
406
407 void operator()( QRgb &rgb, int x, int y );
408
409 private:
410 int mWidth;
411 double *mArray = nullptr;
412 double mSpread;
413 double mSpreadSquared;
414 const DistanceTransformProperties &mProperties;
415 };
416 static void distanceTransform2d( double *im, int width, int height, QgsFeedback *feedback = nullptr );
417 static void distanceTransform1d( double *f, int n, int *v, double *z, double *d );
418 static double maxValueInDistanceTransformArray( const double *array, unsigned int size );
419
420
421 class StackBlurLineOperation
422 {
423 public:
424 StackBlurLineOperation( int alpha, LineOperationDirection direction, bool forwardDirection, int i1, int i2, QgsFeedback *feedback )
425 : mAlpha( alpha )
426 , mDirection( direction )
427 , mForwardDirection( forwardDirection )
428 , mi1( i1 )
429 , mi2( i2 )
430 , mFeedback( feedback )
431 {}
432
433 typedef void result_type;
434
435 LineOperationDirection direction() const { return mDirection; }
436
437 void operator()( QRgb *startRef, int lineLength, int bytesPerLine )
438 {
439 if ( mFeedback && mFeedback->isCanceled() )
440 return;
441
442 unsigned char *p = reinterpret_cast< unsigned char * >( startRef );
443 int rgba[4];
444 int increment = ( mDirection == QgsImageOperation::ByRow ) ? 4 : bytesPerLine;
445 if ( !mForwardDirection )
446 {
447 p += static_cast< std::size_t >( lineLength - 1 ) * increment;
448 increment = -increment;
449 }
450
451 for ( int i = mi1; i <= mi2; ++i )
452 {
453 rgba[i] = p[i] << 4;
454 }
455
456 p += increment;
457 for ( int j = 1; j < lineLength; ++j, p += increment )
458 {
459 if ( mFeedback && mFeedback->isCanceled() )
460 break;
461
462 for ( int i = mi1; i <= mi2; ++i )
463 {
464 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * mAlpha / 16 ) >> 4;
465 }
466 }
467 }
468
469 private:
470 int mAlpha;
471 LineOperationDirection mDirection;
472 bool mForwardDirection;
473 int mi1;
474 int mi2;
475 QgsFeedback *mFeedback = nullptr;
476 };
477
478 static double *createGaussianKernel( int radius );
479
480 class GaussianBlurOperation
481 {
482 public:
483 GaussianBlurOperation( int radius, LineOperationDirection direction, QImage *destImage, double *kernel, QgsFeedback *feedback )
484 : mRadius( radius )
485 , mDirection( direction )
486 , mDestImage( destImage )
487 , mDestImageBpl( destImage->bytesPerLine() )
488 , mKernel( kernel )
489 , mFeedback( feedback )
490 {}
491
492 typedef void result_type;
493
494 void operator()( ImageBlock &block );
495
496 private:
497 int mRadius;
498 LineOperationDirection mDirection;
499 QImage *mDestImage = nullptr;
500 int mDestImageBpl;
501 double *mKernel = nullptr;
502 QgsFeedback *mFeedback = nullptr;
503
504 inline QRgb gaussianBlurVertical( int posy, unsigned char *sourceFirstLine, int sourceBpl, int height ) const;
505 inline QRgb gaussianBlurHorizontal( int posx, unsigned char *sourceFirstLine, int width ) const;
506 };
507
508 //flip
509
510
511 class FlipLineOperation
512 {
513 public:
514 explicit FlipLineOperation( LineOperationDirection direction )
515 : mDirection( direction )
516 {}
517
518 typedef void result_type;
519
520 LineOperationDirection direction() const { return mDirection; }
521
522 void operator()( QRgb *startRef, int lineLength, int bytesPerLine ) const;
523
524 private:
525 LineOperationDirection mDirection;
526 };
527};
528
529#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 QImage floodFill(const QImage &image, const QPoint &startPoint, const QColor &newColor, int tolerance=0, QgsFeedback *feedback=nullptr)
Performs a flood fill operation on an image, replacing contiguous areas of the same color.
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.