QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
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#include "qgsdartmeasurement.h"
22#include "qgslogger.h"
23#include "qgsmapsettings.h"
24
25#include <QDir>
26#include <QList>
27#include <QRegularExpression>
28#include <QString>
29
30using namespace Qt::StringLiterals;
31
32class QImage;
33
34#define DUMP_BASE64_IMAGES 0
35
42class CORE_EXPORT QgsRenderChecker
43{
44 Q_GADGET
45
46 public:
47
52
58 static QDir testReportDir();
59
66 static bool shouldGenerateReport();
67
75 QString controlImagePath() const;
76
83 void setControlImagePath( const QString &path );
84
93 QString report( bool ignoreSuccess = true ) const;
94
104 QString markdownReport( bool ignoreSuccess = true ) const;
105
109 float matchPercent() const
110 {
111 return static_cast<float>( mMismatchCount ) /
112 static_cast<float>( mMatchTarget ) * 100;
113 }
114
118 unsigned int mismatchCount() const { return mMismatchCount; }
119
123 unsigned int matchTarget() const { return mMatchTarget; }
124
130 int elapsedTime() const { return mElapsedTime; }
131 void setElapsedTimeTarget( int target ) { mElapsedTimeTarget = target; }
132
140 void setControlName( const QString &name );
141
146 void setControlExtension( const QString &extension ) { mControlExtension = extension; }
147
152 void setControlPathPrefix( const QString &name ) { mControlPathPrefix = name + '/'; }
153
154 void setControlPathSuffix( const QString &name );
155
157 QString imageToHash( const QString &imageFile );
158
162 void setRenderedImage( const QString &imageFileName ) { mRenderedImageFile = imageFileName; }
163
169 void setExpectFail( bool expectFail ) { mExpectFail = expectFail; }
170
176 QString renderedImage() const { return mRenderedImageFile; }
177
178 void setMapSettings( const QgsMapSettings &mapSettings );
179
186 void setColorTolerance( unsigned int colorTolerance ) { mColorTolerance = colorTolerance; }
187
193 void setSizeTolerance( int xTolerance, int yTolerance ) { mMaxSizeDifferenceX = xTolerance; mMaxSizeDifferenceY = yTolerance; }
194
200 enum class Flag : int SIP_ENUM_BASETYPE( IntFlag )
201 {
202 AvoidExportingRenderedImage = 1 << 0,
203 Silent = 1 << 1,
204 };
205 Q_ENUM( Flag )
206
207
212 Q_DECLARE_FLAGS( Flags, Flag )
213 Q_FLAG( Flags )
214
227 bool runTest( const QString &testName, unsigned int mismatchCount = 0, QgsRenderChecker::Flags flags = QgsRenderChecker::Flags() );
228
242 bool compareImages( const QString &testName, unsigned int mismatchCount = 0, const QString &renderedImageFile = QString(), QgsRenderChecker::Flags flags = QgsRenderChecker::Flags() );
243
249 bool compareImages( const QString &testName, const QString &referenceImageFile, const QString &renderedImageFile, unsigned int mismatchCount = 0, QgsRenderChecker::Flags flags = QgsRenderChecker::Flags() );
250
261 Q_DECL_DEPRECATED bool isKnownAnomaly( const QString &diffImageFile ) SIP_DEPRECATED;
262
267 static void drawBackground( QImage *image );
268
274 QString expectedImageFile() const { return mExpectedImageFile; }
275
283 void enableDashBuffering( bool enable ) { mBufferDashMessages = enable; }
284
291 QVector<QgsDartMeasurement> dartMeasurements() const { return mDashMessages; }
292
298 static QString sourcePath();
299
300 protected:
302 QString mReport;
305 unsigned int mMatchTarget = 0;
310
311 private:
312 void emitDashMessage( const QgsDartMeasurement &dashMessage );
313 void emitDashMessage( const QString &name, QgsDartMeasurement::Type type, const QString &value );
314
315#if DUMP_BASE64_IMAGES
316 void dumpRenderedImageAsBase64();
317#endif
318
319 void performPostTestActions( Flags flags );
320
321 bool mResult = false;
322 bool mExpectFail = false;
323
324 QString mBasePath;
325
326 QString mControlName;
327 unsigned int mMismatchCount = 0;
328 unsigned int mColorTolerance = 0;
329 int mMaxSizeDifferenceX = 0;
330 int mMaxSizeDifferenceY = 0;
331 int mElapsedTimeTarget = 0;
332 QgsMapSettings mMapSettings;
333 QString mControlExtension = u"png"_s;
334 QString mControlPathPrefix;
335 QString mControlPathSuffix;
336 bool mIsCiRun = false;
337 QVector<QgsDartMeasurement> mDashMessages;
338 bool mBufferDashMessages = false;
339 QString mDiffImageFile;
340
342};
343
345
346
353
354inline bool compareWkt( const QString &a, const QString &b, double tolerance = 0.000001 )
355{
356 QgsDebugMsgLevel( u"a:%1 b:%2 tol:%3"_s.arg( a, b ).arg( tolerance ), 2 );
357 const thread_local QRegularExpression re( "-?\\d+(?:\\.\\d+)?(?:[eE]\\d+)?" );
358
359 QString a0( a ), b0( b );
360 a0.replace( re, u"#"_s );
361 b0.replace( re, u"#"_s );
362
363 QgsDebugMsgLevel( u"a0:%1 b0:%2"_s.arg( a0, b0 ), 2 );
364
365 if ( a0 != b0 )
366 return false;
367
368 QList<double> al, bl;
369
370 int pos = 0;
371 QRegularExpressionMatch match = re.match( a );
372 while ( match.hasMatch() )
373 {
374 al << match.captured( 0 ).toDouble();
375 pos = match.capturedStart( 0 ) + match.capturedLength( 0 );
376 match = re.match( a, pos );
377 }
378 match = re.match( b );
379 while ( match.hasMatch() )
380 {
381 bl << match.captured( 0 ).toDouble();
382 pos = match.capturedStart( 0 ) + match.capturedLength( 0 );
383 match = re.match( b, pos );
384 }
385
386 if ( al.size() != bl.size() )
387 return false;
388
389 for ( int i = 0; i < al.size(); i++ )
390 {
391 if ( !qgsDoubleNear( al[i], bl[i], tolerance ) )
392 return false;
393 }
394
395 return true;
396}
397
398#endif
Emits dart measurements for display in CDash reports.
Contains configuration for rendering maps.
Q_DECL_DEPRECATED bool isKnownAnomaly(const QString &diffImageFile)
Gets a list of all the anomalies.
static QDir testReportDir()
Returns the directory to use for generating a test report.
QString markdownReport(bool ignoreSuccess=true) const
Returns the markdown report describing the results of the test run.
void setControlExtension(const QString &extension)
Sets file extension for the control image.
friend class QgsMultiRenderChecker
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.
QString mReport
HTML format report.
static bool shouldGenerateReport()
Returns true if a test report should be generated given the current environment.
unsigned int mMatchTarget
void setControlImagePath(const QString &path)
Sets the base path containing the reference images.
bool runTest(const QString &testName, unsigned int mismatchCount=0, QgsRenderChecker::Flags flags=QgsRenderChecker::Flags())
Test using renderer to generate the image to be compared.
QFlags< Flag > Flags
Render checker flags.
Flag
Render checker flags.
int elapsedTime() const
Returns the total elapsed time for the rendering test.
QString mMarkdownReport
Markdown report.
QString renderedImage() const
Returns the path of the rendered image generated by the test.
void setElapsedTimeTarget(int target)
QVector< QgsDartMeasurement > dartMeasurements() const
Gets access to buffered dash messages.
void setControlPathPrefix(const QString &name)
Sets the path prefix where the control images are kept.
QString report(bool ignoreSuccess=true) const
Returns the HTML report describing the results of the test run.
static void drawBackground(QImage *image)
Draws a checkboard pattern for image backgrounds, so that opacity is visible without requiring a tran...
bool compareImages(const QString &testName, unsigned int mismatchCount=0, const QString &renderedImageFile=QString(), QgsRenderChecker::Flags flags=QgsRenderChecker::Flags())
Test using two arbitrary images (map renderer will not be used).
void setRenderedImage(const QString &imageFileName)
Sets the file name of the rendered image generated by the test.
QgsRenderChecker()
Constructor for QgsRenderChecker.
QString controlImagePath() const
Returns the base path containing the reference images.
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 setExpectFail(bool expectFail)
Sets whether the comparison is expected to fail.
void setColorTolerance(unsigned int colorTolerance)
Set tolerance for color components used by runTest() and compareImages().
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:6900
#define SIP_DEPRECATED
Definition qgis_sip.h:114
#define SIP_ENUM_BASETYPE(type)
Definition qgis_sip.h:275
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
Q_DECLARE_OPERATORS_FOR_FLAGS(QgsProjectionSelectionWidget::CrsOptions)
bool compareWkt(const QString &a, const QString &b, double tolerance=0.000001)
Compare two WKT strings with some tolerance.