QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsmultirenderchecker.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmultirenderchecker.cpp
3  --------------------------------------
4  Date : 6.11.2014
5  Copyright : (C) 2014 Matthias Kuhn
6  Email : matthias at opengis dot ch
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 #include "qgsmultirenderchecker.h"
17 #include "qgscomposition.h"
18 #include <QDebug>
19 
21  : mColorTolerance( 0 )
22 {
23 }
24 
26 {
27  mControlName = theName;
28 }
29 
31 {
32  mControlPathPrefix = prefix;
33 }
34 
36 {
37  mMapSettings = mapSettings;
38 }
39 
40 bool QgsMultiRenderChecker::runTest( const QString& theTestName, unsigned int theMismatchCount )
41 {
42  bool successful = false;
43 
44  const QString baseDir = controlImagePath();
45 
46  QStringList subDirs = QDir( baseDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot );
47 
48  if ( subDirs.isEmpty() )
49  {
50  subDirs << "";
51  }
52 
53  QVector<QgsDartMeasurement> dartMeasurements;
54 
55  Q_FOREACH ( const QString& suffix, subDirs )
56  {
57  qDebug() << "Checking subdir " << suffix;
58  bool result;
59  QgsRenderChecker checker;
60  checker.enableDashBuffering( true );
61  checker.setColorTolerance( mColorTolerance );
62  checker.setControlPathPrefix( mControlPathPrefix );
63  checker.setControlPathSuffix( suffix );
64  checker.setControlName( mControlName );
65  checker.setMapSettings( mMapSettings );
66 
67  if ( !mRenderedImage.isNull() )
68  {
69  checker.setRenderedImage( mRenderedImage );
70  result = checker.compareImages( theTestName, theMismatchCount, mRenderedImage );
71  }
72  else
73  {
74  result = checker.runTest( theTestName, theMismatchCount );
75  mRenderedImage = checker.renderedImage();
76  }
77 
78  successful |= result;
79 
80  dartMeasurements << checker.dartMeasurements();
81 
82  mReport += checker.report();
83  }
84 
85  if ( !successful )
86  {
87  Q_FOREACH ( const QgsDartMeasurement& measurement, dartMeasurements )
88  measurement.send();
89 
90  QgsDartMeasurement msg( "Image not accepted by test", QgsDartMeasurement::Text, "This may be caused because the test is supposed to fail or rendering inconsistencies."
91  "If this is a rendering inconsistency, please add another control image folder, add an anomaly image or increase the color tolerance." );
92  msg.send();
93  }
94 
95  return successful;
96 }
97 
99 {
100  QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
101  QString myControlImageDir = myDataDir + QDir::separator() + "control_images" +
102  QDir::separator() + mControlPathPrefix + QDir::separator() + mControlName + QDir::separator();
103  return myControlImageDir;
104 }
105 
106 #ifdef ENABLE_TESTS
107 
108 //
109 // QgsCompositionChecker
110 //
111 
113 
114 QgsCompositionChecker::QgsCompositionChecker( const QString& testName, QgsComposition* composition )
116  , mTestName( testName )
117  , mComposition( composition )
118  , mSize( 1122, 794 )
119  , mDotsPerMeter( 96 / 25.4 * 1000 )
120 {
121  // The composer has some slight render inconsistencies on the whole image sometimes
122  setColorTolerance( 5 );
123 }
124 
125 QgsCompositionChecker::QgsCompositionChecker()
126  : mComposition( nullptr )
127  , mDotsPerMeter( 96 / 25.4 * 1000 )
128 {
129 }
130 
131 QgsCompositionChecker::~QgsCompositionChecker()
132 {
133 }
134 
135 bool QgsCompositionChecker::testComposition( QString &theReport, int page, int pixelDiff )
136 {
137  if ( !mComposition )
138  {
139  return false;
140  }
141 
142  setControlName( "expected_" + mTestName );
143 
144 #if 0
145  //fake mode to generate expected image
146  //assume 96 dpi and size of the control image 1122 * 794
147  QImage newImage( QSize( 1122, 794 ), QImage::Format_RGB32 );
148  mComposition->setPlotStyle( QgsComposition::Print );
149  newImage.setDotsPerMeterX( 96 / 25.4 * 1000 );
150  newImage.setDotsPerMeterY( 96 / 25.4 * 1000 );
151  drawBackground( &newImage );
152  QPainter expectedPainter( &newImage );
153  //QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
154  //QRectF targetArea( 0, 0, 3507, 2480 );
155  mComposition->renderPage( &expectedPainter, page );
156  expectedPainter.end();
157  newImage.save( controlImagePath() + QDir::separator() + "expected_" + mTestName + ".png", "PNG" );
158  return true;
159 #endif //0
160 
161  QImage outputImage( mSize, QImage::Format_RGB32 );
162 
163  mComposition->setPlotStyle( QgsComposition::Print );
164  outputImage.setDotsPerMeterX( mDotsPerMeter );
165  outputImage.setDotsPerMeterY( mDotsPerMeter );
166  drawBackground( &outputImage );
167  QPainter p( &outputImage );
168  mComposition->renderPage( &p, page );
169  p.end();
170 
171  QString renderedFilePath = QDir::tempPath() + '/' + QFileInfo( mTestName ).baseName() + "_rendered.png";
172  outputImage.save( renderedFilePath, "PNG" );
173 
174  setRenderedImage( renderedFilePath );
175 
176  bool testResult = runTest( mTestName, pixelDiff );
177 
178  theReport += report();
179 
180  return testResult;
181 }
182 
184 
185 #endif
void setControlPathSuffix(const QString &theName)
void setColorTolerance(unsigned int theColorTolerance)
Set tolerance for color components used by runTest() and compareImages().
void setDotsPerMeterX(int x)
void setDotsPerMeterY(int y)
bool end()
void enableDashBuffering(bool enable)
Call this to enable internal buffering of dash messages.
void setControlName(const QString &theName)
Base directory name for the control image (with control image path suffixed) the path to the image wi...
bool save(const QString &fileName, const char *format, int quality) const
bool runTest(const QString &theTestName, unsigned int theMismatchCount=0)
Test using renderer to generate the image to be compared.
QString report() const
Returns a report for this test.
QString renderedImage()
The path of the rendered image can be retrieved through that method.
This is a helper class for unit tests that need to write an image and compare it to an expected resul...
QChar separator()
void setMapSettings(const QgsMapSettings &mapSettings)
bool isNull() const
The QgsMapSettings class contains configuration for rendering of the map.
void setControlName(const QString &theName)
Base directory name for the control image (with control image path suffixed) the path to the image wi...
bool compareImages(const QString &theTestName, unsigned int theMismatchCount=0, const QString &theRenderedImageFile="")
Test using two arbitary images (map renderer will not be used)
void setRenderedImage(const QString &theImageFileName)
QString tempPath()
bool isEmpty() const
QString controlImagePath() const
controlImagePath
void setMapSettings(const QgsMapSettings &mapSettings)
Set the map settings to use to render the image.
Graphics scene for map printing.
void setControlPathPrefix(const QString &prefix)
bool runTest(const QString &theTestName, unsigned int theMismatchCount=0)
Test using renderer to generate the image to be compared.
QVector< QgsDartMeasurement > dartMeasurements() const
Get access to buffered dash messages.
void setControlPathPrefix(const QString &theName)
Prefix where the control images are kept.
void setColorTolerance(unsigned int theColorTolerance)
Set tolerance for color components used by runTest() Default value is 0.
QStringList entryList(QFlags< QDir::Filter > filters, QFlags< QDir::SortFlag > sort) const
static void drawBackground(QImage *image)
Draws a checkboard pattern for image backgrounds, so that transparency is visible without requiring a...
QString baseName() const
void setRenderedImage(const QString &renderedImagePath)
Set the path to the rendered image.