Title: [286285] trunk/Tools
Revision
286285
Author
[email protected]
Date
2021-11-29 23:28:29 -0800 (Mon, 29 Nov 2021)

Log Message

Store image resolution in layout test snapshots, and have ImageDiff read it
https://bugs.webkit.org/show_bug.cgi?id=233609

Reviewed by Darin Adler.

On the way to fixing bug 232525, we need to communicate to ImageDiff the resolution of
layout test snapshots so that it can account for the resolution when computing pixel
tolerance values, which should be reported in CSS pixels.

So have DumpRenderTree and WebKitTestRunner, on Cocoa platforms, add image resolution
metadata, where a 2x snapshot (i.e. a hidpi test) reports a horizontal and vertical
resolution of 144dpi.

Change ImageDiff to read these values and store them in PlatformImage; a future patch will
make use of the data.

* DumpRenderTree/cg/PixelDumpSupportCG.cpp:
(printPNG):
(dumpBitmap):
* DumpRenderTree/cg/PixelDumpSupportCG.h:
(BitmapContext::scaleFactor const):
(BitmapContext::setScaleFactor):
* DumpRenderTree/ios/PixelDumpSupportIOS.mm:
(createBitmapContextFromWebView):
* DumpRenderTree/mac/PixelDumpSupportMac.mm:
(createBitmapContextFromWebView):
* ImageDiff/ImageDiff.cpp:
(main):
* ImageDiff/PlatformImage.h:
(ImageDiff::PlatformImage::scaleFactor const):
* ImageDiff/cg/PlatformImageCG.cpp:
(ImageDiff::createImageFromDataProvider):
(ImageDiff::PlatformImage::createFromFile):
(ImageDiff::PlatformImage::createFromStdin):
(ImageDiff::PlatformImage::PlatformImage):
* WebKitTestRunner/cg/TestInvocationCG.cpp:
(WTR::dumpBitmap):
(WTR::TestInvocation::dumpPixelsAndCompareWithExpected):

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (286284 => 286285)


--- trunk/Tools/ChangeLog	2021-11-30 05:24:37 UTC (rev 286284)
+++ trunk/Tools/ChangeLog	2021-11-30 07:28:29 UTC (rev 286285)
@@ -1,3 +1,44 @@
+2021-11-29  Simon Fraser  <[email protected]>
+
+        Store image resolution in layout test snapshots, and have ImageDiff read it
+        https://bugs.webkit.org/show_bug.cgi?id=233609
+
+        Reviewed by Darin Adler.
+
+        On the way to fixing bug 232525, we need to communicate to ImageDiff the resolution of
+        layout test snapshots so that it can account for the resolution when computing pixel
+        tolerance values, which should be reported in CSS pixels.
+
+        So have DumpRenderTree and WebKitTestRunner, on Cocoa platforms, add image resolution
+        metadata, where a 2x snapshot (i.e. a hidpi test) reports a horizontal and vertical
+        resolution of 144dpi.
+
+        Change ImageDiff to read these values and store them in PlatformImage; a future patch will
+        make use of the data.
+
+        * DumpRenderTree/cg/PixelDumpSupportCG.cpp:
+        (printPNG):
+        (dumpBitmap):
+        * DumpRenderTree/cg/PixelDumpSupportCG.h:
+        (BitmapContext::scaleFactor const):
+        (BitmapContext::setScaleFactor):
+        * DumpRenderTree/ios/PixelDumpSupportIOS.mm:
+        (createBitmapContextFromWebView):
+        * DumpRenderTree/mac/PixelDumpSupportMac.mm:
+        (createBitmapContextFromWebView):
+        * ImageDiff/ImageDiff.cpp:
+        (main):
+        * ImageDiff/PlatformImage.h:
+        (ImageDiff::PlatformImage::scaleFactor const):
+        * ImageDiff/cg/PlatformImageCG.cpp:
+        (ImageDiff::createImageFromDataProvider):
+        (ImageDiff::PlatformImage::createFromFile):
+        (ImageDiff::PlatformImage::createFromStdin):
+        (ImageDiff::PlatformImage::PlatformImage):
+        * WebKitTestRunner/cg/TestInvocationCG.cpp:
+        (WTR::dumpBitmap):
+        (WTR::TestInvocation::dumpPixelsAndCompareWithExpected):
+
 2021-11-29  Jonathan Bedard  <[email protected]>
 
         [webkitscmpy] Guard git-webkit with __name__

Modified: trunk/Tools/DumpRenderTree/cg/PixelDumpSupportCG.cpp (286284 => 286285)


