23 #include <QCryptographicHash>
30 mExpectedImageFile(
"" ),
31 mRenderedImageFile(
"" ),
35 mElapsedTimeTarget( 0 ),
36 mpMapRenderer( NULL ),
37 mControlPathPrefix(
"" )
44 QString myDataDir( TEST_DATA_DIR );
45 QString myControlImageDir = myDataDir + QDir::separator() +
"control_images" +
47 return myControlImageDir;
60 myImage.load( theImageFile );
61 QByteArray myByteArray;
62 QBuffer myBuffer( &myByteArray );
63 myImage.save( &myBuffer,
"PNG" );
64 QString myImageString = QString::fromUtf8( myByteArray.toBase64().data() );
65 QCryptographicHash myHash( QCryptographicHash::Md5 );
66 myHash.addData( myImageString.toUtf8() );
67 return myHash.result().toHex().constData();
74 QDir myDirectory = QDir( myControlImageDir );
76 QString myFilename =
"*";
77 myList = myDirectory.entryList( QStringList( myFilename ),
78 QDir::Files | QDir::NoSymLinks );
83 QString myImageHash =
imageToHash( theDiffImageFile );
86 for (
int i = 0; i < myList.size(); ++i )
88 QString myFile = myList.at( i );
90 "Checking if " + myFile +
" is a known anomaly.";
93 + QDir::separator() + myFile );
94 QString myHashMessage = QString(
95 "Checking if anomaly %1 (hash %2)" )
97 .arg( myAnomalyHash );
98 myHashMessage += QString(
" matches %1 (hash %2)" )
99 .arg( theDiffImageFile )
102 QString myMeasureMessage =
"<DartMeasurement name=\"Anomaly check"
103 "\" type=\"text/text\">" + myHashMessage +
104 "</DartMeasurement>";
105 qDebug() << myMeasureMessage;
106 mReport +=
"<tr><td colspan=3>" + myHashMessage +
"</td></tr>";
107 if ( myImageHash == myAnomalyHash )
109 mReport +=
"<tr><td colspan=3>"
110 "Anomaly found! " + myFile;
115 mReport +=
"<tr><td colspan=3>"
116 "No anomaly found! ";
122 unsigned int theMismatchCount )
126 qDebug(
"QgsRenderChecker::runTest failed - Expected Image File not set." );
128 "<tr><td>Test Result:</td><td>Expected Result:</td></tr>\n"
129 "<tr><td>Nothing rendered</td>\n<td>Failed because Expected "
130 "Image File not set.</td></tr></table>\n";
137 mMatchTarget = myExpectedImage.width() * myExpectedImage.height();
141 QImage myImage( myExpectedImage.width(),
142 myExpectedImage.height(),
143 QImage::Format_RGB32 );
144 myImage.setDotsPerMeterX( myExpectedImage.dotsPerMeterX() );
145 myImage.setDotsPerMeterY( myExpectedImage.dotsPerMeterY() );
146 myImage.fill( qRgb( 152, 219, 249 ) );
147 QPainter myPainter( &myImage );
148 myPainter.setRenderHint( QPainter::Antialiasing );
150 myExpectedImage.width(),
151 myExpectedImage.height() ),
152 myExpectedImage.logicalDpiX() );
163 theTestName +
"_result.png";
168 QFile wldFile( QDir::tempPath() + QDir::separator() + theTestName +
"_result.wld" );
169 if ( wldFile.open( QIODevice::WriteOnly ) )
173 QTextStream stream( &wldFile );
174 stream << QString(
"%1\r\n0 \r\n0 \r\n%2\r\n%3\r\n%4\r\n" )
186 unsigned int theMismatchCount,
187 QString theRenderedImageFile )
191 qDebug(
"QgsRenderChecker::runTest failed - Expected Image (control) File not set." );
193 "<tr><td>Test Result:</td><td>Expected Result:</td></tr>\n"
194 "<tr><td>Nothing rendered</td>\n<td>Failed because Expected "
195 "Image File not set.</td></tr></table>\n";
198 if ( ! theRenderedImageFile.isEmpty() )
204 qDebug(
"QgsRenderChecker::runTest failed - Rendered Image File not set." );
206 "<tr><td>Test Result:</td><td>Expected Result:</td></tr>\n"
207 "<tr><td>Nothing rendered</td>\n<td>Failed because Expected "
208 "Image File not set.</td></tr></table>\n";
216 QImage myDifferenceImage( myExpectedImage.width(),
217 myExpectedImage.height(),
218 QImage::Format_RGB32 );
219 QString myDiffImageFile = QDir::tempPath() + QDir::separator() +
221 theTestName +
"_result_diff.png";
222 myDifferenceImage.fill( qRgb( 152, 219, 249 ) );
227 mMatchTarget = myExpectedImage.width() * myExpectedImage.height();
228 unsigned int myPixelCount = myResultImage.width() * myResultImage.height();
233 mReport +=
"<tr><td colspan=2>";
234 mReport +=
"Test image and result image for " + theTestName +
"<br>"
235 "Expected size: " + QString::number( myExpectedImage.width() ).toLocal8Bit() +
"w x " +
236 QString::number( myExpectedImage.width() ).toLocal8Bit() +
"h (" +
237 QString::number(
mMatchTarget ).toLocal8Bit() +
" pixels)<br>"
238 "Actual size: " + QString::number( myResultImage.width() ).toLocal8Bit() +
"w x " +
239 QString::number( myResultImage.width() ).toLocal8Bit() +
"h (" +
240 QString::number( myPixelCount ).toLocal8Bit() +
" pixels)";
242 mReport +=
"<tr><td colspan = 2>\n";
244 "ms (0 indicates not specified)<br>";
246 QString myImagesString =
"</td></tr>"
247 "<tr><td>Test Result:</td><td>Expected Result:</td><td>Difference (all blue is good, any red is bad)</td></tr>\n"
248 "<tr><td><img src=\"file://" +
250 "\"></td>\n<td><img src=\"file://" +
252 "\"></td><td><img src=\"file://" +
254 "\"></td>\n</tr>\n</table>";
258 QString myDashMessage =
"<DartMeasurementFile name=\"Rendered Image " + theTestName +
"\""
260 "</DartMeasurementFile>\n"
261 "<DartMeasurementFile name=\"Expected Image " + theTestName +
"\" type=\"image/png\">" +
263 "<DartMeasurementFile name=\"Difference Image " + theTestName +
"\" type=\"image/png\">" +
264 myDiffImageFile +
"</DartMeasurementFile>\n";
265 qDebug( ) << myDashMessage;
271 qDebug(
"Expected size: %dw x %dh", myExpectedImage.width(), myExpectedImage.height() );
272 qDebug(
"Actual size: %dw x %dh", myResultImage.width(), myResultImage.height() );
276 qDebug(
"Test image and result image for %s are different - FAILING!", theTestName.toLocal8Bit().constData() );
277 mReport +=
"<tr><td colspan=3>";
278 mReport +=
"<font color=red>Expected image and result image for " + theTestName +
" are different dimensions - FAILING!</font>";
279 mReport +=
"</td></tr>";
280 mReport += myImagesString;
290 for (
int x = 0; x < myExpectedImage.width(); ++x )
292 for (
int y = 0; y < myExpectedImage.height(); ++y )
294 QRgb myExpectedPixel = myExpectedImage.pixel( x, y );
295 QRgb myActualPixel = myResultImage.pixel( x, y );
296 if ( myExpectedPixel != myActualPixel )
299 myDifferenceImage.setPixel( x, y, qRgb( 255, 0, 0 ) );
306 myDifferenceImage.save( myDiffImageFile );
316 mReport +=
"<tr><td colspan=3>" +
319 " pixels mismatched (allowed threshold: " +
320 QString::number( theMismatchCount ) +
")";
326 myDashMessage =
"<DartMeasurement name=\"Mismatch Count "
327 "\" type=\"numeric/integer\">" +
330 "</DartMeasurement>";
331 qDebug( ) << myDashMessage;
335 if ( myAnomalyMatchFlag )
337 mReport +=
"<tr><td colspan=3>"
338 "Difference image matched a known anomaly - passing test! "
344 QString myMessage =
"Difference image did not match any known anomaly.";
345 mReport +=
"<tr><td colspan=3>"
347 QString myMeasureMessage =
"<DartMeasurement name=\"No Anomalies Match"
348 "\" type=\"text/text\">" + myMessage +
349 " If you feel the difference image should be considered an anomaly "
350 "you can do something like this\n"
351 "cp " + myDiffImageFile +
" ../tests/testdata/control_images/" + theTestName +
352 "/<imagename>.{wld,png}"
353 "</DartMeasurement>";
354 qDebug() << myMeasureMessage;
359 mReport +=
"<tr><td colspan = 3>\n";
360 mReport +=
"Test image and result image for " + theTestName +
" are matched<br>";
365 qDebug(
"Test failed because render step took too long" );
366 mReport +=
"<tr><td colspan = 3>\n";
367 mReport +=
"<font color=red>Test failed because render step took too long</font>";
380 mReport +=
"<tr><td colspan = 3>\n";
381 mReport +=
"<font color=red>Test image and result image for " + theTestName +
" are mismatched</font><br>";