QGIS API Documentation  3.25.0-Master (349eb7cb1e)
qgsrenderchecker.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrenderchecker.h - check maprender output against an expected image
3  --------------------------------------
4  Date : 18 Jan 2008
5  Copyright : (C) 2008 by Tim Sutton
6  email : tim @ linfiniti.com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #ifndef QGSRENDERCHECKER_H
17 #define QGSRENDERCHECKER_H
18 
19 #include "qgis_core.h"
20 #include "qgis_sip.h"
21 
22 #include "qgslogger.h"
23 #include "qgsmapsettings.h"
24 #include "qgsdartmeasurement.h"
25 
26 #include <QDir>
27 #include <QString>
28 #include <QRegularExpression>
29 #include <QList>
30 
31 class QImage;
32 
39 class CORE_EXPORT QgsRenderChecker
40 {
41  public:
42 
47 
55  QString controlImagePath() const;
56 
63  void setControlImagePath( const QString &path );
64 
68  QString report() const { return mReport; }
69 
73  float matchPercent() const
74  {
75  return static_cast<float>( mMismatchCount ) /
76  static_cast<float>( mMatchTarget ) * 100;
77  }
78 
82  unsigned int mismatchCount() const { return mMismatchCount; }
83 
87  unsigned int matchTarget() const { return mMatchTarget; }
88 
94  int elapsedTime() const { return mElapsedTime; }
95  void setElapsedTimeTarget( int target ) { mElapsedTimeTarget = target; }
96 
104  void setControlName( const QString &name );
105 
110  void setControlExtension( const QString &extension ) { mControlExtension = extension; }
111 
116  void setControlPathPrefix( const QString &name ) { mControlPathPrefix = name + '/'; }
117 
118  void setControlPathSuffix( const QString &name );
119 
121  QString imageToHash( const QString &imageFile );
122 
126  void setRenderedImage( const QString &imageFileName ) { mRenderedImageFile = imageFileName; }
127 
133  QString renderedImage() const { return mRenderedImageFile; }
134 
136  void setMapSettings( const QgsMapSettings &mapSettings );
137 
145  void setColorTolerance( unsigned int colorTolerance ) { mColorTolerance = colorTolerance; }
146 
153  void setSizeTolerance( int xTolerance, int yTolerance ) { mMaxSizeDifferenceX = xTolerance; mMaxSizeDifferenceY = yTolerance; }
154 
165  bool runTest( const QString &testName, unsigned int mismatchCount = 0 );
166 
178  bool compareImages( const QString &testName, unsigned int mismatchCount = 0, const QString &renderedImageFile = QString() );
179 
185  bool compareImages( const QString &testName, const QString &referenceImageFile, const QString &renderedImageFile, unsigned int mismatchCount = 0 );
186 
195  bool isKnownAnomaly( const QString &diffImageFile );
196 
201  static void drawBackground( QImage *image );
202 
208  QString expectedImageFile() const { return mExpectedImageFile; }
209 
217  void enableDashBuffering( bool enable ) { mBufferDashMessages = enable; }
218 
225  QVector<QgsDartMeasurement> dartMeasurements() const { return mDashMessages; }
226 
227  protected:
228  QString mReport;
229  unsigned int mMatchTarget = 0;
230  int mElapsedTime = 0;
233 
234  private:
235  void emitDashMessage( const QgsDartMeasurement &dashMessage );
236  void emitDashMessage( const QString &name, QgsDartMeasurement::Type type, const QString &value );
237  void dumpRenderedImageAsBase64();
238 
239  QString mBasePath;
240 
241  QString mControlName;
242  unsigned int mMismatchCount = 0;
243  unsigned int mColorTolerance = 0;
244  int mMaxSizeDifferenceX = 0;
245  int mMaxSizeDifferenceY = 0;
246  int mElapsedTimeTarget = 0;
247  QgsMapSettings mMapSettings;
248  QString mControlExtension = QStringLiteral( "png" );
249  QString mControlPathPrefix;
250  QString mControlPathSuffix;
251  QVector<QgsDartMeasurement> mDashMessages;
252  bool mBufferDashMessages = false;
253 }; // class QgsRenderChecker
254 
255 
264 inline bool compareWkt( const QString &a, const QString &b, double tolerance = 0.000001 )
265 {
266  QgsDebugMsg( QStringLiteral( "a:%1 b:%2 tol:%3" ).arg( a, b ).arg( tolerance ) );
267  const QRegularExpression re( "-?\\d+(?:\\.\\d+)?(?:[eE]\\d+)?" );
268 
269  QString a0( a ), b0( b );
270  a0.replace( re, QStringLiteral( "#" ) );
271  b0.replace( re, QStringLiteral( "#" ) );
272 
273  QgsDebugMsg( QStringLiteral( "a0:%1 b0:%2" ).arg( a0, b0 ) );
274 
275  if ( a0 != b0 )
276  return false;
277 
278  QList<double> al, bl;
279 
280  int pos = 0;
281  QRegularExpressionMatch match = re.match( a );
282  while ( match.hasMatch() )
283  {
284  al << match.captured( 0 ).toDouble();
285  pos = match.capturedStart( 0 ) + match.capturedLength( 0 );
286  match = re.match( a, pos );
287  }
288  pos = 0;
289  match = re.match( b );
290  while ( match.hasMatch() )
291  {
292  bl << match.captured( 0 ).toDouble();
293  pos = match.capturedStart( 0 ) + match.capturedLength( 0 );
294  match = re.match( b, pos );
295  }
296 
297  if ( al.size() != bl.size() )
298  return false;
299 
300  for ( int i = 0; i < al.size(); i++ )
301  {
302  if ( !qgsDoubleNear( al[i], bl[i], tolerance ) )
303  return false;
304  }
305 
306  return true;
307 }
308 
309 #endif
The QgsMapSettings class contains configuration for rendering of the map.
This is a helper class for unit tests that need to write an image and compare it to an expected resul...
void setControlExtension(const QString &extension)
Sets file extension for the control image.
float matchPercent() const
Returns the percent of pixels which matched the control image.
unsigned int matchTarget() const
Returns the total number of pixels in the control image.
int elapsedTime() const
Returns the total elapsed time for the rendering test.
QString renderedImage() const
Returns the path of the rendered image generated by the test.
QVector< QgsDartMeasurement > dartMeasurements() const
Gets access to buffered dash messages.
void setElapsedTimeTarget(int target)
void setControlPathPrefix(const QString &name)
Sets the path prefix where the control images are kept.
void setRenderedImage(const QString &imageFileName)
Sets the file name of the rendered image generated by the test.
void setSizeTolerance(int xTolerance, int yTolerance)
Sets the largest allowable difference in size between the rendered and the expected image.
void enableDashBuffering(bool enable)
Call this to enable internal buffering of dash messages.
unsigned int mismatchCount() const
Returns the number of pixels which did not match the control image.
void setColorTolerance(unsigned int colorTolerance)
Set tolerance for color components used by runTest() and compareImages().
QString report() const
Returns the HTML report describing the results of the test run.
QString expectedImageFile() const
Returns the path to the expected image file.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2075
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
bool compareWkt(const QString &a, const QString &b, double tolerance=0.000001)
Compare two WKT strings with some tolerance.