Title: [284764] trunk/Tools
Revision
284764
Author
[email protected]
Date
2021-10-24 11:22:05 -0700 (Sun, 24 Oct 2021)

Log Message

Add an ImageDiff option to print out WPT-style pixel differences
https://bugs.webkit.org/show_bug.cgi?id=232212

Reviewed by NOBODY (OOPS!).

When passed `--difference`, ImageDiff will compute and print out the "maxDifference=;totalPixels="
values documented at https://web-platform-tests.org/writing-tests/reftests.html. With these values,
there is no built-in tolerance as there is with the legacy difference computation.

Rename variables related to the legacy computation.

* ImageDiff/ImageDiff.cpp:
(processImages):
(main):
* ImageDiff/PlatformImage.cpp:
(ImageDiff::PlatformImage::difference):
* ImageDiff/PlatformImage.h:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (284763 => 284764)


--- trunk/Tools/ChangeLog	2021-10-24 18:13:21 UTC (rev 284763)
+++ trunk/Tools/ChangeLog	2021-10-24 18:22:05 UTC (rev 284764)
@@ -1,3 +1,23 @@
+2021-10-23  Simon Fraser  <[email protected]>
+
+        Add an ImageDiff option to print out WPT-style pixel differences
+        https://bugs.webkit.org/show_bug.cgi?id=232212
+
+        Reviewed by Darin Adler.
+        
+        When passed `--difference`, ImageDiff will compute and print out the "maxDifference=;totalPixels="
+        values documented at https://web-platform-tests.org/writing-tests/reftests.html. With these values,
+        there is no built-in tolerance as there is with the legacy difference computation.
+
+        Rename variables related to the legacy computation.
+
+        * ImageDiff/ImageDiff.cpp:
+        (processImages):
+        (main):
+        * ImageDiff/PlatformImage.cpp:
+        (ImageDiff::PlatformImage::difference):
+        * ImageDiff/PlatformImage.h:
+
 2021-10-24  Simon Fraser  <[email protected]>
 
         Allow ImageDiff to read from files

Modified: trunk/Tools/ImageDiff/ImageDiff.cpp (284763 => 284764)


--- trunk/Tools/ImageDiff/ImageDiff.cpp	2021-10-24 18:13:21 UTC (rev 284763)
+++ trunk/Tools/ImageDiff/ImageDiff.cpp	2021-10-24 18:22:05 UTC (rev 284764)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
  * Copyright (C) 2017 Igalia S.L.
  * Copyright (C) 2005, 2007, 2015 Apple Inc. All rights reserved.
  * Copyright (C) 2005 Ben La Monica <[email protected]>.  All rights reserved.
@@ -48,7 +49,7 @@
 #define FORMAT_SIZE_T "zu"
 #endif
 
