Use QgsRenderChecker to compare png images when comparing processing result

directories
This commit is contained in:
Nyall Dawson 2021-02-05 16:18:02 +10:00
parent 1af083415a
commit 973682baa3
4 changed files with 35 additions and 7 deletions

View File

@ -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 );

View File

@ -35,7 +35,8 @@ from qgis.core import (
QgsFeatureRequest,
QgsCoordinateReferenceSystem,
NULL,
QgsVectorLayer
QgsVectorLayer,
QgsRenderChecker
)
import unittest
@ -226,21 +227,28 @@ class TestCase(_TestCase):
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"

View File

@ -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;
@ -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() )
{
@ -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 );
@ -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 ) );
@ -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
@ -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>";

View File

@ -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