QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 "qgslayout.h"
18 #include <QDebug>
19 
20 void QgsMultiRenderChecker::setControlName( const QString &name )
21 {
22  mControlName = name;
23 }
24 
25 void QgsMultiRenderChecker::setControlPathPrefix( const QString &prefix )
26 {
27  mControlPathPrefix = prefix;
28 }
29 
31 {
32  mMapSettings = mapSettings;
33 }
34 
35 bool QgsMultiRenderChecker::runTest( const QString &testName, unsigned int mismatchCount )
36 {
37  bool successful = false;
38 
39  const QString baseDir = controlImagePath();
40 
41  QStringList subDirs = QDir( baseDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot );
42 
43  if ( subDirs.isEmpty() )
44  {
45  subDirs << QString();
46  }
47 
48  QVector<QgsDartMeasurement> dartMeasurements;
49 
50  const auto constSubDirs = subDirs;
51  for ( const QString &suffix : constSubDirs )
52  {
53  qDebug() << "Checking subdir " << suffix;
54  bool result;
55  QgsRenderChecker checker;
56  checker.enableDashBuffering( true );
57  checker.setColorTolerance( mColorTolerance );
58  checker.setSizeTolerance( mMaxSizeDifferenceX, mMaxSizeDifferenceY );
59  checker.setControlPathPrefix( mControlPathPrefix );
60  checker.setControlPathSuffix( suffix );
61  checker.setControlName( mControlName );
62  checker.setMapSettings( mMapSettings );
63 
64  if ( !mRenderedImage.isNull() )
65  {
66  checker.setRenderedImage( mRenderedImage );
67  result = checker.compareImages( testName, mismatchCount, mRenderedImage );
68  }
69  else
70  {
71  result = checker.runTest( testName, mismatchCount );
72  mRenderedImage = checker.renderedImage();
73  }
74 
75  successful |= result;
76 
77  dartMeasurements << checker.dartMeasurements();
78 
79  mReport += checker.report();
80  }
81 
82  if ( !successful )
83  {
84  const auto constDartMeasurements = dartMeasurements;
85  for ( const QgsDartMeasurement &measurement : constDartMeasurements )
86  measurement.send();
87 
88  QgsDartMeasurement msg( QStringLiteral( "Image not accepted by test" ), QgsDartMeasurement::Text, "This may be caused because the test is supposed to fail or rendering inconsistencies."
89  "If this is a rendering inconsistency, please add another control image folder, add an anomaly image or increase the color tolerance." );
90  msg.send();
91  }
92 
93  return successful;
94 }
95 
97 {
98  QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
99  QString myControlImageDir = myDataDir + QDir::separator() + "control_images" +
100  QDir::separator() + mControlPathPrefix + QDir::separator() + mControlName + QDir::separator();
101  return myControlImageDir;
102 }
103 
104 //
105 // QgsLayoutChecker
106 //
107 
109 
110 QgsLayoutChecker::QgsLayoutChecker( const QString &testName, QgsLayout *layout )
111  : mTestName( testName )
112  , mLayout( layout )
113  , mSize( 1122, 794 )
114  , mDotsPerMeter( 96 / 25.4 * 1000 )
115 {
116  // Qt has some slight render inconsistencies on the whole image sometimes
117  setColorTolerance( 5 );
118 }
119 
120 bool QgsLayoutChecker::testLayout( QString &checkedReport, int page, int pixelDiff, bool createReferenceImage )
121 {
122 #ifdef QT_NO_PRINTER
123  return false;
124 #else
125  if ( !mLayout )
126  {
127  return false;
128  }
129 
130  setControlName( "expected_" + mTestName );
131 
132 
133  if ( createReferenceImage )
134  {
135  //fake mode to generate expected image
136  //assume 96 dpi
137 
138 
139  QImage _outputImage( mSize, QImage::Format_RGB32 );
140  _outputImage.setDotsPerMeterX( 96 / 25.4 * 1000 );
141  _outputImage.setDotsPerMeterY( 96 / 25.4 * 1000 );
142  QPainter _p( &_outputImage );
143  QgsLayoutExporter _exporter( mLayout );
144  _exporter.renderPage( &_p, page );
145  _p.end();
146 
147  if ( ! QDir( controlImagePath() ).exists() )
148  {
149  QDir().mkdir( controlImagePath() );
150  }
151  _outputImage.save( controlImagePath() + QDir::separator() + "expected_" + mTestName + ".png", "PNG" );
152  qDebug( ) << "Reference image saved to : " + controlImagePath() + QDir::separator() + "expected_" + mTestName + ".png";
153 
154  }
155 
156  QImage outputImage( mSize, QImage::Format_RGB32 );
157  outputImage.setDotsPerMeterX( mDotsPerMeter );
158  outputImage.setDotsPerMeterY( mDotsPerMeter );
159  drawBackground( &outputImage );
160  QPainter p( &outputImage );
161  QgsLayoutExporter exporter( mLayout );
162  exporter.renderPage( &p, page );
163  p.end();
164 
165  QString renderedFilePath = QDir::tempPath() + '/' + QFileInfo( mTestName ).baseName() + "_rendered.png";
166  outputImage.save( renderedFilePath, "PNG" );
167 
168  setRenderedImage( renderedFilePath );
169 
170  bool testResult = runTest( mTestName, pixelDiff );
171 
172  checkedReport += report();
173 
174  return testResult;
175 #endif // QT_NO_PRINTER
176 }
177 
178 
179 
void setColorTolerance(unsigned int colorTolerance)
Set tolerance for color components used by runTest() Default value is 0.
void enableDashBuffering(bool enable)
Call this to enable internal buffering of dash messages.
void setRenderedImage(const QString &imageFileName)
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...
void setMapSettings(const QgsMapSettings &mapSettings)
void setSizeTolerance(int xTolerance, int yTolerance)
Sets the largest allowable difference in size between the rendered and the expected image...
The QgsMapSettings class contains configuration for rendering of the map.
void setControlName(const QString &name)
Base directory name for the control image (with control image path suffixed) the path to the image wi...
QString controlImagePath() const
Returns the path to the control images.
void setControlPathPrefix(const QString &name)
Prefix where the control images are kept.
void setMapSettings(const QgsMapSettings &mapSettings)
Set the map settings to use to render the image.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
void setControlPathPrefix(const QString &prefix)
bool runTest(const QString &testName, unsigned int mismatchCount=0)
Test using renderer to generate the image to be compared.
bool compareImages(const QString &testName, unsigned int mismatchCount=0, const QString &renderedImageFile=QString())
Test using two arbitrary images (map renderer will not be used)
Handles rendering and exports of layouts to various formats.
QVector< QgsDartMeasurement > dartMeasurements() const
Gets access to buffered dash messages.
bool runTest(const QString &testName, unsigned int mismatchCount=0)
Test using renderer to generate the image to be compared.
void setColorTolerance(unsigned int colorTolerance)
Set tolerance for color components used by runTest() and compareImages().
void setControlPathSuffix(const QString &name)
static void drawBackground(QImage *image)
Draws a checkboard pattern for image backgrounds, so that opacity is visible without requiring a tran...
void setRenderedImage(const QString &renderedImagePath)
Set the path to the rendered image.
void setControlName(const QString &name)
Base directory name for the control image (with control image path suffixed) the path to the image wi...
void renderPage(QPainter *painter, int page) const
Renders a full page to a destination painter.