-static int processImages(std::unique_ptr<PlatformImage>&& actualImage, std::unique_ptr<PlatformImage>&& baselineImage, float tolerance)
+static int processImages(std::unique_ptr<PlatformImage>&& actualImage, std::unique_ptr<PlatformImage>&& baselineImage, float tolerance, bool printDifference)
 {
     if (!actualImage->isCompatible(*baselineImage)) {
         if (actualImage->width() != baselineImage->width() || actualImage->height() != baselineImage->height()) {
@@ -62,22 +63,26 @@
         return EXIT_FAILURE;
     }
 
-    float difference = 100.0f;
-    auto diffImage = actualImage->difference(*baselineImage, difference);
-    if (difference <= tolerance)
-        difference = 0.0f;
+    PlatformImage::Difference differenceData = { 100, 0, 0 };
+    auto diffImage = actualImage->difference(*baselineImage, differenceData);
+    float legacyDifference = differenceData.percentageDifference;
+    if (legacyDifference <= tolerance)
+        legacyDifference = 0.0f;
     else {
-        difference = roundf(difference * 100.0f) / 100.0f;
-        difference = std::max<float>(difference, 0.01f); // round to 2 decimal places
+        legacyDifference = roundf(legacyDifference * 100.0f) / 100.0f;
+        legacyDifference = std::max<float>(legacyDifference, 0.01f); // round to 2 decimal places
     }
 
-    if (difference > 0.0f) {
+    if (legacyDifference > 0.0f) {
         if (diffImage)
             diffImage->writeAsPNGToStdout();
-        fprintf(stdout, "diff: %01.2f%% failed\n", difference);
+        fprintf(stdout, "diff: %01.2f%% failed\n", legacyDifference);
     } else
-        fprintf(stdout, "diff: %01.2f%% passed\n", difference);
+        fprintf(stdout, "diff: %01.2f%% passed\n", legacyDifference);
 
+    if (printDifference)
+        fprintf(stdout, "maxDifference=%u; totalPixels=%lu\n", differenceData.maxDifference, differenceData.totalPixels);
+
     return EXIT_SUCCESS;
 }
 
@@ -90,6 +95,7 @@
 
     float tolerance = 0.0f;
     bool verbose = false;
+    bool printDifference = false;
 
     for (int i = 1; i < argc; ++i) {
         if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "--tolerance")) {
@@ -111,9 +117,14 @@
             continue;
         }
 
+        if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--difference")) {
+            printDifference = true;
+            continue;
+        }
+
         if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
             fprintf(stdout,
-                "usage: ImageDiff [-h] [-t TOLERANCE] [-v] ([actualImage baselineImage] | <stdin>)\n" \
+                "usage: ImageDiff [-h] [-v] [-d] [-t TOLERANCE] ([actualImage baselineImage] | <stdin>)\n" \
                 "\n" \
                 "Reads two PNG-encoded images and compares them. If two file path arguments are supplied, \n" \
                 "reads from the specified files, otherwise from <stdin> where each file is preceded by \n" \
@@ -122,6 +133,7 @@
                 "optional arguments:\n" \
                 "  -h, --help            show this help message and exit\n" \
                 "  -v, --verbose         print diagnostic information to stderr\n" \
+                "  -d, --difference      print WPT-style maxDifference and totalPixels data\n" \
                 "  -t, --tolerance TOLERANCE\n" \
                 "                        compare the images with the given tolerance\n"
             );
@@ -158,7 +170,7 @@
             if (verbose)
                 fprintf(stderr, "Comparing files actual: %s and baseline: %s\n", file1Path, file2Path);
 
-            return processImages(std::move(actualImage), std::move(baselineImage), tolerance);
+            return processImages(std::move(actualImage), std::move(baselineImage), tolerance, printDifference);
         }
     }
 
@@ -206,7 +218,7 @@
         if (actualImage && baselineImage) {
             if (verbose)
                 fprintf(stderr, "ImageDiff: processing images\n");
-            auto result = processImages(std::exchange(actualImage, { }), std::exchange(baselineImage, { }), tolerance);
+            auto result = processImages(std::exchange(actualImage, { }), std::exchange(baselineImage, { }), tolerance, printDifference);
             if (result != EXIT_SUCCESS)
                 return result;
         }

Modified: trunk/Tools/ImageDiff/PlatformImage.cpp (284763 => 284764)


--- trunk/Tools/ImageDiff/PlatformImage.cpp	2021-10-24 18:13:21 UTC (rev 284763)
+++ trunk/Tools/ImageDiff/PlatformImage.cpp	2021-10-24 18:22:05 UTC (rev 284764)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2007, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2007-2021 Apple Inc. All rights reserved.
  * Copyright (C) 2005 Ben La Monica <[email protected]>.  All rights reserved.
  * Copyright (C) 2011 Brent Fulgham. All rights reserved.
  *
@@ -40,7 +40,7 @@
         && hasAlpha() == other.hasAlpha();
 }
 
