diff options
author | 2012-05-22 13:45:35 +0000 | |
---|---|---|
committer | 2012-05-22 13:45:35 +0000 | |
commit | 46256ea736868e6df1a6102672fc4bb41f99d29d (patch) | |
tree | 5e21b96965653e885a24bd3ac01c9213e58fc75b | |
parent | 21ddae75b20c2108815a3142507bc040dc53f385 (diff) |
Add to skdiff: test images for bitwise equality before testing for pixel-wise equality
- we now check for bitwise equality of files before bothering with pixel
comparisons (this will help with formats for which we don't have good
decoders, like PDF)
- unparsable files are now reported as differing, unless they are bitwise equal
(before, they were always reported as matching!)
- "largest area mismatch" is now based on same-size image pairs only;
previously, if any image pairs had mismatching size, it was 100%
- removed repetitive "image size mismatch, so no diff to display" messages
- changed format of leftmost table cells to be more readable
BUG=http://code.google.com/p/skia/issues/detail?id=473
Review URL: https://codereview.appspot.com/6208089
git-svn-id: http://skia.googlecode.com/svn/trunk@4027 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | tools/skdiff_main.cpp | 249 | ||||
-rw-r--r-- | tools/tests/skdiff/test1/output-expected/index.html | 20 | ||||
-rw-r--r-- | tools/tests/skdiff/test1/output-expected/stdout | 7 | ||||
-rw-r--r-- | tools/tests/skdiff/test2/output-expected/stdout | 7 |
4 files changed, 182 insertions, 101 deletions
diff --git a/tools/skdiff_main.cpp b/tools/skdiff_main.cpp index 8a2ba2d560..48e3aedfa4 100644 --- a/tools/skdiff_main.cpp +++ b/tools/skdiff_main.cpp @@ -6,6 +6,7 @@ * found in the LICENSE file. */ #include "SkColorPriv.h" +#include "SkData.h" #include "SkImageDecoder.h" #include "SkImageEncoder.h" #include "SkOSFile.h" @@ -37,7 +38,6 @@ #endif // Result of comparison for each pair of files. -// TODO: we don't actually use all of these yet. enum Result { kEqualBits, // both files in the pair contain exactly the same bits kEqualPixels, // not bitwise equal, but their pixels are exactly the same @@ -159,37 +159,48 @@ struct DiffSummary { } void add (DiffRecord* drp) { - // Maintain current (and, I think, incorrect) skdiff behavior: - // If we were unable to parse either file in the pair as an image, - // treat them as matching. - // TODO: Remove this logic and change the results for the better. - if (kUnknown == drp->fResult) { - drp->fResult = kEqualPixels; - } + uint32_t mismatchValue; switch (drp->fResult) { - case kEqualPixels: + case kEqualBits: fNumMatches++; break; - case kBaseMissing: - fBaseMissing.push(new SkString(drp->fFilename)); - fNumMismatches++; + case kEqualPixels: + fNumMatches++; break; - case kComparisonMissing: - fComparisonMissing.push(new SkString(drp->fFilename)); + case kDifferentSizes: fNumMismatches++; + drp->fFractionDifference = 2.0;// sort as if 200% of pixels differed break; - default: + case kDifferentPixels: fNumMismatches++; if (drp->fFractionDifference * 100 > fMaxMismatchPercent) { fMaxMismatchPercent = drp->fFractionDifference * 100; } - uint32_t value = MAX3(drp->fMaxMismatchR, drp->fMaxMismatchG, - drp->fMaxMismatchB); - if (value > fMaxMismatchV) { - fMaxMismatchV = value; + mismatchValue = MAX3(drp->fMaxMismatchR, drp->fMaxMismatchG, + drp->fMaxMismatchB); + if (mismatchValue > fMaxMismatchV) { + fMaxMismatchV = mismatchValue; } break; + case kDifferentOther: + fNumMismatches++; + drp->fFractionDifference = 3.0;// sort as if 300% of pixels differed + break; + case kBaseMissing: + fNumMismatches++; + fBaseMissing.push(new SkString(drp->fFilename)); + break; + case kComparisonMissing: + fNumMismatches++; + fComparisonMissing.push(new SkString(drp->fFilename)); + break; + case kUnknown: + SkDEBUGFAIL("adding uncategorized DiffRecord"); + break; + default: + SkDEBUGFAIL("adding DiffRecord with unhandled fResult value"); + break; } } }; @@ -269,24 +280,59 @@ static void expand_and_copy (int width, int height, SkBitmap** dest) { *dest = temp; } -static bool get_bitmaps (DiffRecord* diffRecord) { - SkFILEStream compareStream(diffRecord->fComparisonPath.c_str()); - if (!compareStream.isValid()) { - SkDebugf("WARNING: couldn't open comparison file <%s>\n", - diffRecord->fComparisonPath.c_str()); +/// Returns true if the two buffers passed in are both non-NULL, and include +/// exactly the same byte values (and identical lengths). +static bool are_buffers_equal(SkData* skdata1, SkData* skdata2) { + if ((NULL == skdata1) || (NULL == skdata2)) { return false; } - - SkFILEStream baseStream(diffRecord->fBasePath.c_str()); - if (!baseStream.isValid()) { - SkDebugf("ERROR: couldn't open base file <%s>\n", - diffRecord->fBasePath.c_str()); + if (skdata1->size() != skdata2->size()) { return false; } + return (0 == memcmp(skdata1->data(), skdata2->data(), skdata1->size())); +} + +/// Reads the file at the given path and returns its complete contents as an +/// SkData object (or returns NULL on error). +static SkData* read_file(const char* file_path) { + SkFILEStream fileStream(file_path); + if (!fileStream.isValid()) { + SkDebugf("WARNING: could not open file <%s> for reading\n", file_path); + return NULL; + } + size_t bytesInFile = fileStream.getLength(); + size_t bytesLeftToRead = bytesInFile; + + void* bufferStart = sk_malloc_throw(bytesInFile); + char* bufferPointer = (char*)bufferStart; + while (bytesLeftToRead > 0) { + size_t bytesReadThisTime = fileStream.read( + bufferPointer, bytesLeftToRead); + if (0 == bytesReadThisTime) { + SkDebugf("WARNING: error reading from <%s>\n", file_path); + sk_free(bufferStart); + return NULL; + } + bytesLeftToRead -= bytesReadThisTime; + bufferPointer += bytesReadThisTime; + } + return SkData::NewFromMalloc(bufferStart, bytesInFile); +} + +/// Decodes binary contents of baseFile and comparisonFile into +/// diffRecord->fBaseBitmap and diffRecord->fComparisonBitmap. +/// Returns true if that succeeds. +static bool get_bitmaps (SkData* baseFileContents, + SkData* comparisonFileContents, + DiffRecord* diffRecord) { + SkMemoryStream compareStream(comparisonFileContents->data(), + comparisonFileContents->size()); + SkMemoryStream baseStream(baseFileContents->data(), + baseFileContents->size()); SkImageDecoder* codec = SkImageDecoder::Factory(&baseStream); if (NULL == codec) { - SkDebugf("ERROR: no codec found for <%s>\n", + SkDebugf("ERROR: no codec found for basePath <%s>\n", diffRecord->fBasePath.c_str()); return false; } @@ -299,7 +345,7 @@ static bool get_bitmaps (DiffRecord* diffRecord) { if (!codec->decode(&baseStream, diffRecord->fBaseBitmap, SkBitmap::kARGB_8888_Config, SkImageDecoder::kDecodePixels_Mode)) { - SkDebugf("ERROR: codec failed for <%s>\n", + SkDebugf("ERROR: codec failed for basePath <%s>\n", diffRecord->fBasePath.c_str()); return false; } @@ -310,7 +356,7 @@ static bool get_bitmaps (DiffRecord* diffRecord) { if (!codec->decode(&compareStream, diffRecord->fComparisonBitmap, SkBitmap::kARGB_8888_Config, SkImageDecoder::kDecodePixels_Mode)) { - SkDebugf("ERROR: codec failed for <%s>\n", + SkDebugf("ERROR: codec failed for comparisonPath <%s>\n", diffRecord->fComparisonPath.c_str()); return false; } @@ -411,7 +457,6 @@ static void compute_diff(DiffRecord* dr, if (w != dr->fBaseWidth || h != dr->fBaseHeight) { dr->fResult = kDifferentSizes; - dr->fFractionDifference = 1; // for sorting the diffs later return; } // Accumulate fractionally different pixels, then divide out @@ -621,18 +666,41 @@ static void create_diff_images (DiffMetricProc dmp, kBaseMissing); ++j; } else { - // let's diff! + // Found the same filename in both baseDir and comparisonDir. drp = new DiffRecord(*baseFiles[i], basePath, comparisonPath); - - if (get_bitmaps(drp)) { - create_and_write_diff_image(drp, dmp, colorThreshold, - outputDir, *baseFiles[i]); + SkASSERT(kUnknown == drp->fResult); + + SkData* baseFileBits; + SkData* comparisonFileBits; + if (NULL == (baseFileBits = read_file(basePath.c_str()))) { + SkDebugf("WARNING: couldn't read base file <%s>\n", + basePath.c_str()); + drp->fResult = kBaseMissing; + } else if (NULL == (comparisonFileBits = read_file( + comparisonPath.c_str()))) { + SkDebugf("WARNING: couldn't read comparison file <%s>\n", + comparisonPath.c_str()); + drp->fResult = kComparisonMissing; + } else { + if (are_buffers_equal(baseFileBits, comparisonFileBits)) { + drp->fResult = kEqualBits; + } else if (get_bitmaps(baseFileBits, comparisonFileBits, drp)) { + create_and_write_diff_image(drp, dmp, colorThreshold, + outputDir, *baseFiles[i]); + } else { + drp->fResult = kDifferentOther; + } + } + if (baseFileBits) { + baseFileBits->unref(); + } + if (comparisonFileBits) { + comparisonFileBits->unref(); } - ++i; ++j; } - + SkASSERT(kUnknown != drp->fResult); differences->push(drp); summary->add(drp); } @@ -745,44 +813,56 @@ static void print_pixel_count (SkFILEWStream* stream, static void print_label_cell (SkFILEWStream* stream, const DiffRecord& diff) { - stream->writeText("<td>"); + char metricBuf [20]; + + stream->writeText("<td><b>"); stream->writeText(diff.fFilename.c_str()); - stream->writeText("<br>"); + stream->writeText("</b><br>"); switch (diff.fResult) { - case kBaseMissing: - // fall through - case kComparisonMissing: - stream->writeText("</td>"); + case kEqualBits: + SkDEBUGFAIL("should not encounter DiffRecord with kEqualBits here"); + return; + case kEqualPixels: + SkDEBUGFAIL("should not encounter DiffRecord with kEqualPixels here"); return; case kDifferentSizes: - stream->writeText("Image sizes differ"); + stream->writeText("Image sizes differ</td>"); + return; + case kDifferentPixels: + sprintf(metricBuf, "%12.4f%%", 100 * diff.fFractionDifference); + stream->writeText(metricBuf); + stream->writeText(" of pixels differ"); + stream->writeText("\n ("); + sprintf(metricBuf, "%12.4f%%", 100 * diff.fWeightedFraction); + stream->writeText(metricBuf); + stream->writeText(" weighted)"); + // Write the actual number of pixels that differ if it's < 1% + if (diff.fFractionDifference < 0.01) { + print_pixel_count(stream, diff); + } + stream->writeText("<br>Average color mismatch "); + stream->writeDecAsText(static_cast<int>(MAX3(diff.fAverageMismatchR, + diff.fAverageMismatchG, + diff.fAverageMismatchB))); + stream->writeText("<br>Max color mismatch "); + stream->writeDecAsText(MAX3(diff.fMaxMismatchR, + diff.fMaxMismatchG, + diff.fMaxMismatchB)); stream->writeText("</td>"); + break; + case kDifferentOther: + stream->writeText("Files differ; unable to parse one or both files</td>"); + return; + case kBaseMissing: + stream->writeText("Missing from baseDir</td>"); + return; + case kComparisonMissing: + stream->writeText("Missing from comparisonDir</td>"); return; default: - break; // continue in this function - } - - char metricBuf [20]; - sprintf(metricBuf, "%12.4f%%", 100 * diff.fFractionDifference); - stream->writeText(metricBuf); - stream->writeText(" of pixels differ"); - stream->writeText("\n ("); - sprintf(metricBuf, "%12.4f%%", 100 * diff.fWeightedFraction); - stream->writeText(metricBuf); - stream->writeText(" weighted)"); - // Write the actual number of pixels that differ if it's < 1% - if (diff.fFractionDifference < 0.01) { - print_pixel_count(stream, diff); + SkDEBUGFAIL("encountered DiffRecord with unknown result type"); + return; } - stream->writeText("<br>Average color mismatch "); - stream->writeDecAsText(static_cast<int>(MAX3(diff.fAverageMismatchR, - diff.fAverageMismatchG, - diff.fAverageMismatchB))); - stream->writeText("<br>Max color mismatch "); - stream->writeDecAsText(MAX3(diff.fMaxMismatchR, - diff.fMaxMismatchG, - diff.fMaxMismatchB)); - stream->writeText("</td>"); } static void print_image_cell (SkFILEWStream* stream, @@ -878,15 +958,23 @@ static void print_diff_page (const int matchCount, DiffRecord* diff = differences[i]; switch (diff->fResult) { + // Cases in which there is no diff to report. + case kEqualBits: case kEqualPixels: continue; + // Cases in which we want a detailed pixel diff. + case kDifferentPixels: + break; + // Cases in which the files differed, but we can't display the diff. + case kDifferentSizes: + case kDifferentOther: case kBaseMissing: - // fall through case kComparisonMissing: print_diff_with_missing_file(&outputStream, *diff, relativePath); continue; default: - break; + SkDEBUGFAIL("encountered DiffRecord with unknown result type"); + continue; } if (!diff->fBasePath.startsWith(PATH_DIV_STR)) { @@ -899,19 +987,10 @@ static void print_diff_page (const int matchCount, int height = compute_image_height(diff->fBaseHeight, diff->fBaseWidth); outputStream.writeText("<tr>\n"); print_label_cell(&outputStream, *diff); - switch (diff->fResult) { - case kDifferentSizes: - print_text_cell(&outputStream, - "[image size mismatch, so no diff to display]"); - print_text_cell(&outputStream, - "[image size mismatch, so no diff to display]"); - break; - default: - print_image_cell(&outputStream, - filename_to_white_filename(diff->fFilename), height); - print_image_cell(&outputStream, - filename_to_diff_filename(diff->fFilename), height); - } + print_image_cell(&outputStream, + filename_to_white_filename(diff->fFilename), height); + print_image_cell(&outputStream, + filename_to_diff_filename(diff->fFilename), height); print_image_cell(&outputStream, diff->fBasePath, height); print_image_cell(&outputStream, diff->fComparisonPath, height); outputStream.writeText("</tr>\n"); diff --git a/tools/tests/skdiff/test1/output-expected/index.html b/tools/tests/skdiff/test1/output-expected/index.html index 62ab69973f..2cef548d7d 100644 --- a/tools/tests/skdiff/test1/output-expected/index.html +++ b/tools/tests/skdiff/test1/output-expected/index.html @@ -1,30 +1,32 @@ <html> <body> <table> -<tr><th>4 of 12 images matched exactly.<br></th> +<tr><th>3 of 12 images matched exactly.<br></th> <th>every different pixel shown in white</th> <th>color difference at each pixel</th> <th>tools/tests/skdiff/baseDir/</th> <th>tools/tests/skdiff/comparisonDir/</th> </tr> <tr> -<td>slightly-different-sizes.png<br>Image sizes differ</td><td align=center>[image size mismatch, so no diff to display]</td><td align=center>[image size mismatch, so no diff to display]</td><td><a href="../../../../../tools/tests/skdiff/baseDir/slightly-different-sizes.png"><img src="../../../../../tools/tests/skdiff/baseDir/slightly-different-sizes.png" height="240px"></a></td><td><a href="../../../../../tools/tests/skdiff/comparisonDir/slightly-different-sizes.png"><img src="../../../../../tools/tests/skdiff/comparisonDir/slightly-different-sizes.png" height="240px"></a></td></tr> +<td><b>different-bits-unknown-format.xyz</b><br>Files differ; unable to parse one or both files</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr> <tr> -<td>very-different-sizes.png<br>Image sizes differ</td><td align=center>[image size mismatch, so no diff to display]</td><td align=center>[image size mismatch, so no diff to display]</td><td><a href="../../../../../tools/tests/skdiff/baseDir/very-different-sizes.png"><img src="../../../../../tools/tests/skdiff/baseDir/very-different-sizes.png" height="240px"></a></td><td><a href="../../../../../tools/tests/skdiff/comparisonDir/very-different-sizes.png"><img src="../../../../../tools/tests/skdiff/comparisonDir/very-different-sizes.png" height="240px"></a></td></tr> +<td><b>slightly-different-sizes.png</b><br>Image sizes differ</td><td>N/A</td><td>N/A</td><td><a href="../../../../../tools/tests/skdiff/baseDir/slightly-different-sizes.png"><img src="../../../../../tools/tests/skdiff/baseDir/slightly-different-sizes.png" height="240px"></a></td><td><a href="../../../../../tools/tests/skdiff/comparisonDir/slightly-different-sizes.png"><img src="../../../../../tools/tests/skdiff/comparisonDir/slightly-different-sizes.png" height="240px"></a></td></tr> <tr> -<td>very-different-pixels-same-size.png<br> 97.9926% of pixels differ +<td><b>very-different-sizes.png</b><br>Image sizes differ</td><td>N/A</td><td>N/A</td><td><a href="../../../../../tools/tests/skdiff/baseDir/very-different-sizes.png"><img src="../../../../../tools/tests/skdiff/baseDir/very-different-sizes.png" height="240px"></a></td><td><a href="../../../../../tools/tests/skdiff/comparisonDir/very-different-sizes.png"><img src="../../../../../tools/tests/skdiff/comparisonDir/very-different-sizes.png" height="128px"></a></td></tr> +<tr> +<td><b>very-different-pixels-same-size.png</b><br> 97.9926% of pixels differ ( 42.8911% weighted)<br>Average color mismatch 89<br>Max color mismatch 239</td><td><a href="very-different-pixels-same-size-white.png"><img src="very-different-pixels-same-size-white.png" height="240px"></a></td><td><a href="very-different-pixels-same-size-diff.png"><img src="very-different-pixels-same-size-diff.png" height="240px"></a></td><td><a href="../../../../../tools/tests/skdiff/baseDir/very-different-pixels-same-size.png"><img src="../../../../../tools/tests/skdiff/baseDir/very-different-pixels-same-size.png" height="240px"></a></td><td><a href="../../../../../tools/tests/skdiff/comparisonDir/very-different-pixels-same-size.png"><img src="../../../../../tools/tests/skdiff/comparisonDir/very-different-pixels-same-size.png" height="240px"></a></td></tr> <tr> -<td>slightly-different-pixels-same-size.png<br> 0.6630% of pixels differ +<td><b>slightly-different-pixels-same-size.png</b><br> 0.6630% of pixels differ ( 0.1904% weighted)<br>(2164 pixels)<br>Average color mismatch 0<br>Max color mismatch 213</td><td><a href="slightly-different-pixels-same-size-white.png"><img src="slightly-different-pixels-same-size-white.png" height="240px"></a></td><td><a href="slightly-different-pixels-same-size-diff.png"><img src="slightly-different-pixels-same-size-diff.png" height="240px"></a></td><td><a href="../../../../../tools/tests/skdiff/baseDir/slightly-different-pixels-same-size.png"><img src="../../../../../tools/tests/skdiff/baseDir/slightly-different-pixels-same-size.png" height="240px"></a></td><td><a href="../../../../../tools/tests/skdiff/comparisonDir/slightly-different-pixels-same-size.png"><img src="../../../../../tools/tests/skdiff/comparisonDir/slightly-different-pixels-same-size.png" height="240px"></a></td></tr> <tr> -<td>missing-from-baseDir.png<br></td><td>N/A</td><td>N/A</td><td>N/A</td><td><a href="../../../../../tools/tests/skdiff/comparisonDir/missing-from-baseDir.png"><img src="../../../../../tools/tests/skdiff/comparisonDir/missing-from-baseDir.png" height="240px"></a></td></tr> +<td><b>missing-from-baseDir.png</b><br>Missing from baseDir</td><td>N/A</td><td>N/A</td><td>N/A</td><td><a href="../../../../../tools/tests/skdiff/comparisonDir/missing-from-baseDir.png"><img src="../../../../../tools/tests/skdiff/comparisonDir/missing-from-baseDir.png" height="240px"></a></td></tr> <tr> -<td>missing-from-baseDir.xyz<br></td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr> +<td><b>missing-from-baseDir.xyz</b><br>Missing from baseDir</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr> <tr> -<td>missing-from-comparisonDir.png<br></td><td>N/A</td><td>N/A</td><td><a href="../../../../../tools/tests/skdiff/baseDir/missing-from-comparisonDir.png"><img src="../../../../../tools/tests/skdiff/baseDir/missing-from-comparisonDir.png" height="240px"></a></td><td>N/A</td></tr> +<td><b>missing-from-comparisonDir.png</b><br>Missing from comparisonDir</td><td>N/A</td><td>N/A</td><td><a href="../../../../../tools/tests/skdiff/baseDir/missing-from-comparisonDir.png"><img src="../../../../../tools/tests/skdiff/baseDir/missing-from-comparisonDir.png" height="240px"></a></td><td>N/A</td></tr> <tr> -<td>missing-from-comparisonDir.xyz<br></td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr> +<td><b>missing-from-comparisonDir.xyz</b><br>Missing from comparisonDir</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr> </table> </body> </html> diff --git a/tools/tests/skdiff/test1/output-expected/stdout b/tools/tests/skdiff/test1/output-expected/stdout index 4baf58549e..862b5be24c 100644 --- a/tools/tests/skdiff/test1/output-expected/stdout +++ b/tools/tests/skdiff/test1/output-expected/stdout @@ -1,5 +1,6 @@ +ERROR: no codec found for basePath <tools/tests/skdiff/baseDir/different-bits-unknown-format.xyz> ERROR: no codec found for <tools/tests/skdiff/baseDir/different-bits-unknown-format.xyz> -ERROR: no codec found for <tools/tests/skdiff/baseDir/identical-bits-unknown-format.xyz> +ERROR: no codec found for <tools/tests/skdiff/comparisonDir/different-bits-unknown-format.xyz> ERROR: no codec found for <tools/tests/skdiff/comparisonDir/missing-from-baseDir.xyz> ERROR: no codec found for <tools/tests/skdiff/baseDir/missing-from-comparisonDir.xyz> baseDir is [tools/tests/skdiff/baseDir/] @@ -11,6 +12,6 @@ Missing in baseDir: Missing in comparisonDir: missing-from-comparisonDir.png missing-from-comparisonDir.xyz -4 of 12 images matched. +3 of 12 images matched. Maximum pixel intensity mismatch 239 -Largest area mismatch was 100.00% of pixels +Largest area mismatch was 97.99% of pixels diff --git a/tools/tests/skdiff/test2/output-expected/stdout b/tools/tests/skdiff/test2/output-expected/stdout index 5567977d7e..eae392fc54 100644 --- a/tools/tests/skdiff/test2/output-expected/stdout +++ b/tools/tests/skdiff/test2/output-expected/stdout @@ -1,5 +1,4 @@ -ERROR: no codec found for <tools/tests/skdiff/baseDir/different-bits-unknown-format.xyz> -ERROR: no codec found for <tools/tests/skdiff/baseDir/identical-bits-unknown-format.xyz> +ERROR: no codec found for basePath <tools/tests/skdiff/baseDir/different-bits-unknown-format.xyz> baseDir is [tools/tests/skdiff/baseDir/] comparisonDir is [tools/tests/skdiff/comparisonDir/] not writing any diffs to outputDir [tools/tests/skdiff/test2/output-actual/] @@ -9,6 +8,6 @@ Missing in baseDir: Missing in comparisonDir: missing-from-comparisonDir.png missing-from-comparisonDir.xyz -4 of 12 images matched. +3 of 12 images matched. Maximum pixel intensity mismatch 239 -Largest area mismatch was 100.00% of pixels +Largest area mismatch was 97.99% of pixels |