23 #include <QCryptographicHash>
31 mpMapRenderer( NULL ),
33 mRenderedImageFile(
"" ),
34 mExpectedImageFile(
"" ),
37 mElapsedTimeTarget( 0 ),
38 mControlPathPrefix(
"" )
45 QString myDataDir( TEST_DATA_DIR );
46 QString myControlImageDir = myDataDir + QDir::separator() +
"control_images" +
48 return myControlImageDir;
61 myImage.load( theImageFile );
62 QByteArray myByteArray;
63 QBuffer myBuffer( &myByteArray );
64 myImage.save( &myBuffer,
"PNG" );
65 QString myImageString = QString::fromUtf8( myByteArray.toBase64().data() );
66 QCryptographicHash myHash( QCryptographicHash::Md5 );
67 myHash.addData( myImageString.toUtf8() );
68 return myHash.result().toHex().constData();
75 QDir myDirectory = QDir( myControlImageDir );
77 QString myFilename =
"*";
78 myList = myDirectory.entryList( QStringList( myFilename ),
79 QDir::Files | QDir::NoSymLinks );
84 QString myImageHash =
imageToHash( theDiffImageFile );
87 for (
int i = 0; i < myList.size(); ++i )
89 QString myFile = myList.at( i );
91 "Checking if " + myFile +
" is a known anomaly.";
94 + QDir::separator() + myFile );
95 QString myHashMessage = QString(
96 "Checking if anomaly %1 (hash %2)<br>" )
98 .arg( myAnomalyHash );
99 myHashMessage += QString(
" matches %1 (hash %2)" )
100 .arg( theDiffImageFile )
103 QString myMeasureMessage =
"<DartMeasurement name=\"Anomaly check"
104 "\" type=\"text/text\">" + myHashMessage +
105 "</DartMeasurement>";
106 qDebug() << myMeasureMessage;
107 mReport +=
"<tr><td colspan=3>" + myHashMessage +
"</td></tr>";
108 if ( myImageHash == myAnomalyHash )
110 mReport +=
"<tr><td colspan=3>"
111 "Anomaly found! " + myFile;
116 mReport +=
"<tr><td colspan=3>"
117 "No anomaly found! ";
123 unsigned int theMismatchCount )
127 qDebug(
"QgsRenderChecker::runTest failed - Expected Image File not set." );
129 "<tr><td>Test Result:</td><td>Expected Result:</td></tr>\n"
130 "<tr><td>Nothing rendered</td>\n<td>Failed because Expected "
131 "Image File not set.</td></tr></table>\n";
138 mMatchTarget = myExpectedImage.width() * myExpectedImage.height();
142 QImage myImage( myExpectedImage.width(),
143 myExpectedImage.height(),
144 QImage::Format_RGB32 );
145 myImage.setDotsPerMeterX( myExpectedImage.dotsPerMeterX() );
146 myImage.setDotsPerMeterY( myExpectedImage.dotsPerMeterY() );
147 myImage.fill( qRgb( 152, 219, 249 ) );
148 QPainter myPainter( &myImage );
149 myPainter.setRenderHint( QPainter::Antialiasing );
151 myExpectedImage.width(),
152 myExpectedImage.height() ),
153 myExpectedImage.logicalDpiX() );
164 theTestName +
"_result.png";
169 QFile wldFile( QDir::tempPath() + QDir::separator() + theTestName +
"_result.wld" );
170 if ( wldFile.open( QIODevice::WriteOnly ) )
174 QTextStream stream( &wldFile );
175 stream << QString(
"%1\r\n0 \r\n0 \r\n%2\r\n%3\r\n%4\r\n" )
187 unsigned int theMismatchCount,
188 QString theRenderedImageFile )
192 qDebug(
"QgsRenderChecker::runTest failed - Expected Image (control) File not set." );
194 "<tr><td>Test Result:</td><td>Expected Result:</td></tr>\n"
195 "<tr><td>Nothing rendered</td>\n<td>Failed because Expected "
196 "Image File not set.</td></tr></table>\n";
199 if ( ! theRenderedImageFile.isEmpty() )
205 qDebug(
"QgsRenderChecker::runTest failed - Rendered Image File not set." );
207 "<tr><td>Test Result:</td><td>Expected Result:</td></tr>\n"
208 "<tr><td>Nothing rendered</td>\n<td>Failed because Rendered "
209 "Image File not set.</td></tr></table>\n";
217 QImage myDifferenceImage( myExpectedImage.width(),
218 myExpectedImage.height(),
219 QImage::Format_RGB32 );
220 QString myDiffImageFile = QDir::tempPath() + QDir::separator() +
222 theTestName +
"_result_diff.png";
223 myDifferenceImage.fill( qRgb( 152, 219, 249 ) );
228 mMatchTarget = myExpectedImage.width() * myExpectedImage.height();
229 unsigned int myPixelCount = myResultImage.width() * myResultImage.height();
234 mReport +=
"<tr><td colspan=2>";
235 mReport +=
"Test image and result image for " + theTestName +
"<br>"
236 "Expected size: " + QString::number( myExpectedImage.width() ).toLocal8Bit() +
"w x " +
237 QString::number( myExpectedImage.height() ).toLocal8Bit() +
"h (" +
238 QString::number(
mMatchTarget ).toLocal8Bit() +
" pixels)<br>"
239 "Actual size: " + QString::number( myResultImage.width() ).toLocal8Bit() +
"w x " +
240 QString::number( myResultImage.height() ).toLocal8Bit() +
"h (" +
241 QString::number( myPixelCount ).toLocal8Bit() +
" pixels)";
243 mReport +=
"<tr><td colspan = 2>\n";
245 "ms (0 indicates not specified)<br>";
251 if ( ! myExpectedImage.isNull() )
253 imgWidth = qMin( myExpectedImage.width(), imgWidth );
254 imgHeight = myExpectedImage.height() * imgWidth / myExpectedImage.width();
256 QString myImagesString =
"</td></tr>"
257 "<tr><td>Test Result:</td><td>Expected Result:</td><td>Difference (all blue is good, any red is bad)</td></tr>\n"
258 "<tr><td><img width=" + QString::number( imgWidth ) +
259 " height=" + QString::number( imgHeight ) +
262 "\"></td>\n<td><img width=" + QString::number( imgWidth ) +
263 " height=" + QString::number( imgHeight ) +
266 "\"></td>\n<td><img width=" + QString::number( imgWidth ) +
267 " height=" + QString::number( imgHeight ) +
270 "\"></td>\n</tr>\n</table>";
274 QString myDashMessage =
"<DartMeasurementFile name=\"Rendered Image " + theTestName +
"\""
276 "</DartMeasurementFile>\n"
277 "<DartMeasurementFile name=\"Expected Image " + theTestName +
"\" type=\"image/png\">" +
279 "<DartMeasurementFile name=\"Difference Image " + theTestName +
"\" type=\"image/png\">" +
280 myDiffImageFile +
"</DartMeasurementFile>\n";
281 qDebug( ) << myDashMessage;
287 qDebug(
"Expected size: %dw x %dh", myExpectedImage.width(), myExpectedImage.height() );
288 qDebug(
"Actual size: %dw x %dh", myResultImage.width(), myResultImage.height() );
292 qDebug(
"Test image and result image for %s are different - FAILING!", theTestName.toLocal8Bit().constData() );
293 mReport +=
"<tr><td colspan=3>";
294 mReport +=
"<font color=red>Expected image and result image for " + theTestName +
" are different dimensions - FAILING!</font>";
295 mReport +=
"</td></tr>";
296 mReport += myImagesString;
307 for (
int x = 0; x < myExpectedImage.width(); ++x )
309 for (
int y = 0; y < myExpectedImage.height(); ++y )
311 QRgb myExpectedPixel = myExpectedImage.pixel( x, y );
312 QRgb myActualPixel = myResultImage.pixel( x, y );
315 if ( myExpectedPixel != myActualPixel )
318 myDifferenceImage.setPixel( x, y, qRgb( 255, 0, 0 ) );
323 if ( qAbs( qRed( myExpectedPixel ) - qRed( myActualPixel ) ) > colorTolerance ||
324 qAbs( qGreen( myExpectedPixel ) - qGreen( myActualPixel ) ) > colorTolerance ||
325 qAbs( qBlue( myExpectedPixel ) - qBlue( myActualPixel ) ) > colorTolerance ||
326 qAbs( qAlpha( myExpectedPixel ) - qAlpha( myActualPixel ) ) > colorTolerance )
329 myDifferenceImage.setPixel( x, y, qRgb( 255, 0, 0 ) );
337 myDifferenceImage.save( myDiffImageFile );
347 mReport +=
"<tr><td colspan=3>" +
350 " pixels mismatched (allowed threshold: " +
351 QString::number( theMismatchCount ) +
352 ", allowed color component tolerance: " +
359 myDashMessage =
"<DartMeasurement name=\"Mismatch Count "
360 "\" type=\"numeric/integer\">" +
363 "</DartMeasurement>";
364 qDebug( ) << myDashMessage;
368 if ( myAnomalyMatchFlag )
370 mReport +=
"<tr><td colspan=3>"
371 "Difference image matched a known anomaly - passing test! "
377 QString myMessage =
"Difference image did not match any known anomaly.";
378 mReport +=
"<tr><td colspan=3>"
380 QString myMeasureMessage =
"<DartMeasurement name=\"No Anomalies Match"
381 "\" type=\"text/text\">" + myMessage +
382 " If you feel the difference image should be considered an anomaly "
383 "you can do something like this\n"
384 "cp " + myDiffImageFile +
" ../tests/testdata/control_images/" + theTestName +
385 "/<imagename>.{wld,png}"
386 "</DartMeasurement>";
387 qDebug() << myMeasureMessage;
392 mReport +=
"<tr><td colspan = 3>\n";
393 mReport +=
"Test image and result image for " + theTestName +
" are matched<br>";
398 qDebug(
"Test failed because render step took too long" );
399 mReport +=
"<tr><td colspan = 3>\n";
400 mReport +=
"<font color=red>Test failed because render step took too long</font>";
413 mReport +=
"<tr><td colspan = 3>\n";
414 mReport +=
"<font color=red>Test image and result image for " + theTestName +
" are mismatched</font><br>";