--- trunk/Tools/DumpRenderTree/cg/PixelDumpSupportCG.cpp	2021-11-30 05:24:37 UTC (rev 286284)
+++ trunk/Tools/DumpRenderTree/cg/PixelDumpSupportCG.cpp	2021-11-30 07:28:29 UTC (rev 286285)
@@ -33,7 +33,7 @@
 
 #include "DumpRenderTree.h"
 #include "PixelDumpSupport.h"
-#include <ImageIO/CGImageDestination.h>
+#include <ImageIO/ImageIO.h>
 #include <algorithm>
 #include <ctype.h>
 #include <wtf/Assertions.h>
@@ -57,11 +57,20 @@
 static const CFStringRef kUTTypePNG = CFSTR("public.png");
 #endif
 
-static void printPNG(CGImageRef image, const char* checksum)
+static void printPNG(CGImageRef image, const char* checksum, double scaleFactor)
 {
-    RetainPtr<CFMutableDataRef> imageData = adoptCF(CFDataCreateMutable(0, 0));
-    RetainPtr<CGImageDestinationRef> imageDest = adoptCF(CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0));
-    CGImageDestinationAddImage(imageDest.get(), image, 0);
+    auto imageData = adoptCF(CFDataCreateMutable(0, 0));
+    auto imageDest = adoptCF(CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0));
+
+    auto propertiesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    double resolutionWidth = 72.0 * scaleFactor;
+    double resolutionHeight = 72.0 * scaleFactor;
+    auto resolutionWidthNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &resolutionWidth));
+    auto resolutionHeightNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &resolutionHeight));
+    CFDictionarySetValue(propertiesDictionary.get(), kCGImagePropertyDPIWidth, resolutionWidthNumber.get());
+    CFDictionarySetValue(propertiesDictionary.get(), kCGImagePropertyDPIHeight, resolutionHeightNumber.get());
+
+    CGImageDestinationAddImage(imageDest.get(), image, propertiesDictionary.get());
     CGImageDestinationFinalize(imageDest.get());
 
     const UInt8* data = ""
@@ -110,7 +119,7 @@
 void dumpBitmap(BitmapContext* context, const char* checksum)
 {
     RetainPtr<CGImageRef> image = adoptCF(CGBitmapContextCreateImage(context->cgContext()));
-    printPNG(image.get(), checksum);
+    printPNG(image.get(), checksum, context->scaleFactor());
 }
 
 #if PLATFORM(COCOA)

Modified: trunk/Tools/DumpRenderTree/cg/PixelDumpSupportCG.h (286284 => 286285)


--- trunk/Tools/DumpRenderTree/cg/PixelDumpSupportCG.h	2021-11-30 05:24:37 UTC (rev 286284)
+++ trunk/Tools/DumpRenderTree/cg/PixelDumpSupportCG.h	2021-11-30 07:28:29 UTC (rev 286285)
@@ -63,6 +63,9 @@
     }
 
     CGContextRef cgContext() const { return m_context.get(); }
+    
+    double scaleFactor() const { return m_scaleFactor; }
+    void setScaleFactor(double scaleFactor) { m_scaleFactor = scaleFactor; }
 
 private:
 
@@ -74,7 +77,7 @@
 
     PlatformBitmapBuffer m_buffer;
     RetainPtr<CGContextRef> m_context;
-
+    double m_scaleFactor { 1.0 };
 };
 
 #if PLATFORM(COCOA)

Modified: trunk/Tools/DumpRenderTree/ios/PixelDumpSupportIOS.mm (286284 => 286285)


--- trunk/Tools/DumpRenderTree/ios/PixelDumpSupportIOS.mm	2021-11-30 05:24:37 UTC (rev 286284)
+++ trunk/Tools/DumpRenderTree/ios/PixelDumpSupportIOS.mm	2021-11-30 07:28:29 UTC (rev 286285)
@@ -81,6 +81,8 @@
     if (!bitmapContext)
         return nullptr;
 
+    bitmapContext->setScaleFactor(deviceScaleFactor);
+
     CGContextDrawImage(bitmapContext->cgContext(), CGRectMake(0, 0, bufferWidth, bufferHeight), cgImage.get());
     return bitmapContext;
 }

Modified: trunk/Tools/DumpRenderTree/mac/PixelDumpSupportMac.mm (286284 => 286285)


--- trunk/Tools/DumpRenderTree/mac/PixelDumpSupportMac.mm	2021-11-30 05:24:37 UTC (rev 286284)
+++ trunk/Tools/DumpRenderTree/mac/PixelDumpSupportMac.mm	2021-11-30 07:28:29 UTC (rev 286285)
@@ -103,6 +103,9 @@
     auto bitmapContext = createBitmapContext(pixelsWide, pixelsHigh, rowBytes, buffer);
     if (!bitmapContext)
         return nullptr;
