QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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:
51
57 static QDir testReportDir();
58
65 static bool shouldGenerateReport();
66
74 QString controlImagePath() const;
75
82 void setControlImagePath( const QString &path );
83
92 QString report( bool ignoreSuccess = true ) const;
93
103 QString markdownReport( bool ignoreSuccess = true ) const;
104
108 float matchPercent() const { return static_cast<float>( mMismatchCount ) / static_cast<float>( mMatchTarget ) * 100; }
109
113 unsigned int mismatchCount() const { return mMismatchCount; }
114
118 unsigned int matchTarget() const { return mMatchTarget; }
119
125 int elapsedTime() const { return mElapsedTime; }
126 void setElapsedTimeTarget( int target ) { mElapsedTimeTarget = target; }
127
135 void setControlName( const QString &name );
136
141 void setControlExtension( const QString &extension ) { mControlExtension = extension; }
142
147 void setControlPathPrefix( const QString &name ) { mControlPathPrefix = name + '/'; }
148
149 void setControlPathSuffix( const QString &name );
150
152 QString imageToHash( const QString &imageFile );
153
157 void setRenderedImage( const QString &imageFileName ) { mRenderedImageFile = imageFileName; }
158
164 void setExpectFail( bool expectFail ) { mExpectFail = expectFail; }
165
171 QString renderedImage() const { return mRenderedImageFile; }
172
173 void setMapSettings( const QgsMapSettings &mapSettings );
174
181 void setColorTolerance( unsigned int colorTolerance ) { mColorTolerance = colorTolerance; }
182
188 void setSizeTolerance( int xTolerance, int yTolerance )
189 {
190 mMaxSizeDifferenceX = xTolerance;
191 mMaxSizeDifferenceY = yTolerance;
192 }
193
199 enum class Flag : int SIP_ENUM_BASETYPE( IntFlag )
200 {
201 AvoidExportingRenderedImage = 1 << 0,
202 Silent = 1 << 1,
203 };
204 Q_ENUM( Flag )
205
206
211 Q_DECLARE_FLAGS( Flags, Flag )
212 Q_FLAG( Flags )
213
226 bool runTest( const QString &testName, unsigned int mismatchCount = 0, QgsRenderChecker::Flags flags = QgsRenderChecker::Flags() );
227
241 bool compareImages( const QString &testName, unsigned int mismatchCount = 0, const QString &renderedImageFile = QString(), QgsRenderChecker::Flags flags = QgsRenderChecker::Flags() );
242
248 bool compareImages(
249 const QString &testName, const QString &referenceImageFile, const QString &renderedImageFile, unsigned int mismatchCount = 0, QgsRenderChecker::Flags flags = QgsRenderChecker::Flags()
250 );
251
262 Q_DECL_DEPRECATED bool isKnownAnomaly( const QString &diffImageFile ) SIP_DEPRECATED;
263
268 static void drawBackground( QImage *image );
269
275 QString expectedImageFile() const { return mExpectedImageFile; }
276
284 void enableDashBuffering( bool enable ) { mBufferDashMessages = enable; }
285
292 QVector<QgsDartMeasurement> dartMeasurements() const { return mDashMessages; }
293
299 static QString sourcePath();
300
301 protected:
303 QString mReport;
306 unsigned int mMatchTarget = 0;
311
312 private:
313 void emitDashMessage( const QgsDartMeasurement &dashMessage );
314 void emitDashMessage( const QString &name, QgsDartMeasurement::Type type, const QString &value );
315
316#if DUMP_BASE64_IMAGES
317 void dumpRenderedImageAsBase64();
318#endif
319
320 void performPostTestActions( Flags flags );
321
322 bool mResult = false;
323 bool mExpectFail = false;
324
325 QString mBasePath;
326
327 QString mControlName;
328 unsigned int mMismatchCount = 0;
329 unsigned int mColorTolerance = 0;
330 int mMaxSizeDifferenceX = 0;
331 int mMaxSizeDifferenceY = 0;
332 int mElapsedTimeTarget = 0;
333 QgsMapSettings mMapSettings;
334 QString mControlExtension = u"png"_s;
335 QString mControlPathPrefix;
336 QString mControlPathSuffix;
337 bool mIsCiRun = false;
338 QVector<QgsDartMeasurement> mDashMessages;
339 bool mBufferDashMessages = false;
340 QString mDiffImageFile;
341
343};
344
346
347
354
355inline bool compareWkt( const QString &a, const QString &b, double tolerance = 0.000001 )
356{
357 QgsDebugMsgLevel( u"a:%1 b:%2 tol:%3"_s.arg( a, b ).arg( tolerance ), 2 );
358 const thread_local QRegularExpression re( "-?\\d+(?:\\.\\d+)?(?:[eE]\\d+)?" );
359
360 QString a0( a ), b0( b );
361 a0.replace( re, u"#"_s );
362 b0.replace( re, u"#"_s );
363
364 QgsDebugMsgLevel( u"a0:%1 b0:%2"_s.arg( a0, b0 ), 2 );
365
366 if ( a0 != b0 )
367 return false;
368
369 QList<double> al, bl;
370
371 int pos = 0;
372 QRegularExpressionMatch match = re.match( a );
373 while ( match.hasMatch() )
374 {
375 al << match.captured( 0 ).toDouble();
376 pos = match.capturedStart( 0 ) + match.capturedLength( 0 );
377 match = re.match( a, pos );
378 }
379 match = re.match( b );
380 while ( match.hasMatch() )
381 {
382 bl << match.captured( 0 ).toDouble();
383 pos = match.capturedStart( 0 ) + match.capturedLength( 0 );
384 match = re.match( b, pos );
385 }
386
387 if ( al.size() != bl.size() )
388 return false;
389
390 for ( int i = 0; i < al.size(); i++ )
391 {
392 if ( !qgsDoubleNear( al[i], bl[i], tolerance ) )
393 return false;
394 }
395
396 return true;
397}
398
399#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:6975
#define SIP_DEPRECATED
Definition qgis_sip.h:113
#define SIP_ENUM_BASETYPE(type)
Definition qgis_sip.h:274
#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.