Skip to content

Commit

Permalink
Use QgsRenderChecker to compare png images when comparing processing …
Browse files Browse the repository at this point in the history
…result

directories
  • Loading branch information
nyalldawson committed Feb 8, 2021
1 parent 1af0834 commit 973682b
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 7 deletions.
7 changes: 7 additions & 0 deletions python/core/auto_generated/qgsrenderchecker.sip.in
Expand Up @@ -165,6 +165,13 @@ Test using two arbitrary images (map renderer will not be used)
for that by providing a tolerance.
:param renderedImageFile: to optionally override the output filename
\note: make sure to call setExpectedImage and setRenderedImage first.
%End

bool compareImages( const QString &testName, const QString &referenceImageFile, const QString &renderedImageFile, unsigned int mismatchCount = 0 );
%Docstring
Test using two arbitrary images at the specified paths for equality.

.. versionadded:: 3.18
%End

bool isKnownAnomaly( const QString &diffImageFile );
Expand Down
12 changes: 10 additions & 2 deletions python/testing/__init__.py
Expand Up @@ -35,7 +35,8 @@
QgsFeatureRequest,
QgsCoordinateReferenceSystem,
NULL,
QgsVectorLayer
QgsVectorLayer,
QgsRenderChecker
)

import unittest
Expand Down Expand Up @@ -226,21 +227,28 @@ def assertDirectoryEqual(self, dirpath_expected: str, dirpath_result: str):

contents_result = list(path_result.iterdir())
contents_expected = list(path_expected.iterdir())
contents_expected = [p for p in contents_expected if p.suffix != '.png' or not p.stem.endswith('_mask')]
self.assertCountEqual([p.name if p.is_file() else p.stem for p in contents_expected], [p.name if p.is_file() else p.stem for p in contents_result], f'Directory contents mismatch in {dirpath_expected} vs {dirpath_result}')

# compare file contents
for expected_file_path in path_expected.iterdir():
for expected_file_path in contents_expected:
if expected_file_path.is_dir():
continue

result_file_path = path_result / expected_file_path.name

if expected_file_path.suffix == '.pbf':
# vector layer, use assertLayersEqual
layer_expected = QgsVectorLayer(str(expected_file_path), 'Expected')
self.assertTrue(layer_expected.isValid())
layer_result = QgsVectorLayer(str(result_file_path), 'Result')
self.assertTrue(layer_result.isValid())
self.assertLayersEqual(layer_expected, layer_result)
elif expected_file_path.suffix == '.png':
# image file, use QgsRenderChecker
checker = QgsRenderChecker()
res = checker.compareImages(expected_file_path.stem, expected_file_path.as_posix(), result_file_path.as_posix())
self.assertTrue(res)
else:
assert False, f"Don't know how to compare {expected_file_path.suffix} files"

Expand Down
16 changes: 11 additions & 5 deletions src/core/qgsrenderchecker.cpp
Expand Up @@ -251,6 +251,12 @@ bool QgsRenderChecker::compareImages( const QString &testName,
"Image File not set.</td></tr></table>\n";
return false;
}

return compareImages( testName, mExpectedImageFile, renderedImageFile, mismatchCount );
}

bool QgsRenderChecker::compareImages( const QString &testName, const QString &referenceImageFile, const QString &renderedImageFile, unsigned int mismatchCount )
{
if ( ! renderedImageFile.isEmpty() )
{
mRenderedImageFile = renderedImageFile;
Expand All @@ -272,7 +278,7 @@ bool QgsRenderChecker::compareImages( const QString &testName,
//
// Load /create the images
//
QImage myExpectedImage( mExpectedImageFile );
QImage myExpectedImage( referenceImageFile );
QImage myResultImage( mRenderedImageFile );
if ( myResultImage.isNull() )
{
Expand All @@ -290,7 +296,7 @@ bool QgsRenderChecker::compareImages( const QString &testName,
myDifferenceImage.fill( qRgb( 152, 219, 249 ) );

//check for mask
QString maskImagePath = mExpectedImageFile;
QString maskImagePath = referenceImageFile;
maskImagePath.chop( 4 ); //remove .png extension
maskImagePath += QLatin1String( "_mask.png" );
const QImage maskImage( maskImagePath );
Expand Down Expand Up @@ -343,7 +349,7 @@ bool QgsRenderChecker::compareImages( const QString &testName,
.arg( testName,
myDiffImageFile,
mRenderedImageFile,
mExpectedImageFile )
referenceImageFile )
.arg( imgWidth ).arg( imgHeight )
.arg( QUuid::createUuid().toString().mid( 1, 6 ) );

Expand All @@ -356,7 +362,7 @@ bool QgsRenderChecker::compareImages( const QString &testName,
// To get the images into CDash
//
emitDashMessage( "Rendered Image " + testName + prefix, QgsDartMeasurement::ImagePng, mRenderedImageFile );
emitDashMessage( "Expected Image " + testName + prefix, QgsDartMeasurement::ImagePng, mExpectedImageFile );
emitDashMessage( "Expected Image " + testName + prefix, QgsDartMeasurement::ImagePng, referenceImageFile );

//
// Put the same info to debug too
Expand Down Expand Up @@ -524,7 +530,7 @@ bool QgsRenderChecker::compareImages( const QString &testName,
"you can do something like this\n"
"cp '" + myDiffImageFile + "' " + controlImagePath() + mControlName +
"/\nIf it should be included in the mask run\n"
"scripts/generate_test_mask_image.py '" + mExpectedImageFile + "' '" + mRenderedImageFile + "'\n" );
"scripts/generate_test_mask_image.py '" + referenceImageFile + "' '" + mRenderedImageFile + "'\n" );

mReport += QLatin1String( "<tr><td colspan = 3>\n" );
mReport += "<font color=red>Test image and result image for " + testName + " are mismatched</font><br>";
Expand Down
7 changes: 7 additions & 0 deletions src/core/qgsrenderchecker.h
Expand Up @@ -170,6 +170,13 @@ class CORE_EXPORT QgsRenderChecker
*/
bool compareImages( const QString &testName, unsigned int mismatchCount = 0, const QString &renderedImageFile = QString() );

/**
* Test using two arbitrary images at the specified paths for equality.
*
* \since QGIS 3.18
*/
bool compareImages( const QString &testName, const QString &referenceImageFile, const QString &renderedImageFile, unsigned int mismatchCount = 0 );

/**
* Gets a list of all the anomalies. An anomaly is a rendered difference
* file where there is some red pixel content (indicating a render check
Expand Down

0 comments on commit 973682b

Please sign in to comment.