-std::unique_ptr<PlatformImage> PlatformImage::difference(const PlatformImage& other, float& percentageDifference)
+std::unique_ptr<PlatformImage> PlatformImage::difference(const PlatformImage& other, Difference& difference)
 {
     size_t width = this->width();
     size_t height = this->height();
@@ -47,27 +47,39 @@
 
     // Compare the content of the 2 bitmaps
     void* diffBuffer = malloc(width * height);
-    float count = 0.0f;
-    float sum = 0.0f;
-    float maxDistance = 0.0f;
+    size_t pixelCountWithSignificantDifference = 0;
+    float legacyDistanceSum = 0.0f;
+    float legacyDistanceMax = 0.0f;
+
     unsigned char* basePixel = this->pixels();
     unsigned char* pixel = other.pixels();
     unsigned char* diffPixel = reinterpret_cast<unsigned char*>(diffBuffer);
+
     for (size_t y = 0; y < height; ++y) {
         for (size_t x = 0; x < width; ++x) {
-            float red = (pixel[0] - basePixel[0]) / std::max<float>(255 - basePixel[0], basePixel[0]);
+            float red   = (pixel[0] - basePixel[0]) / std::max<float>(255 - basePixel[0], basePixel[0]);
             float green = (pixel[1] - basePixel[1]) / std::max<float>(255 - basePixel[1], basePixel[1]);
-            float blue = (pixel[2] - basePixel[2]) / std::max<float>(255 - basePixel[2], basePixel[2]);
+            float blue  = (pixel[2] - basePixel[2]) / std::max<float>(255 - basePixel[2], basePixel[2]);
             float alpha = (pixel[3] - basePixel[3]) / std::max<float>(255 - basePixel[3], basePixel[3]);
-            float distance = sqrtf(red * red + green * green + blue * blue + alpha * alpha) / 2.0f;
+            float legacyDistance = sqrtf(red * red + green * green + blue * blue + alpha * alpha) / 2.0f;
 
-            *diffPixel++ = static_cast<unsigned char>(distance * 255.0f);
+            *diffPixel++ = static_cast<unsigned char>(legacyDistance * 255.0f);
+            
+            // WPT-style difference code.
+            if (legacyDistance) {
+                ++difference.totalPixels;
+                unsigned redDiff    = std::abs(pixel[0] - basePixel[0]);
+                unsigned greenDiff  = std::abs(pixel[1] - basePixel[1]);
+                unsigned blueDiff   = std::abs(pixel[2] - basePixel[2]);
+                unsigned maxDiff = std::max({ redDiff, greenDiff, blueDiff });
+                difference.maxDifference = std::max(difference.maxDifference, maxDiff);
+            }
 
-            if (distance >= 1.0f / 255.0f) {
-                count += 1.0f;
-                sum += distance;
-                if (distance > maxDistance)
-                    maxDistance = distance;
+            // Legacy difference code. Note there is some built-in tolerance here.
+            if (legacyDistance >= 1.0f / 255.0f) {
+                ++pixelCountWithSignificantDifference;
+                legacyDistanceSum += legacyDistance;
+                legacyDistanceMax = std::max(legacyDistanceMax, legacyDistance);
             }
 
             basePixel += 4;
@@ -75,22 +87,22 @@
         }
     }
 
-    // Compute the difference as a percentage combining both the number of different pixels and their difference amount i.e. the average distance over the entire image
-    if (count > 0.0f)
-        percentageDifference = 100.0f * sum / (height * width);
+    // Compute the difference as a percentage combining both the number of different pixels and their difference amount i.e. the average distance over the entire image.
+    if (pixelCountWithSignificantDifference)
+        difference.percentageDifference = 100.0f * legacyDistanceSum / (height * width);
     else
-        percentageDifference = 0.0f;
+        difference.percentageDifference = 0.0f;
 
-    if (!percentageDifference) {
+    if (!pixelCountWithSignificantDifference) {
         free(diffBuffer);
         return nullptr;
     }
 
-    // Generate a normalized diff image if there is any difference
-    if (maxDistance < 1.0f) {
+    // Generate a normalized diff image if there is any difference.
+    if (pixelCountWithSignificantDifference) {
         diffPixel = reinterpret_cast<unsigned char*>(diffBuffer);
         for (size_t p = 0; p < height * width; ++p)
-            diffPixel[p] /= maxDistance;
+            diffPixel[p] /= legacyDistanceMax;
     }
 
     return PlatformImage::createFromDiffData(diffBuffer, width, height);

Modified: trunk/Tools/ImageDiff/PlatformImage.h (284763 => 284764)


--- trunk/Tools/ImageDiff/PlatformImage.h	2021-10-24 18:13:21 UTC (rev 284763)
+++ trunk/Tools/ImageDiff/PlatformImage.h	2021-10-24 18:22:05 UTC (rev 284764)
@@ -51,9 +51,19 @@
     size_t height() const;
     size_t rowBytes() const;
     bool hasAlpha() const;
+
     unsigned char* pixels() const;
     bool isCompatible(const PlatformImage&) const;
-    std::unique_ptr<PlatformImage> difference(const PlatformImage&, float& percentageDifference);
+
+    struct Difference {
+        float percentageDifference { 0 }; // Legacy different measure.
+
+        // WPT-style difference: https://web-platform-tests.org/writing-tests/reftests.html.
+        unsigned maxDifference { 0 };
+        size_t totalPixels { 0 };
+    };
+    std::unique_ptr<PlatformImage> difference(const PlatformImage&, Difference&);
+
     void writeAsPNGToStdout();
 
 private:
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to