+
+    bitmapContext->setScaleFactor(deviceScaleFactor);
+
     CGContextRef context = bitmapContext->cgContext();
     // The final scaling gets doubled on the screen capture surface when we use the hidpi backingScaleFactor value for CTM.
     // This is a workaround to push the scaling back.

Modified: trunk/Tools/ImageDiff/ImageDiff.cpp (286284 => 286285)


--- trunk/Tools/ImageDiff/ImageDiff.cpp	2021-11-30 05:24:37 UTC (rev 286284)
+++ trunk/Tools/ImageDiff/ImageDiff.cpp	2021-11-30 07:28:29 UTC (rev 286285)
@@ -151,7 +151,7 @@
             }
             
             if (verbose)
-                fprintf(stderr, "Comparing files actual: %s and baseline: %s\n", file1Path, file2Path);
+                fprintf(stderr, "Comparing files actual: %s (resolution %.1f) and baseline: %s (resolution %.1f)\n", file1Path, actualImage->scaleFactor(), file2Path, baselineImage->scaleFactor());
 
             return processImages(std::move(actualImage), std::move(baselineImage), exact, printDifference);
         }
@@ -199,6 +199,9 @@
         }
 
         if (actualImage && baselineImage) {
+            if (verbose)
+                fprintf(stderr, "Actual image resolution: %.1f, baseline image resolution: %.1f\n", actualImage->scaleFactor(), baselineImage->scaleFactor());
+
             auto result = processImages(std::exchange(actualImage, { }), std::exchange(baselineImage, { }), exact, printDifference);
             if (result != EXIT_SUCCESS)
                 return result;

Modified: trunk/Tools/ImageDiff/PlatformImage.h (286284 => 286285)


--- trunk/Tools/ImageDiff/PlatformImage.h	2021-11-30 05:24:37 UTC (rev 286284)
+++ trunk/Tools/ImageDiff/PlatformImage.h	2021-11-30 07:28:29 UTC (rev 286285)
@@ -43,7 +43,7 @@
 #if defined(USE_CAIRO) && USE_CAIRO
     PlatformImage(cairo_surface_t*);
 #else
-    PlatformImage(CGImageRef);
+    PlatformImage(CGImageRef, double scaleFactor = 1);
 #endif
     ~PlatformImage();
 
@@ -51,6 +51,7 @@
     size_t height() const;
     size_t rowBytes() const;
     bool hasAlpha() const;
+    double scaleFactor() const { return m_scaleFactor; }
 
     unsigned char* pixels() const;
     bool isCompatible(const PlatformImage&) const;
@@ -73,6 +74,7 @@
     CGImageRef m_image;
     mutable void* m_buffer { nullptr };
 #endif
+    double m_scaleFactor { 1 }; // Essentially resolution, but not in DPI.
 };
 
 } // namespace ImageDiff

Modified: trunk/Tools/ImageDiff/cg/PlatformImageCG.cpp (286284 => 286285)


--- trunk/Tools/ImageDiff/cg/PlatformImageCG.cpp	2021-11-30 05:24:37 UTC (rev 286284)
+++ trunk/Tools/ImageDiff/cg/PlatformImageCG.cpp	2021-11-30 07:28:29 UTC (rev 286285)
@@ -28,7 +28,7 @@
 
 #include <CoreGraphics/CGBitmapContext.h>
 #include <CoreGraphics/CGImage.h>
-#include <ImageIO/CGImageDestination.h>
+#include <ImageIO/ImageIO.h>
 #include <algorithm>
 #include <stdio.h>
 
@@ -71,6 +71,34 @@
 
 namespace ImageDiff {
 
+static std::unique_ptr<PlatformImage> createImageFromDataProvider(CGDataProviderRef dataProvider)
+{
+    double scaleFactor = 1;
+
+    auto imageSource = CGImageSourceCreateWithDataProvider(dataProvider, 0);
+    if (auto properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nullptr)) {
+        auto resolutionXProperty = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyDPIWidth);
+        auto resolutionYProperty = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyDPIHeight);
+        if (resolutionXProperty && resolutionYProperty) {
+            double resolutionX, resolutionY;
+            if (CFNumberGetValue(resolutionXProperty, kCFNumberDoubleType, &resolutionX) && CFNumberGetValue(resolutionYProperty, kCFNumberDoubleType, &resolutionY)) {
+                if (resolutionX != resolutionY)
+                    fprintf(stderr, "Image has different horizontal and vertical resolutions, which is not supported");
+
+                scaleFactor = resolutionX / 72.0;
+            }
+        }
+        CFRelease(properties);
+    }
+
+    auto image = CGImageSourceCreateImageAtIndex(imageSource, 0, nullptr);
+    CFRelease(imageSource);
+    if (!image)
+        return nullptr;
+
+    return std::make_unique<PlatformImage>(image, scaleFactor);
+}
+
 std::unique_ptr<PlatformImage> PlatformImage::createFromFile(const char* filePath)
 {
     auto dataProvider = CGDataProviderCreateWithFilename(filePath);
@@ -77,12 +105,9 @@
     if (!dataProvider)
         return nullptr;
 
-    auto image = CGImageCreateWithPNGDataProvider(dataProvider, 0, false, kCGRenderingIntentDefault);
+    auto result = createImageFromDataProvider(dataProvider);
     CGDataProviderRelease(dataProvider);
-    if (!image)
-        return nullptr;
-
-    return std::make_unique<PlatformImage>(image);
+    return result;
 }
 
 std::unique_ptr<PlatformImage> PlatformImage::createFromStdin(size_t imageSize)
