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