@@ -99,10 +124,10 @@
     }
     CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(data);
     CFRelease(data);
-    CGImageRef image = CGImageCreateWithPNGDataProvider(dataProvider, 0, false, kCGRenderingIntentDefault);
-    CFRelease(dataProvider);
 
-    return std::make_unique<PlatformImage>(image);
+    auto result = createImageFromDataProvider(dataProvider);
+    CGDataProviderRelease(dataProvider);
+    return result;
 }
 
 std::unique_ptr<PlatformImage> PlatformImage::createFromDiffData(void* data, size_t width, size_t height)
@@ -117,8 +142,9 @@
     return std::make_unique<PlatformImage>(image);
 }
 
-PlatformImage::PlatformImage(CGImageRef image)
+PlatformImage::PlatformImage(CGImageRef image, double scaleFactor)
     : m_image(image)
+    , m_scaleFactor(scaleFactor)
 {
 }
 

Modified: trunk/Tools/WebKitTestRunner/cg/TestInvocationCG.cpp (286284 => 286285)


--- trunk/Tools/WebKitTestRunner/cg/TestInvocationCG.cpp	2021-11-30 05:24:37 UTC (rev 286284)
+++ trunk/Tools/WebKitTestRunner/cg/TestInvocationCG.cpp	2021-11-30 07:28:29 UTC (rev 286285)
@@ -29,7 +29,7 @@
 #include "PixelDumpSupport.h"
 #include "PlatformWebView.h"
 #include "TestController.h"
-#include <ImageIO/CGImageDestination.h>
+#include <ImageIO/ImageIO.h>
 #include <WebKit/WKImageCG.h>
 #include <wtf/RetainPtr.h>
 #include <wtf/SHA1.h>
@@ -107,12 +107,21 @@
         snprintf(hashString, 33, "%s%02x", hashString, hash[i]);
 }
 
-static void dumpBitmap(CGContextRef bitmapContext, const char* checksum)
+static void dumpBitmap(CGContextRef bitmapContext, const char* checksum, WKSize imageSize, WKSize windowSize)
 {
     auto image = adoptCF(CGBitmapContextCreateImage(bitmapContext));
     auto imageData = adoptCF(CFDataCreateMutable(0, 0));
     auto imageDest = adoptCF(CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0));
-    CGImageDestinationAddImage(imageDest.get(), image.get(), 0);
+
+    auto propertiesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    double resolutionWidth = 72.0 * imageSize.width / windowSize.width;
+    double resolutionHeight = 72.0 * imageSize.height / windowSize.height;
+    auto resolutionWidthNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &resolutionWidth));
+    auto resolutionHeightNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &resolutionHeight));
+    CFDictionarySetValue(propertiesDictionary.get(), kCGImagePropertyDPIWidth, resolutionWidthNumber.get());
+    CFDictionarySetValue(propertiesDictionary.get(), kCGImagePropertyDPIHeight, resolutionHeightNumber.get());
+
+    CGImageDestinationAddImage(imageDest.get(), image.get(), propertiesDictionary.get());
     CGImageDestinationFinalize(imageDest.get());
 
     const unsigned char* data = ""
@@ -181,10 +190,12 @@
     if (repaintRects)
         paintRepaintRectOverlay(context.get(), imageSize, repaintRects);
 
+    auto windowSize = TestController::singleton().mainWebView()->windowFrame().size;
+
     char actualHash[33];
     computeSHA1HashStringForContext(context.get(), actualHash);
     if (!compareActualHashToExpectedAndDumpResults(actualHash))
-        dumpBitmap(context.get(), actualHash);
+        dumpBitmap(context.get(), actualHash, imageSize, windowSize);
 }
 
 } // namespace WTR
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to