From 94eec18b6fb6749a5a07016eeeedcab958f43c30 Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Sun, 11 Sep 2022 20:03:53 -0400 Subject: [PATCH 1/7] Add an optional perceptualPrecision parameter for image snapshot comparisons The perceptual precision number is between 0 & 1 that gets translated to a CIE94 tolerance https://en.wikipedia.org/wiki/Color_difference --- .../SnapshotTesting/Snapshotting/Any.swift | 2 +- .../Snapshotting/CALayer.swift | 16 ++-- .../SnapshotTesting/Snapshotting/CGPath.swift | 16 ++-- .../Snapshotting/NSBezierPath.swift | 8 +- .../Snapshotting/NSImage.swift | 68 ++++++++++++----- .../SnapshotTesting/Snapshotting/NSView.swift | 5 +- .../Snapshotting/NSViewController.swift | 5 +- .../Snapshotting/SceneKit.swift | 14 ++-- .../Snapshotting/SpriteKit.swift | 14 ++-- .../Snapshotting/SwiftUIView.swift | 4 +- .../Snapshotting/UIBezierPath.swift | 8 +- .../Snapshotting/UIImage.swift | 75 +++++++++++++------ .../SnapshotTesting/Snapshotting/UIView.swift | 4 +- .../Snapshotting/UIViewController.swift | 8 +- .../SnapshotTestingTests.swift | 2 +- 15 files changed, 168 insertions(+), 81 deletions(-) diff --git a/Sources/SnapshotTesting/Snapshotting/Any.swift b/Sources/SnapshotTesting/Snapshotting/Any.swift index 55d5155a..385c2642 100644 --- a/Sources/SnapshotTesting/Snapshotting/Any.swift +++ b/Sources/SnapshotTesting/Snapshotting/Any.swift @@ -7,7 +7,7 @@ extension Snapshotting where Format == String { } } -@available(macOS 10.13, watchOS 4.0, *) +@available(macOS 10.13, watchOS 4.0, tvOS 11.0, *) extension Snapshotting where Format == String { /// A snapshot strategy for comparing any structure based on their JSON representation. public static var json: Snapshotting { diff --git a/Sources/SnapshotTesting/Snapshotting/CALayer.swift b/Sources/SnapshotTesting/Snapshotting/CALayer.swift index d11e37f4..51b5a44e 100644 --- a/Sources/SnapshotTesting/Snapshotting/CALayer.swift +++ b/Sources/SnapshotTesting/Snapshotting/CALayer.swift @@ -9,9 +9,11 @@ extension Snapshotting where Value == CALayer, Format == NSImage { /// A snapshot strategy for comparing layers based on pixel equality. /// - /// - Parameter precision: The percentage of pixels that must match. - public static func image(precision: Float) -> Snapshotting { - return SimplySnapshotting.image(precision: precision).pullback { layer in + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) + public static func image(precision: Float, perceptualPrecision: Float = 1) -> Snapshotting { + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision).pullback { layer in let image = NSImage(size: layer.bounds.size) image.lockFocus() let context = NSGraphicsContext.current!.cgContext @@ -34,10 +36,12 @@ extension Snapshotting where Value == CALayer, Format == UIImage { /// A snapshot strategy for comparing layers based on pixel equality. /// - /// - Parameter precision: The percentage of pixels that must match. - public static func image(precision: Float = 1, traits: UITraitCollection = .init()) + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, traits: UITraitCollection = .init()) -> Snapshotting { - return SimplySnapshotting.image(precision: precision, scale: traits.displayScale).pullback { layer in + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision, scale: traits.displayScale).pullback { layer in renderer(bounds: layer.bounds, for: traits).image { ctx in layer.setNeedsLayout() layer.layoutIfNeeded() diff --git a/Sources/SnapshotTesting/Snapshotting/CGPath.swift b/Sources/SnapshotTesting/Snapshotting/CGPath.swift index d7ee7df1..8e96568e 100644 --- a/Sources/SnapshotTesting/Snapshotting/CGPath.swift +++ b/Sources/SnapshotTesting/Snapshotting/CGPath.swift @@ -9,9 +9,11 @@ extension Snapshotting where Value == CGPath, Format == NSImage { /// A snapshot strategy for comparing bezier paths based on pixel equality. /// - /// - Parameter precision: The percentage of pixels that must match. - public static func image(precision: Float = 1, drawingMode: CGPathDrawingMode = .eoFill) -> Snapshotting { - return SimplySnapshotting.image(precision: precision).pullback { path in + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, drawingMode: CGPathDrawingMode = .eoFill) -> Snapshotting { + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision).pullback { path in let bounds = path.boundingBoxOfPath var transform = CGAffineTransform(translationX: -bounds.origin.x, y: -bounds.origin.y) let path = path.copy(using: &transform)! @@ -38,9 +40,11 @@ extension Snapshotting where Value == CGPath, Format == UIImage { /// A snapshot strategy for comparing bezier paths based on pixel equality. /// - /// - Parameter precision: The percentage of pixels that must match. - public static func image(precision: Float = 1, scale: CGFloat = 1, drawingMode: CGPathDrawingMode = .eoFill) -> Snapshotting { - return SimplySnapshotting.image(precision: precision, scale: scale).pullback { path in + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, scale: CGFloat = 1, drawingMode: CGPathDrawingMode = .eoFill) -> Snapshotting { + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision, scale: scale).pullback { path in let bounds = path.boundingBoxOfPath let format: UIGraphicsImageRendererFormat if #available(iOS 11.0, tvOS 11.0, *) { diff --git a/Sources/SnapshotTesting/Snapshotting/NSBezierPath.swift b/Sources/SnapshotTesting/Snapshotting/NSBezierPath.swift index d9d5defc..b76bf57d 100644 --- a/Sources/SnapshotTesting/Snapshotting/NSBezierPath.swift +++ b/Sources/SnapshotTesting/Snapshotting/NSBezierPath.swift @@ -9,9 +9,11 @@ extension Snapshotting where Value == NSBezierPath, Format == NSImage { /// A snapshot strategy for comparing bezier paths based on pixel equality. /// - /// - Parameter precision: The percentage of pixels that must match. - public static func image(precision: Float = 1) -> Snapshotting { - return SimplySnapshotting.image(precision: precision).pullback { path in + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1) -> Snapshotting { + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision).pullback { path in // Move path info frame: let bounds = path.bounds let transform = AffineTransform(translationByX: -bounds.origin.x, byY: -bounds.origin.y) diff --git a/Sources/SnapshotTesting/Snapshotting/NSImage.swift b/Sources/SnapshotTesting/Snapshotting/NSImage.swift index 625639d8..9090729b 100644 --- a/Sources/SnapshotTesting/Snapshotting/NSImage.swift +++ b/Sources/SnapshotTesting/Snapshotting/NSImage.swift @@ -1,21 +1,24 @@ #if os(macOS) +import CoreImage import Cocoa import XCTest extension Diffing where Value == NSImage { /// A pixel-diffing strategy for NSImage's which requires a 100% match. - public static let image = Diffing.image(precision: 1) + public static let image = Diffing.image() /// A pixel-diffing strategy for NSImage that allows customizing how precise the matching must be. /// - /// - Parameter precision: A value between 0 and 1, where 1 means the images must match 100% of their pixels. + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - Returns: A new diffing strategy. - public static func image(precision: Float) -> Diffing { + public static func image(precision: Float = 1, perceptualPrecision: Float = 1) -> Diffing { return .init( toData: { NSImagePNGRepresentation($0)! }, fromData: { NSImage(data: $0)! } ) { old, new in - guard !compare(old, new, precision: precision) else { return nil } + guard !compare(old, new, precision: precision, perceptualPrecision: perceptualPrecision) else { return nil } let difference = SnapshotTesting.diff(old, new) let message = new.size == old.size ? "Newly-taken snapshot does not match reference." @@ -31,16 +34,18 @@ extension Diffing where Value == NSImage { extension Snapshotting where Value == NSImage, Format == NSImage { /// A snapshot strategy for comparing images based on pixel equality. public static var image: Snapshotting { - return .image(precision: 1) + return .image() } /// A snapshot strategy for comparing images based on pixel equality. /// - /// - Parameter precision: The percentage of pixels that must match. - public static func image(precision: Float) -> Snapshotting { + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1) -> Snapshotting { return .init( pathExtension: "png", - diffing: .image(precision: precision) + diffing: .image(precision: precision, perceptualPrecision: perceptualPrecision) ) } } @@ -52,7 +57,7 @@ private func NSImagePNGRepresentation(_ image: NSImage) -> Data? { return rep.representation(using: .png, properties: [:]) } -private func compare(_ old: NSImage, _ new: NSImage, precision: Float) -> Bool { +private func compare(_ old: NSImage, _ new: NSImage, precision: Float, perceptualPrecision: Float) -> Bool { guard let oldCgImage = old.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return false } guard let newCgImage = new.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return false } guard oldCgImage.width != 0 else { return false } @@ -72,19 +77,42 @@ private func compare(_ old: NSImage, _ new: NSImage, precision: Float) -> Bool { guard let newerContext = context(for: newerCgImage) else { return false } guard let newerData = newerContext.data else { return false } if memcmp(oldData, newerData, byteCount) == 0 { return true } - if precision >= 1 { return false } - let oldRep = NSBitmapImageRep(cgImage: oldCgImage) - let newRep = NSBitmapImageRep(cgImage: newerCgImage) - var differentPixelCount = 0 - let pixelCount = oldRep.pixelsWide * oldRep.pixelsHigh - let threshold = (1 - precision) * Float(pixelCount) - let p1: UnsafeMutablePointer = oldRep.bitmapData! - let p2: UnsafeMutablePointer = newRep.bitmapData! - for offset in 0 ..< pixelCount * 4 { - if p1[offset] != p2[offset] { + if precision >= 1, perceptualPrecision >= 1 { return false } + if perceptualPrecision < 1, #available(macOS 10.13, *) { + let oldImage = CIImage(cgImage: oldCgImage) + let newImage = CIImage(cgImage: newerCgImage) + let perceptualThreshold = (1 - perceptualPrecision) * 100 + guard let filter = CIFilter(name: "CILabDeltaE", parameters: [kCIInputImageKey: oldImage, "inputImage2": newImage]) else { return false } + guard let outputImage = filter.outputImage else { return false } + let pixelCount = oldCgImage.width * oldCgImage.height + var outputPixels = [Float](repeating: 0, count: pixelCount) + CIContext().render( + outputImage, + toBitmap: &outputPixels, + rowBytes: Int(outputImage.extent.width) * MemoryLayout.size, + bounds: outputImage.extent, + format: .Rf, + colorSpace: nil + ) + let pixelCountThreshold = Int((1 - precision) * Float(pixelCount)) + var differentPixelCount = 0 + for pixel in outputPixels { + if pixel > perceptualThreshold { differentPixelCount += 1 + if differentPixelCount > pixelCountThreshold { return false } + } + } + } else { + let oldRep = NSBitmapImageRep(cgImage: oldCgImage).bitmapData! + let newRep = NSBitmapImageRep(cgImage: newerCgImage).bitmapData! + let byteCountThreshold = Int((1 - precision) * Float(byteCount)) + var differentByteCount = 0 + for offset in 0.. byteCountThreshold { return false } + } } - if Float(differentPixelCount) > threshold { return false } } return true } diff --git a/Sources/SnapshotTesting/Snapshotting/NSView.swift b/Sources/SnapshotTesting/Snapshotting/NSView.swift index 292570f2..b0402f92 100644 --- a/Sources/SnapshotTesting/Snapshotting/NSView.swift +++ b/Sources/SnapshotTesting/Snapshotting/NSView.swift @@ -11,9 +11,10 @@ extension Snapshotting where Value == NSView, Format == NSImage { /// /// - Parameters: /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: A view size override. - public static func image(precision: Float = 1, size: CGSize? = nil) -> Snapshotting { - return SimplySnapshotting.image(precision: precision).asyncPullback { view in + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, size: CGSize? = nil) -> Snapshotting { + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision).asyncPullback { view in let initialSize = view.frame.size if let size = size { view.frame.size = size } guard view.frame.width > 0, view.frame.height > 0 else { diff --git a/Sources/SnapshotTesting/Snapshotting/NSViewController.swift b/Sources/SnapshotTesting/Snapshotting/NSViewController.swift index 70d97247..6f316e8a 100644 --- a/Sources/SnapshotTesting/Snapshotting/NSViewController.swift +++ b/Sources/SnapshotTesting/Snapshotting/NSViewController.swift @@ -11,9 +11,10 @@ extension Snapshotting where Value == NSViewController, Format == NSImage { /// /// - Parameters: /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: A view size override. - public static func image(precision: Float = 1, size: CGSize? = nil) -> Snapshotting { - return Snapshotting.image(precision: precision, size: size).pullback { $0.view } + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, size: CGSize? = nil) -> Snapshotting { + return Snapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision, size: size).pullback { $0.view } } } diff --git a/Sources/SnapshotTesting/Snapshotting/SceneKit.swift b/Sources/SnapshotTesting/Snapshotting/SceneKit.swift index 86dc7ff5..42bd21b9 100644 --- a/Sources/SnapshotTesting/Snapshotting/SceneKit.swift +++ b/Sources/SnapshotTesting/Snapshotting/SceneKit.swift @@ -12,9 +12,10 @@ extension Snapshotting where Value == SCNScene, Format == NSImage { /// /// - Parameters: /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: The size of the scene. - public static func image(precision: Float = 1, size: CGSize) -> Snapshotting { - return .scnScene(precision: precision, size: size) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, size: CGSize) -> Snapshotting { + return .scnScene(precision: precision, perceptualPrecision: perceptualPrecision, size: size) } } #elseif os(iOS) || os(tvOS) @@ -23,16 +24,17 @@ extension Snapshotting where Value == SCNScene, Format == UIImage { /// /// - Parameters: /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: The size of the scene. - public static func image(precision: Float = 1, size: CGSize) -> Snapshotting { - return .scnScene(precision: precision, size: size) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, size: CGSize) -> Snapshotting { + return .scnScene(precision: precision, perceptualPrecision: perceptualPrecision, size: size) } } #endif fileprivate extension Snapshotting where Value == SCNScene, Format == Image { - static func scnScene(precision: Float, size: CGSize) -> Snapshotting { - return Snapshotting.image(precision: precision).pullback { scene in + static func scnScene(precision: Float, perceptualPrecision: Float, size: CGSize) -> Snapshotting { + return Snapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision).pullback { scene in let view = SCNView(frame: .init(x: 0, y: 0, width: size.width, height: size.height)) view.scene = scene return view diff --git a/Sources/SnapshotTesting/Snapshotting/SpriteKit.swift b/Sources/SnapshotTesting/Snapshotting/SpriteKit.swift index 8d71ce13..2a1f6036 100644 --- a/Sources/SnapshotTesting/Snapshotting/SpriteKit.swift +++ b/Sources/SnapshotTesting/Snapshotting/SpriteKit.swift @@ -12,9 +12,10 @@ extension Snapshotting where Value == SKScene, Format == NSImage { /// /// - Parameters: /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: The size of the scene. - public static func image(precision: Float = 1, size: CGSize) -> Snapshotting { - return .skScene(precision: precision, size: size) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, size: CGSize) -> Snapshotting { + return .skScene(precision: precision, perceptualPrecision: perceptualPrecision, size: size) } } #elseif os(iOS) || os(tvOS) @@ -23,16 +24,17 @@ extension Snapshotting where Value == SKScene, Format == UIImage { /// /// - Parameters: /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: The size of the scene. - public static func image(precision: Float = 1, size: CGSize) -> Snapshotting { - return .skScene(precision: precision, size: size) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, size: CGSize) -> Snapshotting { + return .skScene(precision: precision, perceptualPrecision: perceptualPrecision, size: size) } } #endif fileprivate extension Snapshotting where Value == SKScene, Format == Image { - static func skScene(precision: Float, size: CGSize) -> Snapshotting { - return Snapshotting.image(precision: precision).pullback { scene in + static func skScene(precision: Float, perceptualPrecision: Float, size: CGSize) -> Snapshotting { + return Snapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision).pullback { scene in let view = SKView(frame: .init(x: 0, y: 0, width: size.width, height: size.height)) view.presentScene(scene) return view diff --git a/Sources/SnapshotTesting/Snapshotting/SwiftUIView.swift b/Sources/SnapshotTesting/Snapshotting/SwiftUIView.swift index ec7bd910..38742895 100644 --- a/Sources/SnapshotTesting/Snapshotting/SwiftUIView.swift +++ b/Sources/SnapshotTesting/Snapshotting/SwiftUIView.swift @@ -28,11 +28,13 @@ extension Snapshotting where Value: SwiftUI.View, Format == UIImage { /// - Parameters: /// - drawHierarchyInKeyWindow: Utilize the simulator's key window in order to render `UIAppearance` and `UIVisualEffect`s. This option requires a host application for your tests and will _not_ work for framework test targets. /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: A view size override. /// - traits: A trait collection override. public static func image( drawHierarchyInKeyWindow: Bool = false, precision: Float = 1, + perceptualPrecision: Float = 1, layout: SwiftUISnapshotLayout = .sizeThatFits, traits: UITraitCollection = .init() ) @@ -51,7 +53,7 @@ extension Snapshotting where Value: SwiftUI.View, Format == UIImage { config = .init(safeArea: .zero, size: size, traits: traits) } - return SimplySnapshotting.image(precision: precision, scale: traits.displayScale).asyncPullback { view in + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision, scale: traits.displayScale).asyncPullback { view in var config = config let controller: UIViewController diff --git a/Sources/SnapshotTesting/Snapshotting/UIBezierPath.swift b/Sources/SnapshotTesting/Snapshotting/UIBezierPath.swift index 826044f4..d21d0cd5 100644 --- a/Sources/SnapshotTesting/Snapshotting/UIBezierPath.swift +++ b/Sources/SnapshotTesting/Snapshotting/UIBezierPath.swift @@ -9,9 +9,11 @@ extension Snapshotting where Value == UIBezierPath, Format == UIImage { /// A snapshot strategy for comparing bezier paths based on pixel equality. /// - /// - Parameter precision: The percentage of pixels that must match. - public static func image(precision: Float = 1, scale: CGFloat = 1) -> Snapshotting { - return SimplySnapshotting.image(precision: precision, scale: scale).pullback { path in + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, scale: CGFloat = 1) -> Snapshotting { + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision, scale: scale).pullback { path in let bounds = path.bounds let format: UIGraphicsImageRendererFormat if #available(iOS 11.0, tvOS 11.0, *) { diff --git a/Sources/SnapshotTesting/Snapshotting/UIImage.swift b/Sources/SnapshotTesting/Snapshotting/UIImage.swift index 4b7c51dc..5b441dd1 100644 --- a/Sources/SnapshotTesting/Snapshotting/UIImage.swift +++ b/Sources/SnapshotTesting/Snapshotting/UIImage.swift @@ -1,17 +1,20 @@ #if os(iOS) || os(tvOS) +import CoreImage import UIKit import XCTest extension Diffing where Value == UIImage { /// A pixel-diffing strategy for UIImage's which requires a 100% match. - public static let image = Diffing.image(precision: 1, scale: nil) + public static let image = Diffing.image() /// A pixel-diffing strategy for UIImage that allows customizing how precise the matching must be. /// - /// - Parameter precision: A value between 0 and 1, where 1 means the images must match 100% of their pixels. - /// - Parameter scale: Scale to use when loading the reference image from disk. If `nil` or the `UITraitCollection`s default value of `0.0`, the screens scale is used. + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) + /// - scale: Scale to use when loading the reference image from disk. If `nil` or the `UITraitCollection`s default value of `0.0`, the screens scale is used. /// - Returns: A new diffing strategy. - public static func image(precision: Float, scale: CGFloat?) -> Diffing { + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, scale: CGFloat? = nil) -> Diffing { let imageScale: CGFloat if let scale = scale, scale != 0.0 { imageScale = scale @@ -23,7 +26,7 @@ extension Diffing where Value == UIImage { toData: { $0.pngData() ?? emptyImage().pngData()! }, fromData: { UIImage(data: $0, scale: imageScale)! } ) { old, new in - guard !compare(old, new, precision: precision) else { return nil } + guard !compare(old, new, precision: precision, perceptualPrecision: perceptualPrecision) else { return nil } let difference = SnapshotTesting.diff(old, new) let message = new.size == old.size ? "Newly-taken snapshot does not match reference." @@ -56,27 +59,29 @@ extension Diffing where Value == UIImage { extension Snapshotting where Value == UIImage, Format == UIImage { /// A snapshot strategy for comparing images based on pixel equality. public static var image: Snapshotting { - return .image(precision: 1, scale: nil) + return .image() } /// A snapshot strategy for comparing images based on pixel equality. /// - /// - Parameter precision: The percentage of pixels that must match. - /// - Parameter scale: The scale of the reference image stored on disk. - public static func image(precision: Float, scale: CGFloat?) -> Snapshotting { + /// - Parameters: + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) + /// - scale: The scale of the reference image stored on disk. + public static func image(precision: Float = 1, perceptualPrecision: Float = 1, scale: CGFloat? = nil) -> Snapshotting { return .init( pathExtension: "png", - diffing: .image(precision: precision, scale: scale) + diffing: .image(precision: precision, perceptualPrecision: perceptualPrecision, scale: scale) ) } } // remap snapshot & reference to same colorspace -let imageContextColorSpace = CGColorSpace(name: CGColorSpace.sRGB) -let imageContextBitsPerComponent = 8 -let imageContextBytesPerPixel = 4 +private let imageContextColorSpace = CGColorSpace(name: CGColorSpace.sRGB) +private let imageContextBitsPerComponent = 8 +private let imageContextBytesPerPixel = 4 -private func compare(_ old: UIImage, _ new: UIImage, precision: Float) -> Bool { +private func compare(_ old: UIImage, _ new: UIImage, precision: Float, perceptualPrecision: Float) -> Bool { guard let oldCgImage = old.cgImage else { return false } guard let newCgImage = new.cgImage else { return false } guard oldCgImage.width != 0 else { return false } @@ -86,7 +91,8 @@ private func compare(_ old: UIImage, _ new: UIImage, precision: Float) -> Bool { guard newCgImage.height != 0 else { return false } guard oldCgImage.height == newCgImage.height else { return false } - let byteCount = imageContextBytesPerPixel * oldCgImage.width * oldCgImage.height + let pixelCount = oldCgImage.width * oldCgImage.height + let byteCount = imageContextBytesPerPixel * pixelCount var oldBytes = [UInt8](repeating: 0, count: byteCount) guard let oldContext = context(for: oldCgImage, data: &oldBytes) else { return false } guard let oldData = oldContext.data else { return false } @@ -99,12 +105,39 @@ private func compare(_ old: UIImage, _ new: UIImage, precision: Float) -> Bool { guard let newerContext = context(for: newerCgImage, data: &newerBytes) else { return false } guard let newerData = newerContext.data else { return false } if memcmp(oldData, newerData, byteCount) == 0 { return true } - if precision >= 1 { return false } - var differentPixelCount = 0 - let threshold = 1 - precision - for byte in 0.. threshold { return false} + if precision >= 1, perceptualPrecision >= 1 { return false } + if perceptualPrecision < 1, #available(tvOS 11.0, *) { + let oldImage = CIImage(cgImage: oldCgImage) + let newImage = CIImage(cgImage: newerCgImage) + guard let filter = CIFilter(name: "CILabDeltaE", parameters: [kCIInputImageKey: oldImage, "inputImage2": newImage]) else { return false } + guard let outputImage = filter.outputImage else { return false } + var outputPixels = [Float32](repeating: 0, count: pixelCount) + CIContext().render( + outputImage, + toBitmap: &outputPixels, + rowBytes: Int(outputImage.extent.width) * MemoryLayout.size, + bounds: outputImage.extent, + format: .Rf, + colorSpace: nil + ) + let pixelCountThreshold = Int((1 - precision) * Float(pixelCount)) + let perceptualThreshold = (1 - perceptualPrecision) * 100 + var differentPixelCount = 0 + for pixel in outputPixels { + if pixel > perceptualThreshold { + differentPixelCount += 1 + if differentPixelCount > pixelCountThreshold { return false } + } + } + } else { + let byteCountThreshold = Int((1 - precision) * Float(byteCount)) + var differentByteCount = 0 + for offset in 0.. byteCountThreshold { return false } + } + } } return true } diff --git a/Sources/SnapshotTesting/Snapshotting/UIView.swift b/Sources/SnapshotTesting/Snapshotting/UIView.swift index fe1e81a5..d2ed6e0f 100644 --- a/Sources/SnapshotTesting/Snapshotting/UIView.swift +++ b/Sources/SnapshotTesting/Snapshotting/UIView.swift @@ -12,17 +12,19 @@ extension Snapshotting where Value == UIView, Format == UIImage { /// - Parameters: /// - drawHierarchyInKeyWindow: Utilize the simulator's key window in order to render `UIAppearance` and `UIVisualEffect`s. This option requires a host application for your tests and will _not_ work for framework test targets. /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: A view size override. /// - traits: A trait collection override. public static func image( drawHierarchyInKeyWindow: Bool = false, precision: Float = 1, + perceptualPrecision: Float = 1, size: CGSize? = nil, traits: UITraitCollection = .init() ) -> Snapshotting { - return SimplySnapshotting.image(precision: precision, scale: traits.displayScale).asyncPullback { view in + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision, scale: traits.displayScale).asyncPullback { view in snapshotView( config: .init(safeArea: .zero, size: size ?? view.frame.size, traits: .init()), drawHierarchyInKeyWindow: drawHierarchyInKeyWindow, diff --git a/Sources/SnapshotTesting/Snapshotting/UIViewController.swift b/Sources/SnapshotTesting/Snapshotting/UIViewController.swift index 736bdcb2..833ec5e0 100644 --- a/Sources/SnapshotTesting/Snapshotting/UIViewController.swift +++ b/Sources/SnapshotTesting/Snapshotting/UIViewController.swift @@ -12,17 +12,19 @@ extension Snapshotting where Value == UIViewController, Format == UIImage { /// - Parameters: /// - config: A set of device configuration settings. /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: A view size override. /// - traits: A trait collection override. public static func image( on config: ViewImageConfig, precision: Float = 1, + perceptualPrecision: Float = 1, size: CGSize? = nil, traits: UITraitCollection = .init() ) -> Snapshotting { - return SimplySnapshotting.image(precision: precision, scale: traits.displayScale).asyncPullback { viewController in + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision, scale: traits.displayScale).asyncPullback { viewController in snapshotView( config: size.map { .init(safeArea: config.safeArea, size: $0, traits: config.traits) } ?? config, drawHierarchyInKeyWindow: false, @@ -38,17 +40,19 @@ extension Snapshotting where Value == UIViewController, Format == UIImage { /// - Parameters: /// - drawHierarchyInKeyWindow: Utilize the simulator's key window in order to render `UIAppearance` and `UIVisualEffect`s. This option requires a host application for your tests and will _not_ work for framework test targets. /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) /// - size: A view size override. /// - traits: A trait collection override. public static func image( drawHierarchyInKeyWindow: Bool = false, precision: Float = 1, + perceptualPrecision: Float = 1, size: CGSize? = nil, traits: UITraitCollection = .init() ) -> Snapshotting { - return SimplySnapshotting.image(precision: precision, scale: traits.displayScale).asyncPullback { viewController in + return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision, scale: traits.displayScale).asyncPullback { viewController in snapshotView( config: .init(safeArea: .zero, size: size, traits: traits), drawHierarchyInKeyWindow: drawHierarchyInKeyWindow, diff --git a/Tests/SnapshotTestingTests/SnapshotTestingTests.swift b/Tests/SnapshotTestingTests/SnapshotTestingTests.swift index a5fe97f1..3a5ced4d 100644 --- a/Tests/SnapshotTestingTests/SnapshotTestingTests.swift +++ b/Tests/SnapshotTestingTests/SnapshotTestingTests.swift @@ -43,7 +43,7 @@ final class SnapshotTestingTests: XCTestCase { """) } - @available(macOS 10.13, *) + @available(macOS 10.13, tvOS 11.0, *) func testAnyAsJson() throws { struct User: Encodable { let id: Int, name: String, bio: String } let user = User(id: 1, name: "Blobby", bio: "Blobbed around the world.") From 2da95761cfc7644b821de729502869a48d0d069c Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Sun, 21 Aug 2022 22:53:21 -0400 Subject: [PATCH 2/7] Use CIColorThreshold and CIAreaAverage for a 70% faster image diff on iOS 14, tvOS 14, and macOS 11 --- .../Snapshotting/NSImage.swift | 64 +++++++++++++------ .../Snapshotting/UIImage.swift | 62 ++++++++++++------ 2 files changed, 85 insertions(+), 41 deletions(-) diff --git a/Sources/SnapshotTesting/Snapshotting/NSImage.swift b/Sources/SnapshotTesting/Snapshotting/NSImage.swift index 9090729b..02185db1 100644 --- a/Sources/SnapshotTesting/Snapshotting/NSImage.swift +++ b/Sources/SnapshotTesting/Snapshotting/NSImage.swift @@ -1,5 +1,5 @@ #if os(macOS) -import CoreImage +import CoreImage.CIFilterBuiltins import Cocoa import XCTest @@ -60,10 +60,8 @@ private func NSImagePNGRepresentation(_ image: NSImage) -> Data? { private func compare(_ old: NSImage, _ new: NSImage, precision: Float, perceptualPrecision: Float) -> Bool { guard let oldCgImage = old.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return false } guard let newCgImage = new.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return false } - guard oldCgImage.width != 0 else { return false } guard newCgImage.width != 0 else { return false } guard oldCgImage.width == newCgImage.width else { return false } - guard oldCgImage.height != 0 else { return false } guard newCgImage.height != 0 else { return false } guard oldCgImage.height == newCgImage.height else { return false } guard let oldContext = context(for: oldCgImage) else { return false } @@ -82,24 +80,48 @@ private func compare(_ old: NSImage, _ new: NSImage, precision: Float, perceptua let oldImage = CIImage(cgImage: oldCgImage) let newImage = CIImage(cgImage: newerCgImage) let perceptualThreshold = (1 - perceptualPrecision) * 100 - guard let filter = CIFilter(name: "CILabDeltaE", parameters: [kCIInputImageKey: oldImage, "inputImage2": newImage]) else { return false } - guard let outputImage = filter.outputImage else { return false } - let pixelCount = oldCgImage.width * oldCgImage.height - var outputPixels = [Float](repeating: 0, count: pixelCount) - CIContext().render( - outputImage, - toBitmap: &outputPixels, - rowBytes: Int(outputImage.extent.width) * MemoryLayout.size, - bounds: outputImage.extent, - format: .Rf, - colorSpace: nil - ) - let pixelCountThreshold = Int((1 - precision) * Float(pixelCount)) - var differentPixelCount = 0 - for pixel in outputPixels { - if pixel > perceptualThreshold { - differentPixelCount += 1 - if differentPixelCount > pixelCountThreshold { return false } + if #available(macOS 11.0, *) { + let deltaFilter = CIFilter.labDeltaE() + deltaFilter.inputImage = oldImage + deltaFilter.image2 = newImage + let thresholdFilter = CIFilter.colorThreshold() + thresholdFilter.inputImage = deltaFilter.outputImage + thresholdFilter.threshold = perceptualThreshold + let averageFilter = CIFilter.areaAverage() + averageFilter.inputImage = thresholdFilter.outputImage + averageFilter.extent = CGRect(x: 0, y: 0, width: oldCgImage.width, height: oldCgImage.height) + guard let outputImage = averageFilter.outputImage else { return false } + var averagePixel: Float = 0 + CIContext().render( + outputImage, + toBitmap: &averagePixel, + rowBytes: MemoryLayout.size, + bounds: CGRect(x: 0, y: 0, width: 1, height: 1), + format: .Rf, + colorSpace: nil + ) + let pixelCountThreshold = 1 - precision + if averagePixel > pixelCountThreshold { return false } + } else { + guard let filter = CIFilter(name: "CILabDeltaE", parameters: [kCIInputImageKey: oldImage, "inputImage2": newImage]) else { return false } + guard let outputImage = filter.outputImage else { return false } + let pixelCount = oldCgImage.width * oldCgImage.height + var outputPixels = [Float](repeating: 0, count: pixelCount) + CIContext().render( + outputImage, + toBitmap: &outputPixels, + rowBytes: Int(outputImage.extent.width) * MemoryLayout.size, + bounds: outputImage.extent, + format: .Rf, + colorSpace: nil + ) + let pixelCountThreshold = Int((1 - precision) * Float(pixelCount)) + var differentPixelCount = 0 + for pixel in outputPixels { + if pixel > perceptualThreshold { + differentPixelCount += 1 + if differentPixelCount > pixelCountThreshold { return false } + } } } } else { diff --git a/Sources/SnapshotTesting/Snapshotting/UIImage.swift b/Sources/SnapshotTesting/Snapshotting/UIImage.swift index 5b441dd1..d4e6c235 100644 --- a/Sources/SnapshotTesting/Snapshotting/UIImage.swift +++ b/Sources/SnapshotTesting/Snapshotting/UIImage.swift @@ -1,5 +1,5 @@ #if os(iOS) || os(tvOS) -import CoreImage +import CoreImage.CIFilterBuiltins import UIKit import XCTest @@ -84,10 +84,8 @@ private let imageContextBytesPerPixel = 4 private func compare(_ old: UIImage, _ new: UIImage, precision: Float, perceptualPrecision: Float) -> Bool { guard let oldCgImage = old.cgImage else { return false } guard let newCgImage = new.cgImage else { return false } - guard oldCgImage.width != 0 else { return false } guard newCgImage.width != 0 else { return false } guard oldCgImage.width == newCgImage.width else { return false } - guard oldCgImage.height != 0 else { return false } guard newCgImage.height != 0 else { return false } guard oldCgImage.height == newCgImage.height else { return false } @@ -109,24 +107,48 @@ private func compare(_ old: UIImage, _ new: UIImage, precision: Float, perceptua if perceptualPrecision < 1, #available(tvOS 11.0, *) { let oldImage = CIImage(cgImage: oldCgImage) let newImage = CIImage(cgImage: newerCgImage) - guard let filter = CIFilter(name: "CILabDeltaE", parameters: [kCIInputImageKey: oldImage, "inputImage2": newImage]) else { return false } - guard let outputImage = filter.outputImage else { return false } - var outputPixels = [Float32](repeating: 0, count: pixelCount) - CIContext().render( - outputImage, - toBitmap: &outputPixels, - rowBytes: Int(outputImage.extent.width) * MemoryLayout.size, - bounds: outputImage.extent, - format: .Rf, - colorSpace: nil - ) - let pixelCountThreshold = Int((1 - precision) * Float(pixelCount)) let perceptualThreshold = (1 - perceptualPrecision) * 100 - var differentPixelCount = 0 - for pixel in outputPixels { - if pixel > perceptualThreshold { - differentPixelCount += 1 - if differentPixelCount > pixelCountThreshold { return false } + if #available(iOS 14.0, tvOS 14.0, *) { + let deltaFilter = CIFilter.labDeltaE() + deltaFilter.inputImage = oldImage + deltaFilter.image2 = newImage + let thresholdFilter = CIFilter.colorThreshold() + thresholdFilter.inputImage = deltaFilter.outputImage + thresholdFilter.threshold = perceptualThreshold + let averageFilter = CIFilter.areaAverage() + averageFilter.inputImage = thresholdFilter.outputImage + averageFilter.extent = CGRect(x: 0, y: 0, width: oldCgImage.width, height: oldCgImage.height) + guard let outputImage = averageFilter.outputImage else { return false } + var averagePixel: Float = 0 + CIContext().render( + outputImage, + toBitmap: &averagePixel, + rowBytes: MemoryLayout.size, + bounds: CGRect(x: 0, y: 0, width: 1, height: 1), + format: .Rf, + colorSpace: nil + ) + let pixelCountThreshold = 1 - precision + if averagePixel > pixelCountThreshold { return false } + } else { + guard let filter = CIFilter(name: "CILabDeltaE", parameters: [kCIInputImageKey: oldImage, "inputImage2": newImage]) else { return false } + guard let outputImage = filter.outputImage else { return false } + var outputPixels = [Float32](repeating: 0, count: pixelCount) + CIContext().render( + outputImage, + toBitmap: &outputPixels, + rowBytes: Int(outputImage.extent.width) * MemoryLayout.size, + bounds: outputImage.extent, + format: .Rf, + colorSpace: nil + ) + let pixelCountThreshold = Int((1 - precision) * Float(pixelCount)) + var differentPixelCount = 0 + for pixel in outputPixels { + if pixel > perceptualThreshold { + differentPixelCount += 1 + if differentPixelCount > pixelCountThreshold { return false } + } } } } else { From f9b9f9568216050c00fc61a20d4fd7a88be04a5a Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Sat, 10 Sep 2022 22:28:46 -0400 Subject: [PATCH 3/7] Add a unit test demonstrating the difference between pixel precision and perceptual precision --- .../SnapshotTestingTests.swift | 18 ++++++++++++++++++ .../testImagePrecision.reference.png | Bin 0 -> 34448 bytes .../testImagePrecision.exact.png | Bin 0 -> 34448 bytes .../testImagePrecision.perceptual.png | Bin 0 -> 35000 bytes 4 files changed, 18 insertions(+) create mode 100644 Tests/SnapshotTestingTests/__Fixtures__/testImagePrecision.reference.png create mode 100644 Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testImagePrecision.exact.png create mode 100644 Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testImagePrecision.perceptual.png diff --git a/Tests/SnapshotTestingTests/SnapshotTestingTests.swift b/Tests/SnapshotTestingTests/SnapshotTestingTests.swift index 3a5ced4d..93ce66a5 100644 --- a/Tests/SnapshotTestingTests/SnapshotTestingTests.swift +++ b/Tests/SnapshotTestingTests/SnapshotTestingTests.swift @@ -289,6 +289,24 @@ final class SnapshotTestingTests: XCTestCase { #endif } + func testImagePrecision() throws { + #if os(iOS) || os(tvOS) || os(macOS) + let imageURL = URL(fileURLWithPath: String(#file), isDirectory: false) + .deletingLastPathComponent() + .appendingPathComponent("__Fixtures__/testImagePrecision.reference.png") + #if os(iOS) || os(tvOS) + let image = try XCTUnwrap(UIImage(contentsOfFile: imageURL.path)) + #elseif os(macOS) + let image = try XCTUnwrap(NSImage(byReferencing: imageURL)) + #endif + + assertSnapshot(matching: image, as: .image(precision: 0.995), named: "exact") + if #available(iOS 11.0, tvOS 11.0, macOS 10.13, *) { + assertSnapshot(matching: image, as: .image(perceptualPrecision: 0.98), named: "perceptual") + } + #endif + } + func testSCNView() { // #if os(iOS) || os(macOS) || os(tvOS) // // NB: CircleCI crashes while trying to instantiate SCNView. diff --git a/Tests/SnapshotTestingTests/__Fixtures__/testImagePrecision.reference.png b/Tests/SnapshotTestingTests/__Fixtures__/testImagePrecision.reference.png new file mode 100644 index 0000000000000000000000000000000000000000..4f4ced61d7e0f0815a4407a8f3257e3dd244394e GIT binary patch literal 34448 zcmeIbX;hM1*gkG%M;p~9&78{0JZh%pEMlk9%F<4jvsjW^&SZ`VWS!C+uu07vn>2GE zXHx+ygmTObaY76-oDmfP5%@oNhWGvOe*Ay=t)*+Rgw6A8_HYl^ecgNS=l*#IyUiO^ zHb_ZHZ9aYK#04oS=@}`hbtZDZ0VS=JBa(k>!Y|nUAywX~Iu3j|;p=+Z@7y`5-+}jX zQfm^fOUXzs0bVM=OG;{O!5XQx!2dOpvI6OUzm=XTSo`n$btaMv-*uM;N=eyBoj!5w zV)U9Rs_au=w@W4?piSndly5xRqkZgllBV22Ik~O-{1p%1x_xl(ZMme|K2m=wqAJZ! ztod@xXse9O_AkdfuYcY(0iHZs^eZyrQdESCV-%)lc-{)MBV=IG3m$^t4k0>00l@?J zQl-{N%g8Bc+T4x|NJ~~Mdilj5m~S@3&Dbu z*dz_GgV~S2*tx7Y|2VOL2G;XcLo9SNo)lS)n$2f*Ssl9hd}C^|*OU+As`emXH1{%2 zs^`i$6RolEQbRb#`>72!w-$~&V#JnA^DgrY6w{jfp2Y7$iPXSo%YWOXIxg)kUZRlf zA#;z|k}nfgCk#odN6N!X>Cqq`6@ z;f(D?W-W>GIN?kb-V!IA4o!2)owzv9LR(C{;Yayf4)zlzH^Dyb9uD&yKjWgJ4SsLx zy2XoRwe{~o2|Fm`<0z=g7f!M78pK`MLIm?4gUx+pe-%3-CKTZ~dD2e!5}s2QnhJb& z3P&a@?eqstx{*>tZoX8Tjsd^<02=XeoJ{~P|9}-9$-VBm^exl+#V5K`{?d1LqMen` z5YY3iJ@R%?F6U`CPurS(pTR|mxy-|&)X+HSiA37W&MP1YwS|ITZo{ia)qhgkGPrMe z=BZa&^TXd244!~_ALKh7iR@bD2c+S0R#%)~6GM≪)gT=Nv4Vy?3GUQP@c@Mg#^< z&580!@SXZ>^{BS*y^5umR+Bg9t&3V_Jz@Wr=x9stpd+B0O)sMRKB=1=3X9*E0!;%& zdNNcf%9)Krqr_cZ(L`8HiC3^{)DTS8s`>HUJ=CH<%4C>FG)3ci$#^pzjbFD|meO#& zsP`n$j3GX0xzz<%>HQp}ZuW;L6TdvlUxa~SC>Y*ETBg=uwuuP}MIK64+p2_{z01tq z>TmXG7twK<;FyA1CZUEzYQZ-;T<`Eb@Eni%aDTlB!Ci0OUB01DS9@?Me2`7XAS2Q| zT83YR=P*dR}3)AP?BwYPMeIlW-;o%y9x6CoD!o zgm=KaJ24o+Tu$U0JW*Y&d^}}8

2(GN?j?wDTy1(Y~0J?RRf%y;NRlve`#ux{g~j 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≪)gT=Nv4Vy?3GUQP@c@Mg#^< z&580!@SXZ>^{BS*y^5umR+Bg9t&3V_Jz@Wr=x9stpd+B0O)sMRKB=1=3X9*E0!;%& zdNNcf%9)Krqr_cZ(L`8HiC3^{)DTS8s`>HUJ=CH<%4C>FG)3ci$#^pzjbFD|meO#& zsP`n$j3GX0xzz<%>HQp}ZuW;L6TdvlUxa~SC>Y*ETBg=uwuuP}MIK64+p2_{z01tq z>TmXG7twK<;FyA1CZUEzYQZ-;T<`Eb@Eni%aDTlB!Ci0OUB01DS9@?Me2`7XAS2Q| zT83YR=P*dR}3)AP?BwYPMeIlW-;o%y9x6CoD!o zgm=KaJ24o+Tu$U0JW*Y&d^}}8

2(GN?j?wDTy1(Y~0J?RRf%y;NRlve`#ux{g~j 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

-t8E*w<`A{#_>v?5Ej&!e$T$nTA+oT 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 Date: Mon, 12 Sep 2022 10:08:17 -0400 Subject: [PATCH 4/7] Update the reference image for the image precision test --- .../testImagePrecision.reference.png | Bin 34448 -> 36125 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/SnapshotTestingTests/__Fixtures__/testImagePrecision.reference.png b/Tests/SnapshotTestingTests/__Fixtures__/testImagePrecision.reference.png index 4f4ced61d7e0f0815a4407a8f3257e3dd244394e..e9d01c5fc683268bc944148628933a5f8b6fdcac 100644 GIT binary patch literal 36125 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 KDLj1P=Klo%Vh7Lw literal 34448 zcmeIbX;hM1*gkG%M;p~9&78{0JZh%pEMlk9%F<4jvsjW^&SZ`VWS!C+uu07vn>2GE zXHx+ygmTObaY76-oDmfP5%@oNhWGvOe*Ay=t)*+Rgw6A8_HYl^ecgNS=l*#IyUiO^ zHb_ZHZ9aYK#04oS=@}`hbtZDZ0VS=JBa(k>!Y|nUAywX~Iu3j|;p=+Z@7y`5-+}jX zQfm^fOUXzs0bVM=OG;{O!5XQx!2dOpvI6OUzm=XTSo`n$btaMv-*uM;N=eyBoj!5w zV)U9Rs_au=w@W4?piSndly5xRqkZgllBV22Ik~O-{1p%1x_xl(ZMme|K2m=wqAJZ! ztod@xXse9O_AkdfuYcY(0iHZs^eZyrQdESCV-%)lc-{)MBV=IG3m$^t4k0>00l@?J zQl-{N%g8Bc+T4x|NJ~~Mdilj5m~S@3&Dbu z*dz_GgV~S2*tx7Y|2VOL2G;XcLo9SNo)lS)n$2f*Ssl9hd}C^|*OU+As`emXH1{%2 zs^`i$6RolEQbRb#`>72!w-$~&V#JnA^DgrY6w{jfp2Y7$iPXSo%YWOXIxg)kUZRlf zA#;z|k}nfgCk#odN6N!X>Cqq`6@ z;f(D?W-W>GIN?kb-V!IA4o!2)owzv9LR(C{;Yayf4)zlzH^Dyb9uD&yKjWgJ4SsLx zy2XoRwe{~o2|Fm`<0z=g7f!M78pK`MLIm?4gUx+pe-%3-CKTZ~dD2e!5}s2QnhJb& z3P&a@?eqstx{*>tZoX8Tjsd^<02=XeoJ{~P|9}-9$-VBm^exl+#V5K`{?d1LqMen` z5YY3iJ@R%?F6U`CPurS(pTR|mxy-|&)X+HSiA37W&MP1YwS|ITZo{ia)qhgkGPrMe z=BZa&^TXd244!~_ALKh7iR@bD2c+S0R#%)~6GM≪)gT=Nv4Vy?3GUQP@c@Mg#^< z&580!@SXZ>^{BS*y^5umR+Bg9t&3V_Jz@Wr=x9stpd+B0O)sMRKB=1=3X9*E0!;%& zdNNcf%9)Krqr_cZ(L`8HiC3^{)DTS8s`>HUJ=CH<%4C>FG)3ci$#^pzjbFD|meO#& zsP`n$j3GX0xzz<%>HQp}ZuW;L6TdvlUxa~SC>Y*ETBg=uwuuP}MIK64+p2_{z01tq z>TmXG7twK<;FyA1CZUEzYQZ-;T<`Eb@Eni%aDTlB!Ci0OUB01DS9@?Me2`7XAS2Q| zT83YR=P*dR}3)AP?BwYPMeIlW-;o%y9x6CoD!o zgm=KaJ24o+Tu$U0JW*Y&d^}}8

2(GN?j?wDTy1(Y~0J?RRf%y;NRlve`#ux{g~j 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 Date: Mon, 12 Sep 2022 19:22:35 -0400 Subject: [PATCH 5/7] Backport the threshold filter to macOS 10.13 by creating a CIImageProcessorKernel implementation --- .../Snapshotting/NSImage.swift | 81 +++++------- .../Snapshotting/UIImage.swift | 119 +++++++++++------- .../testImagePrecision.reference.png | Bin 36125 -> 28029 bytes .../testImagePrecision.exact.png | Bin 34448 -> 28872 bytes .../testImagePrecision.perceptual.png | Bin 35000 -> 28319 bytes 5 files changed, 106 insertions(+), 94 deletions(-) diff --git a/Sources/SnapshotTesting/Snapshotting/NSImage.swift b/Sources/SnapshotTesting/Snapshotting/NSImage.swift index 02185db1..ec43acd5 100644 --- a/Sources/SnapshotTesting/Snapshotting/NSImage.swift +++ b/Sources/SnapshotTesting/Snapshotting/NSImage.swift @@ -77,53 +77,40 @@ private func compare(_ old: NSImage, _ new: NSImage, precision: Float, perceptua if memcmp(oldData, newerData, byteCount) == 0 { return true } if precision >= 1, perceptualPrecision >= 1 { return false } if perceptualPrecision < 1, #available(macOS 10.13, *) { - let oldImage = CIImage(cgImage: oldCgImage) - let newImage = CIImage(cgImage: newerCgImage) - let perceptualThreshold = (1 - perceptualPrecision) * 100 - if #available(macOS 11.0, *) { - let deltaFilter = CIFilter.labDeltaE() - deltaFilter.inputImage = oldImage - deltaFilter.image2 = newImage - let thresholdFilter = CIFilter.colorThreshold() - thresholdFilter.inputImage = deltaFilter.outputImage - thresholdFilter.threshold = perceptualThreshold - let averageFilter = CIFilter.areaAverage() - averageFilter.inputImage = thresholdFilter.outputImage - averageFilter.extent = CGRect(x: 0, y: 0, width: oldCgImage.width, height: oldCgImage.height) - guard let outputImage = averageFilter.outputImage else { return false } - var averagePixel: Float = 0 - CIContext().render( - outputImage, - toBitmap: &averagePixel, - rowBytes: MemoryLayout.size, - bounds: CGRect(x: 0, y: 0, width: 1, height: 1), - format: .Rf, - colorSpace: nil - ) - let pixelCountThreshold = 1 - precision - if averagePixel > pixelCountThreshold { return false } - } else { - guard let filter = CIFilter(name: "CILabDeltaE", parameters: [kCIInputImageKey: oldImage, "inputImage2": newImage]) else { return false } - guard let outputImage = filter.outputImage else { return false } - let pixelCount = oldCgImage.width * oldCgImage.height - var outputPixels = [Float](repeating: 0, count: pixelCount) - CIContext().render( - outputImage, - toBitmap: &outputPixels, - rowBytes: Int(outputImage.extent.width) * MemoryLayout.size, - bounds: outputImage.extent, - format: .Rf, - colorSpace: nil - ) - let pixelCountThreshold = Int((1 - precision) * Float(pixelCount)) - var differentPixelCount = 0 - for pixel in outputPixels { - if pixel > perceptualThreshold { - differentPixelCount += 1 - if differentPixelCount > pixelCountThreshold { return false } - } - } - } + let deltaFilter = CIFilter( + name: "CILabDeltaE", + parameters: [ + kCIInputImageKey: CIImage(cgImage: newCgImage), + "inputImage2": CIImage(cgImage: oldCgImage) + ] + ) + guard let deltaOutputImage = deltaFilter?.outputImage else { return false } + let extent = CGRect(x: 0, y: 0, width: oldCgImage.width, height: oldCgImage.height) + let thresholdOutputImage = try? ThresholdImageProcessorKernel.apply( + withExtent: extent, + inputs: [deltaOutputImage], + arguments: [ThresholdImageProcessorKernel.inputThresholdKey: (1 - perceptualPrecision) * 100] + ) + guard let thresholdOutputImage = thresholdOutputImage else { return false } + let averageFilter = CIFilter( + name: "CIAreaAverage", + parameters: [ + kCIInputImageKey: thresholdOutputImage, + kCIInputExtentKey: extent + ] + ) + guard let averageOutputImage = averageFilter?.outputImage else { return false } + var averagePixel: Float = 0 + CIContext(options: [.workingColorSpace: NSNull(), .outputColorSpace: NSNull()]).render( + averageOutputImage, + toBitmap: &averagePixel, + rowBytes: MemoryLayout.size, + bounds: CGRect(x: 0, y: 0, width: 1, height: 1), + format: .Rf, + colorSpace: nil + ) + let pixelCountThreshold = 1 - precision + if averagePixel > pixelCountThreshold { return false } } else { let oldRep = NSBitmapImageRep(cgImage: oldCgImage).bitmapData! let newRep = NSBitmapImageRep(cgImage: newerCgImage).bitmapData! diff --git a/Sources/SnapshotTesting/Snapshotting/UIImage.swift b/Sources/SnapshotTesting/Snapshotting/UIImage.swift index d4e6c235..1d88b590 100644 --- a/Sources/SnapshotTesting/Snapshotting/UIImage.swift +++ b/Sources/SnapshotTesting/Snapshotting/UIImage.swift @@ -104,53 +104,41 @@ private func compare(_ old: UIImage, _ new: UIImage, precision: Float, perceptua guard let newerData = newerContext.data else { return false } if memcmp(oldData, newerData, byteCount) == 0 { return true } if precision >= 1, perceptualPrecision >= 1 { return false } - if perceptualPrecision < 1, #available(tvOS 11.0, *) { - let oldImage = CIImage(cgImage: oldCgImage) - let newImage = CIImage(cgImage: newerCgImage) - let perceptualThreshold = (1 - perceptualPrecision) * 100 - if #available(iOS 14.0, tvOS 14.0, *) { - let deltaFilter = CIFilter.labDeltaE() - deltaFilter.inputImage = oldImage - deltaFilter.image2 = newImage - let thresholdFilter = CIFilter.colorThreshold() - thresholdFilter.inputImage = deltaFilter.outputImage - thresholdFilter.threshold = perceptualThreshold - let averageFilter = CIFilter.areaAverage() - averageFilter.inputImage = thresholdFilter.outputImage - averageFilter.extent = CGRect(x: 0, y: 0, width: oldCgImage.width, height: oldCgImage.height) - guard let outputImage = averageFilter.outputImage else { return false } - var averagePixel: Float = 0 - CIContext().render( - outputImage, - toBitmap: &averagePixel, - rowBytes: MemoryLayout.size, - bounds: CGRect(x: 0, y: 0, width: 1, height: 1), - format: .Rf, - colorSpace: nil - ) - let pixelCountThreshold = 1 - precision - if averagePixel > pixelCountThreshold { return false } - } else { - guard let filter = CIFilter(name: "CILabDeltaE", parameters: [kCIInputImageKey: oldImage, "inputImage2": newImage]) else { return false } - guard let outputImage = filter.outputImage else { return false } - var outputPixels = [Float32](repeating: 0, count: pixelCount) - CIContext().render( - outputImage, - toBitmap: &outputPixels, - rowBytes: Int(outputImage.extent.width) * MemoryLayout.size, - bounds: outputImage.extent, - format: .Rf, - colorSpace: nil - ) - let pixelCountThreshold = Int((1 - precision) * Float(pixelCount)) - var differentPixelCount = 0 - for pixel in outputPixels { - if pixel > perceptualThreshold { - differentPixelCount += 1 - if differentPixelCount > pixelCountThreshold { return false } - } - } - } + if perceptualPrecision < 1, #available(iOS 11.0, tvOS 11.0, *) { + let deltaFilter = CIFilter( + name: "CILabDeltaE", + parameters: [ + kCIInputImageKey: CIImage(cgImage: newCgImage), + "inputImage2": CIImage(cgImage: oldCgImage) + ] + ) + guard let deltaOutputImage = deltaFilter?.outputImage else { return false } + let extent = CGRect(x: 0, y: 0, width: oldCgImage.width, height: oldCgImage.height) + let thresholdOutputImage = try? ThresholdImageProcessorKernel.apply( + withExtent: extent, + inputs: [deltaOutputImage], + arguments: [ThresholdImageProcessorKernel.inputThresholdKey: (1 - perceptualPrecision) * 100] + ) + guard let thresholdOutputImage = thresholdOutputImage else { return false } + let averageFilter = CIFilter( + name: "CIAreaAverage", + parameters: [ + kCIInputImageKey: thresholdOutputImage, + kCIInputExtentKey: extent + ] + ) + guard let averageOutputImage = averageFilter?.outputImage else { return false } + var averagePixel: Float = 0 + CIContext(options: [.workingColorSpace: NSNull(), .outputColorSpace: NSNull()]).render( + averageOutputImage, + toBitmap: &averagePixel, + rowBytes: MemoryLayout.size, + bounds: CGRect(x: 0, y: 0, width: 1, height: 1), + format: .Rf, + colorSpace: nil + ) + let pixelCountThreshold = 1 - precision + if averagePixel > pixelCountThreshold { return false } } else { let byteCountThreshold = Int((1 - precision) * Float(byteCount)) var differentByteCount = 0 @@ -195,3 +183,40 @@ private func diff(_ old: UIImage, _ new: UIImage) -> UIImage { return differenceImage } #endif + +#if os(iOS) || os(tvOS) || os(macOS) +import CoreImage.CIKernel +import MetalPerformanceShaders + +// Copied from https://developer.apple.com/documentation/coreimage/ciimageprocessorkernel +@available(iOS 10.0, tvOS 10.0, macOS 10.13, *) +final class ThresholdImageProcessorKernel: CIImageProcessorKernel { + static let inputThresholdKey = "thresholdValue" + static let device = MTLCreateSystemDefaultDevice() + + override class func process(with inputs: [CIImageProcessorInput]?, arguments: [String: Any]?, output: CIImageProcessorOutput) throws { + guard + let device = device, + let commandBuffer = output.metalCommandBuffer, + let input = inputs?.first, + let sourceTexture = input.metalTexture, + let destinationTexture = output.metalTexture, + let thresholdValue = arguments?[inputThresholdKey] as? Float else { + return + } + + let threshold = MPSImageThresholdBinary( + device: device, + thresholdValue: thresholdValue, + maximumValue: 1.0, + linearGrayColorTransform: nil + ) + + threshold.encode( + commandBuffer: commandBuffer, + sourceTexture: sourceTexture, + destinationTexture: destinationTexture + ) + } +} +#endif diff --git a/Tests/SnapshotTestingTests/__Fixtures__/testImagePrecision.reference.png b/Tests/SnapshotTestingTests/__Fixtures__/testImagePrecision.reference.png index e9d01c5fc683268bc944148628933a5f8b6fdcac..7f3ac46bf02aaf240aa51a0020acf5fef3dfa6e1 100644 GIT binary patch literal 28029 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 KDLj1P=Klo%Vh7Lw diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testImagePrecision.exact.png b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testImagePrecision.exact.png index 4f4ced61d7e0f0815a4407a8f3257e3dd244394e..a62a125ad02b8c029301f67e3d9fec890eab6bbc 100644 GIT binary patch literal 28872 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 HINbjqR4iQ3 literal 34448 zcmeIbX;hM1*gkG%M;p~9&78{0JZh%pEMlk9%F<4jvsjW^&SZ`VWS!C+uu07vn>2GE zXHx+ygmTObaY76-oDmfP5%@oNhWGvOe*Ay=t)*+Rgw6A8_HYl^ecgNS=l*#IyUiO^ zHb_ZHZ9aYK#04oS=@}`hbtZDZ0VS=JBa(k>!Y|nUAywX~Iu3j|;p=+Z@7y`5-+}jX zQfm^fOUXzs0bVM=OG;{O!5XQx!2dOpvI6OUzm=XTSo`n$btaMv-*uM;N=eyBoj!5w zV)U9Rs_au=w@W4?piSndly5xRqkZgllBV22Ik~O-{1p%1x_xl(ZMme|K2m=wqAJZ! ztod@xXse9O_AkdfuYcY(0iHZs^eZyrQdESCV-%)lc-{)MBV=IG3m$^t4k0>00l@?J zQl-{N%g8Bc+T4x|NJ~~Mdilj5m~S@3&Dbu z*dz_GgV~S2*tx7Y|2VOL2G;XcLo9SNo)lS)n$2f*Ssl9hd}C^|*OU+As`emXH1{%2 zs^`i$6RolEQbRb#`>72!w-$~&V#JnA^DgrY6w{jfp2Y7$iPXSo%YWOXIxg)kUZRlf zA#;z|k}nfgCk#odN6N!X>Cqq`6@ z;f(D?W-W>GIN?kb-V!IA4o!2)owzv9LR(C{;Yayf4)zlzH^Dyb9uD&yKjWgJ4SsLx zy2XoRwe{~o2|Fm`<0z=g7f!M78pK`MLIm?4gUx+pe-%3-CKTZ~dD2e!5}s2QnhJb& z3P&a@?eqstx{*>tZoX8Tjsd^<02=XeoJ{~P|9}-9$-VBm^exl+#V5K`{?d1LqMen` z5YY3iJ@R%?F6U`CPurS(pTR|mxy-|&)X+HSiA37W&MP1YwS|ITZo{ia)qhgkGPrMe z=BZa&^TXd244!~_ALKh7iR@bD2c+S0R#%)~6GM≪)gT=Nv4Vy?3GUQP@c@Mg#^< z&580!@SXZ>^{BS*y^5umR+Bg9t&3V_Jz@Wr=x9stpd+B0O)sMRKB=1=3X9*E0!;%& zdNNcf%9)Krqr_cZ(L`8HiC3^{)DTS8s`>HUJ=CH<%4C>FG)3ci$#^pzjbFD|meO#& zsP`n$j3GX0xzz<%>HQp}ZuW;L6TdvlUxa~SC>Y*ETBg=uwuuP}MIK64+p2_{z01tq z>TmXG7twK<;FyA1CZUEzYQZ-;T<`Eb@Eni%aDTlB!Ci0OUB01DS9@?Me2`7XAS2Q| zT83YR=P*dR}3)AP?BwYPMeIlW-;o%y9x6CoD!o zgm=KaJ24o+Tu$U0JW*Y&d^}}8

2(GN?j?wDTy1(Y~0J?RRf%y;NRlve`#ux{g~j z2?%hY3x0`ALH@KuUKMh=K(8r<`_(LC-rPYBlE5N%U{9lTpkqv{)0QO!>*p5yVhyHD zNH-AC2exnO74D>sPA>Fz4J>@TCW;#9$%_oO7`dX4JA_Ye%bW~ZR^h^d$qm(4C)wU= z?v?J@NUIsAme-80N41Ib>0(Sab;>WWXX9iU>sqosZsD~-**Qy##aJ465elwde3%w@ zwGLiCvd*BMGFU1CqX5kctQ!pBd|Hsc>cKU~*1KjehD^gucZZ??8SqV;3|elHwVsWq z1{JAo+>N3814d@bY2>tH?6-kx=oJvmE;+AA zR^9admvcmvh>1e$97St``CsNAJ&wM#&BIevPXdJuXD8> ziqWt1GgQ3hpHXt;t%Sc!@$Uz}`kaHSKDWYZKBJ<>Gm+N`7K?rMO7K#8@S>TkaW5Xs zeczQ!fuH+u8RD~TawJoKaRfV;j#16TPWh5_A?yvZ6^9Pvw)SZ%h&5WaR`t=v*aYi^ z=g`=0ONa1hJt>r?U&ix|SG=Z?KEej52Tjn-uTvsp%br>X~ae$kaMf zAIZA*ae^LV@cMMmz``PLfQTJs&u`z}8v+PE1}he_Xa;xsUhb$%9(0_9Q3S>v>3kTS zO@{&2V@fBi#Df|j6le9lY=XhbC6F2r3&>HE%9f_cRc4&VFvp{Qf z(x^O@krP>eNGVt_iSDfz3u$8ERU_iUJ}?HAgX;SU?z!-c-+lmAFnV+hRIbPzSe^&w z4wmdO0#X;SDiF|=I?J9g4Q1-}@GH(`PDL}8`g z2>0KPc(Yy`AjX?yEg;jLf&oe%H%XtlkdyJbopK)=kR4pXTskHn`<2Jf7xQ5)x)9iK z>?Sfa+HEF(g2&>Y|Q7@65K^dE+f% z$%8G^FGclu-(=E#P&m6DFqMnjc@jC|02b=X?z((_R(=+jKw?3=coUW$>_)P<&ZImr zPB`g}7kL`#rw&ewJL;#?L}O{4f#VE8Uym9WpQ}F{1OKU|VeV}_eBUEaw=R4T>!m$R z^_Vd&S7Mn>1;X2*>Q$qcAiR%Coh-eOm~~13h$yJHnM$Qi)IZm^r$rKIVJ)uV=G5_J zmVRhV+dX^kvSIH>5@&cmk2@84WvarRI=MBlCR32R#o0Z%&84omnLpRJmUCOF=`tei z;?OU7@vJ-rqXJK%NA(O21@>rAID!<~xlpHeiXfN9&*gJ_lKeC38YfBjJUJMm@ zugQ#B@?bF2FjGLAm|WP&j|;M~f|R<69|LX}RIZZYh+68Q6lxVwe98hMU zNqi*yK_5ds5coF{4{>lzYW7(im;GF2u%RxMPVtE<&gRYQd|{i z21Zq8&Uq@cM$WbIds#l5#h&E59K&Tm9%)Mv&iJg1r4CA#!{v7-xmT`;hSj;3_RzLz zzVnJtg;!=WI{;C>KqA5bt19oAo#B2+DReTh)WE7>+N~?LclpHbc$me>A8V*~O_v%} zuSQTBha-XqULH-DxZbfm0N^hsU!+w);$#G`pQ(u3x1}-#tRQAT-{=PaxGnG9B7lS7kN~6U>v^n@k`eXiRw6mOPeoWkU=P2Cslqr(sOBO>2vw^F zi}LzU(^kJOkcM#%@FhwiXfzPTjY8E8l3y%dr;ZO)I|OW@!m}SJwnAghdV)jh8qUEx zehJb@6^fegYHak3lkZqE#5K`}l9UKAg#ekpaoz*|`~8Qqhrc{S4KL*_iXV;VHuGT& zkpYU|7CO1bC*imim=IiuofdG0npB$VHq7)aEpiN7gqV<$x-`6eTQWL2k6M3DL%j}n z(*UBderEUG<+Hb%MRGx#2yE5peL|0bezQ)wnI72rwwA%A*k;)x;$THZOK~^drfhA0 zA=n6NvHMe;$~!Yh{=(kNxNKc-ek*k8xUp!OCJGjP9;m}k2hU$fCzBFK5A|sL6{FKO z!7@c^6ph@kdsPI+?KT*gW6D~MteJoRgt3obvFy8x(j}Ve>SQFn2KNk$_>hP5z8X z&9wKi8Zec5a$O&zk~i|&OwHrFS`jS;1s|k;e^>#U_%rR9JX(;6;%9Qg$ut0)YOp0j zI=s%O*exz@ap9*$q0%>~1>`Ey`e~$UsX=m9?}xPOYW%o?3cye<8l>JiR+PJIesdvc z2uuJEv{a)^x2kBeR@6c!c=6A3H0SpD47b`rN0(DU?W;{FW5@1k3jdQ#SQpTRE)f1QPYWNI&%b&YOCXRaZ2 z*Ri|bRg{$<@j8@->4EUc8m2<)PN@p;bI{Db+sL4vZ`mN?4rYjm>@6ho=f=xe{7Ir% z^)oc2DUF;D)fWYagl8M(p1Bre)zdz~F%ejoYXA<1B(TGjW8b@_vp%0v}^74%x_P(xaXpB zGWM!1C@HlucxQkRYm+pL*evXKz=2&L*pMlm`@!y$xTVRpB5RQiLFa3subS2to76iM z83pG0r~4VmqPj8?zcUI4LgLv+Ny5V!#pfFG%(C5J9kJrr)5* z`j;QKV)@Ww6G@{k)gyEe&8=HP?4t*-`;4Sh_S_^>t4}BGf)vAuje&db2=qphb)7L(ZtZdoxFgk?`4A4B4 z0GaIbz~<_2dF2f`Pw0FwdY2d((#W=8Z}D0l3=jaaKFv{6_VDs||NRJFD&~tl#E7m* zj;`BVd;QCgCD{i-{>(OKE{h8U51$Vyu->SLw;KvB5!c9a%{-0;v1Jc*o_@b%GA2sV z?0ljCzei6SL3ahe2g^6LL@~H(q>hu@%r=RR z8}Mnm)nDI|oM$FD9=A7W$~;-g8fKC;?ke>hp_P%pK4_0ZTSuY%V-M6CRrr0aQC)XmBTL{l6L5$e2Yxq*V6NyL&XOu?cSl|>1h7r^T*8<5La+-uF! zfBJbek#~o#Awi~(SF}Lpc)VHHjTX7juZY&x*STC%{KdF)nSL~^0wMyiKP$Sw4PtT# z$xhZt`VqTHdcO<=Koe-+(<2M(+u(mK9yEfSx2sQcDkl!ln1O;lqx$Ke#_69P)72{N ztmumK^Mg0~Cn(Vm73|k$MzQx+lVlGDbIpIHiFs+vs1dp~G!))cPa8K;3u-_rRh&3% ztr>u#m3dh2JLFKd+aQj9JhyPI3sXR)pdWH%xtjq%nY4jWkqmoF74~m2t6vG2G8?|X z{-wDKb=l_&ak#dxZEOA^Wz?8YC@hHGdt<6NX}@Y)(Q?@^>89TkvWEN@uHsF`@|Oyk zYZj@4%fdY|BM7Tgf6bU_E&>Qo5E2?sf{0xmwvpBl)Ju7v8e|gWxa^&%(yY{HK{9ed z-j_K|;}uiTl3-4y?=I>Ms({KuPTI5RRljG9qS{8;#>1zRb9c6F#hR(_&!7dFR+FF( z{*76z8y0t`myVT{q*dT)BnamYOvH`WHnEO^TIi1^uD!tE8xOBb@wLj%*3L0mt$vfd? zg^vBZD`epu{rJ&>9^UN3R1dxE`!x>|pvm$cNx__3Z^^I|3TRMY+i(TB&7qa06=yK% z%*aLa7%G#&K>T9a+2%tJTvo+2R%Jn2VG3 z4Hd-s%Z`KFJ}hg9c_h0WkX~)H-IXd|r0n<}DloqtG8v-->>O2(sl#R$YJK(E`Z6li z$9P+!)8JMk)S1Y-n6C3Ov&yc2aplk@9(wFVn_ZLTn6SILDJ9;*iAg1r2c{xZ0+jQK z65Pi*Qcr;J%pP2~$X{BDkRLV0^Rw~h^qz~17Tc*05X2Ql*)F1Xqpg=byzkSmXIn=5 zGDt~BC518h>#m~ex*9;iJHL7y@U_A-)yiZqck5NVtf!_g5i`641g3qv> z!%M%Q>ty%7B3XPT>vuLQ*kAL}zh0`Jwzi5cRc7}1c+==^)b~6f(k~nS`5;cCEyf4r zcZ;+{?t`ioL6ak%8P@jMn;;Z=u7H$cr`(dkf0cYde7Jw7KO^dR2919PfHdm~jh7_2 zh?y(L_T0&IPCKmOu?()A8b#+b)-TmF(7Q|E;|wk=?sQW#EhxFGDDjSmOWo*tBqyqk zi(0TlRojK7(eyp6vXdj(7^xkUZ`r=tg?WgcxH6o1jGCVjE;;rm!A z5qG_>g*%r&ZkYNU(01c z`z)Ipb{-AcZGQo;$tde2_C3lZIL^V)n_9D?$W`y`sAmoWWpg_tXguCa64rhGO^N)7> z11_@|U3b{Qw{aLkxInUMxY=7fD* zKMylb2*kkkw9}yZ02`v0b{{ki`<)X6Xp)Y0uEOTc;;eV*yhK+JF zRR3E`{}II(0H#=H;Oc|_E}^cI;m#bf5&l=8BO}Az9&B{#KR$W}Ad|Vf3XuO5YzGRG zOm^)9I=Vth+eEGTfE8>y5B{%U!KYL8}p(Y43N09gC? zO*fSkh8nx1INSa$cm>epPSsyD|LgtgaI6l;s&uR<;i|H%+KyFIy5g}`JA>3+2yBgq2#jo-mtMt!*ne4;%B25C zt*<5)R`V?X3BzihWi`*TnrB(fvnZ_QXjfC#s~P;2;Bj?9!|M8u)#WZLq4VnMpVh@s z|1Yc!%du)XxLMNB`!b>*sn8+jeoKwnZo5?WsO;1-a%in&^}u&vjalHrpF3paRF6s1 zgd$~cac8IO%}Sm6!4>Yjd9P-@!B)xMixJKBIpVX><>kAzxT-otK#D;elroxW$yFxh z_{~q|wfhh|t}JH&KX+~&+C96rutql<_>gdN#KKXTv7bfbd^Kq789pw$va3LLKfu7m zYh7p-7=_ke$nIh{Qn39RSoI+}f zNpV43OX)%&D8AlJVrBol-d6D3W~kMIaU+uZATSLkXq#3W+v%vrh|uVd$fXSXrfkgf zou5RF4mPUKYYZPH%HpHx5$L=>1mr`9i6D#>aq}VA7{n^aOq!+$ED=ltmIxM6e&27S z`MkLfXG+w@R|bxFFZC*i3Vte^#?C3zmS=vo#6@iAYva^~`(<}Ien7n!agp!%2%P^w z35u$XX8+i>*t9I@35M`Lc!@(0{f6q|HfYY=7zo2Ol~|s4;cGr1nD=JlCF6Qx1nRBM zI6#`-Fzs)}QFgJQDJ$h?e9oEeFm!-zy*nx&cO^v^97{QDl?|L8@b_5&&=U_UtbPTM z(Cly}RYs5ZZpJ7njg59pQ!Fw!n^9{dE|w0eZrvjP2QWL4z%t3k4Be+v@ukvT2(B_L zglji^Ii=BS{Hvb*`^j*JP17z`UDf`=PH2wkN#jObkb6To_Ig^}R0V3Wkr++1B-Qu7 zj>4n!C4zLBDZNE!;Qezru(+{#&$j5HbHsYVo(K^FBzArWss4L^lu+cAucp=8vLePKBOByqWGOvZV5Ua)ZL43Zu3a9xUflkCz$Z;m z*8wx7SRt`z!^fCmfy8d zC~-W(Mr%HK8=k8s(Ir*YH6Mf{W(`Wf`zKp@3-?A4X-t-POg?`=aC=Gf4Yl@6%HC##0j83gUJnP5RD zm&BW0pY5&X0GSV0vS3%%A?XAb!cL;B33fJNV5=E*$&YK_ZyxPL(5Xb7U3ISOk9d!3 z4A)QgI5;-7%+RO{7qmrj_)Ng&gy!<*{b(RS>4tt}HHxqdr);lJtQFbN1_s4pVMt;- z?4CAP_^UI{_Q)Ey?9}*cp|5Ug3CTct3!fXRFC?YnsY0fQS7b_ZUIc|T%+E3mS@>y) z6Jn{DZQz#VJ7VrH!x{E%!@PxBLkMzNIg|Gz!Eibz7{5niZ`SSz3!8{;o9n+c_j8vO&y2Txn5S71v#o0<)qPThTIFD(PTKI4 zx^U$ZB$vFT(7nPnarUF~l z0AYF5{H0LKK0j{Wa3&_*@KAWCA)QH{{!K}PF&(AB_{MY4haoHdkqe9bU2McVZG|k|kn;){8gOznZh-Krhbws(Tgg zvAo^V%*_MO(j4IPj87RpZfA2^etG(vRZbYI03v*Ghr&=vq_fw5d570Bdg(f3hZdlj ze_Q_l;|dw>h3Si%BvL84%H|TVMmxZt{GX>df5s-vV6}>s;aMGvRk>KzkyU%~k2!q} z?0{LdoqxNQ)v@^BUUyY4R=@-RVOHg0RWAN-WV)&&t2*+3MJ%gwu__m;%a7MHA}O~D6KL||1e5o6g*1$s(-}(-*|G<1v}RK zaY}Q~#*|bWqu>4_O|A7~+xDBCUsN_Ke?>p-_xm;%;^Q-ZbQMzPSu0~FhYM9Meogxz z@6@#WHud%13QE>j-)D2#WDjBQp7r~_-d@}=Cb+|R>bzQa z4h|s}_;-}n{~M>vTv&f_$mzAy;s5fkZtJ$sxE;|w^iNV%D*mGM2JXf2?f;WzbzXB9 z-rJtElI4}uqnUo|Bj}RFy5s+@(0Opl=0~1!6@BkNnOlWZ`wPMx(;YtigN0<|uI@Nr zzuJty(+{hou__y@nj*13t9E16ivF{hXVs^ydf0yuh|MbA_-pRbdx#?c!Kp66@a5u~{ZTu7uI5 zy-4UW0_m5nstcAPLA{q}WqL8*8f_W+$vbqNPwesytv#1*qCX6rp--IZuY$Vr{ViPI{8ZJ#YRP7Z_ z6eeapc8^%cTv-X-V3SpXyZYr(^g_2?;C%07K9@_`b;OS_nhC51C#FuaoGdlsGd3O^ z@^F}v7V6A?%T}z5)1^Pp6wH?erm+7blZn3_TcdC|kHb|EpvA`+mfpu*6#*g$i3Ws*{^t zGEWR~&NeO-R%!Syi1ShSd92IIjrGk{UDh7(tpN03F!c zd8KSeG}MFO&l<-E=7irMG#1&VsCR>zp1e3hojNN&+=amD~`uDrrUjJ+^4oU722yZaJ|N#fEXbS#^18U8wgH z#re7K+|EV_u`33-rt+b}4+B zO(MNI{n)3s)U9T(IKw04{`HjA5Z&7y@@B_8bxX)>$74t9{*k;$t;6r63tKmp)|D7*&epu%JoUZ#kW20^ z*b<>r%_TI+ELhAH4-W5OSEc6;K0|Pt?G@W7cI{c;rgo_UE9&E)?>QfGCb&?|%6GK9 zaprAml15y4u~Sj6?I6%?!a$*-mM!6~5=42U(jlv8%1fMgV`T8Oimdo+*!Q*5HU%xx zwnHA9rWUZ>y2Q^pJW0$Qq^1= zJm^Dhh|u3$v3*dYu~XDWZgWJTBgT3EwMsV%_Ow|-4Pc^&FF>?eWzAUKSon!9LH^<2 z=~_(SIUP_pLR3j{x^FP=+kq5x{kWPMMz9ox;=IQQ!>j<&8@Ns?(aFN$r8%3|Mz=AF*GvJ@qS5ziB9}Sd8UM)o z^bn-u3Z_mLk`nDJ?s36;r8ZFpYr^+BlsRXO2kM%BD=*H-`Yx%iz(2n7EW@VSs0-2h zq%#}+EZ4<*$vq?*7?eqyn}f!3{~C+6!0aqc1!n(AeGp5Y>a4n{-`jRG3oBr@J>gKm zhL~_XuE`yuzqwdq@NK%JeRn){uHEKfwx<&;ULH7O#F>2Zr--BuFBR1mV|-gwQf(~P z-xOIF=f=J^IPN^sfpq-4?Y?UNkm5Tw__9|W>sqoA^(JzuXpG*}cE z^R2{ILd1YJsy2B-yWqx)+6;#VRF<&3)0_R{@0z7LoP$ z#}7vDHVI0E&%DpdJ{&@n*$hcGnl>5aH> zQs%f3;yPkH%Da5h6|h9A8>M|GT5W2KJ`QvCob}z%Q4b@_o!b_yDWION6=^GWe07qr^7FkHyfm5bjH*E9mFPItRSL;DB8(K*pG^VBI{;2{cfo4n%ZPW0T#3=Xx!q*^=j`EK>{L>$c6S6i zR)>fu+x!sC5fcU8DfKt~NHwjLer?;*zOTHRHu+r|7Da5~G_d_S{`tYffRlS_9O$g) zjce-q(UlLz*E++6Cq@r^?|x}Vaeibz{%Xeb%rv#pR6Ta=`BM32ls@=sd(L|?YRhH~ zUpwhCrStW5!+kqqb!Ht6#=L%5KX*^6D5XI{lU;0|yl8s3*fAmdSL_eSBED7yBrXwC zK0j0w#QhwSvp;4sS9x>4e?Il%59Dl*eV2JrMfao1UIBtjRhsNAn>1d^^3QXF zCpux|Z%W1Q-1zkO9-qraEUZmd?1j8*1J`sXaZw2RggE+Dx0Y7xlV|0m^1*Ms3g51- zrn)G>pk&MD@k<3~K{}JA+**mV#Xg&;jF{|otqpP;f|1lJZj81LL&|H#G0aP*pzAUN z=P&o+-qu{f-@KlKrcIHeNSOZFNZvZ_Vb;zl@ z4hmVgFBQM2RKM`eKF#cg^;5<6Y*WW>>!<6(reAJ2IFxqgYQl%DPdz{>ON^5OQn1lpAcwNGkjk|(Fhe+KhQ_pET0HK)< zg&j}XZFLnw?&(W_+LKg4{N869~_{8K#jFLz(^iGEIs=C?5IxB z9k-@572~(g)f&qqh4G4EJEXBn@7|teb*LJilJ>k809ld9Tfo5h|QxtlW`e0I4~-OEg=_JE9IbofU=DP8&pBFg-n*rilZt6BcjHji_sJt|p;&GD5psaZ zW6~mNSFU8+rcA8v`N9r8x5|BI_RuuS+I{maqe7mLgIb+jjipI%0ch{qk%QDwIJj>4 z<0$z_#%o0y%E)K3d~LQ0lAU*CZwTClKw_ReI}5^IF|`Dum4b9>Ow-&ME1*ddGSqdbAx#-kih{Q&Oy_6HiW9u7&)DU5Gg@HUh4DXo{V8%+w*o1h)9|2M<->IPfA zljZ0aBDAlfwln@uuVsV1!>}97NQ`893b5;T z9`aO{*yw*^@uA^dvZeH$gClnR#|Tm5M43EK%AeJlSaG1SS|NZFtu2vP2{hzBdT{{W zH&9E|gC&1n*7voy6D){R`>>{TFdj32I{?^^6IOptn>Ie%EzZuo*$yBH4{<};(v=ZX zTZ!WGM3+IyJdT-?82DCWXSr1sE&(GEm%|Fu66w|RsMSM*MZEgij~nGZZ*XU*?B=!d z--iuc-)Y*Wm50O*&@v8rsrYV3%?!PV(eIN@1#i=Z-Z7);(Hyc1RJg>c=_)#xy|XAE z8LQk+lV{ow0=&tf^+^lY4b$HMqsHF7(E_5e%w7L-ujtby#X6)eU87{TOJgk_zVAhQ z8j4b#NW+!9Of(o&!Yi}!Z;MT%Xv4yUcrP+eLzJ%wE>2qfW_vNvfZDj1o}9c_G~%Kq zVvuXnge%)v*J_^Mu;`x`a{%BfoOeIODD}UVLM@FK1%eK?aI^d)Q%Zq=%=F9;$Og{R z7=k|qJc1im7KVw6;Y^U(gl&!|bcTUZASzooEv1*+7Idt8`{;z$*I{YjCr#D-OFs~= zoN2hY;{>AmPCecfNKxV}Mjz#Vk&;?RKYilZ#RimjY6HrO-c+mzfBTR}6P)H&WhgFP zsP?`QYiuOOXw?dj5niBn!fqH(&xMP>ns?y@fBr4Jx-zY&mcD4`tG?zz>dKdPjEQOk zE-??Dqfjt-QEb^YgZVL1$}Xotc=wBwH7^i!!hLqUd|W}~r%74hDezCNVr~S>h=$>; zvix2b>0o^T%}*|jc`CYAz5aA%_|Fa8%F6b>fPu5`0~rs=2?K~90|6&Q%V_E4mrUEZ zU*FIObqw3-4zYZcYCyuuIHe7cNZQG^pLqjl{f+H(_8*jky-=ul@KiTz3!~46N>DX zXfSPb0o6f^3}G$3J^M*V9%b>;{m}&=43moQ-T0)~=p_)OpG((C{y{DxK6!y{LP==G z{M_(P^FM8e+N^j^j-Z;}3ILuKep&c_hAsM)9omajcq6{`wFhaf^>qtiy&^x~2H;e| z_LOQBy$I}_2|XBC{K#l?o<6W`E?%!a4*2K1_C%h=7xtA?gzGKWM`>8fy zyB#M;8QszLV3W6gU&m^C)BHW)-A{QMMKMyRvu!Kd_X{!B zqvjgenHH%2Ri1&h;c9wUunae-FXq!T{a_6F{zJ|_~eFu@oxXXK8& z?faOTlv<6D-_Ieuz1LUY0jRc>8M!nPWq|pW9-6|dO4y5>MhAen0bhtEel9Js#^>ky zo}oXr9gJ~%jNQ&cTnF>65=K$m*aEWrdYagm&_b3IwN515)&RMrF1r9HI%psdkJ;l@ z?E$fQu6G!@%yWl%6}CRL^zXqDL=CaGt65&;4q;ek)E+Cn_Z_3S|WAmZKq6B4N zH?P9UYj6ZSCU#=8>Ck!jVW%tyr;G$W)5eVVvj8D$c{sNahsOYH)n(TR)5wU%T-%X8 z#e??7)|Wtc80i5?XWy@{vBtjMp*U46nsmikzZj~vcs_r9psfB$_)4}zO72OeKTuN* zopw+lb*u3N9taTx={;Zm#WjFr**13+m%$>OC2jm0>f3Szzni{i}_elN%8fQEm&Rw^(WK#z2x!Ks0 zeb_jeU4XBBz!w`E$5VDT4&Wy{^RuU*zrO{Mo^t%X-=WFuSlL_Z%f@ENcJ7RkT_pSb z7_3w^++|`B=cBayi*c3qVeo)$YbT<#vJ>GJ|7&Nf%%`ifZ8LH8-88e4y(+j{t*RW+L(T(>s?@_Rma-!`=-X@|xH7=%Jmsn7jI37xB z!cpTMbN)hn4TX@~38Im~`b}e}8e(onY{(kMv$2CXxrJm6C+~`B&)&6Cl>F0X{({0Q zL6Qdj`vE*YeoFfAxih~XV0K7CYyD>gSy{JwE_0ELzas*@Ndmygf2QE(mLS11&&dC6 z1HEH7wx{0i00Je&Je3#b`S$?{()hn4v9YH9Ek~BX4OuW_sw+#m0Mo%TDch!)Wk^As zEcdbPELl#IMHT)qC>B*pvDjVi6=3L1Gak7C~YWBo;wp5v2b~ArMwh zh?!}^zT@5cq>JCos3SdI5!a7cRtTWZq7`XjvD+L&TbGlcQuEyOvXE@hP9Dj(US+t6 zuqAlUsSP4*=|Jobrp&e7fj%b+d5wTuXHNRcSzlU#*W>j^l+o7%WsC?i4$SEEb=msK zMIQ}~Ju%JEvi=-+Na*!IY{^EQqrw08Xsy+e(0pdab>IS6@xCA zjdtHAl8Y|EU&fVSZGeejlz|)2(wGg`4OCpa6Jv%LgJMiqjJm*PHv~z`!;m3I46J2* zwvi@7D(}L~z`=|))$-L)vJ(M(rKYBwu|l7HjNVIBMf;V>#CDRRS8J@s7?Fe4lXU=h zIc|y#LVc~Z;1S~Hjh!OZ8U#~a7e<;Z2VxAW27Ke9yvCxw!x0;!;t_PlEKC7Y-Cd;F z!WhJ3s6RPi-ITz%ON^1YU@z$R6A=0=d1y-m6GK~r=n?{5s|Ik8w`l1o5)zgNHfBmq zQPr&;)tFzwl;_2R3%$7Vupb1933a*$Lik|qOxUkEad0_D7q3H3Z(EX?Xc*9<6+MZ8 z-6dv>1R|n_zT!8tyCU$4y#x`OeVe?0t1D2b}6K@$c^NeqEP2{Qx20!L3QxseW-0Ed+KdUfe zibA%Mw)POSDg>+fWz-fqOKf1Oq zO-Wc?>1QtA8#DqrL9>JU!8Y276D!g4)2|pc1I}r*9v(W4C^N(m)q)04F~`?1(CZA` z`cbB2BkMs))RqU!cws;RRK)5xLMdQU^7u+W&5of+u4h2V6kuq>$?rS(DOp-8dzkYK z@JJ4A@v2d1gY@o~z>=nCP=%YVd;`&aGZ@D;*pHm#&62Gs=IHC@z+)A5A7{5m->n^e zi+nxm%k_8}>R{R;VrzlNU~y1!BVzlAZ?eNe=ki6V?93_VID7QHU~YjJYg)d6!CC=K znXrhWXds5DIm<+uiMWxjcI$p4SmfJV`k$sBPqBVC3%p8$hw zx={S$4$)3fQLu@LVfq8u;$AB3J1j1iQAZPF8l=b40JK)>sTY8n#Gu0<9Bhe>9HVF6 zrGgpFjCKTV0M{5gMzz+}U!%4&s1I;Mj1t&NUHE_(CTPoRltF=QO8G*`u(7uk2!8A) z13dfx%d3rBkGAOR@_K_y!yo*HA^QSPLo`ho&>8gcWc(%)vpflwV`!B-5D2JB%H?Kq zmT%JxGGaiSY(PIkq#+VeP`nd(W#-AM1=*1>Cs?*xs!D5l*t}Ik6aI6A^qIcoBeNAu z@a$DyXoAI+p*9nmf*3#X5d$Nd;AMI@l3ZTo7bmqYIMy(r8!+k^xDN5vr~2Zfhi4G} zrW+j4$C!=46cn_Zw3&@3md0peK7Ja}bZ2})jSj_@b>m~&NDYz8&;{7duAb;+u7QS` z=P{6}(Qa!lT3^I`xoIBN5Yj6HEPxH3C479;+5`u&0PauNOisiRNSo_3)RBqx=B6M( zyUXy92nNapwi4yrG*ycxEsp8cQr3F`ARo5}%<*s|`rm?ATVUCT?2(nsJpjUD2VDd-S0N-LIhX zw~e)9Z-L%eCLP+|5U>j~9tqORhTBX>yWQuZvRl2i|M=Lyn^t0P(Ps&PB?NX53kiUV zu!O)8!f$iVLIMj3EF`da0*frM7^4u2HUox$B?OibSWzS^lxF11c|OcA0$= zF&^FbT)I}8I@n&mjGNd>ZWIK0y^NoV%NEmJEY&4B5iH3NphA;aTIYfpSVcMdMo?Ns ztOxli$SXkgGo%^ayzJ=fvbHV?D+ixu7RMEty6N@=HZHcURv}=1V=H%Z2Z$&%bXkU^ z*i$VCiock*bwBJ^0kWJ=wQ->pHIEZY;hC2l)8CZEfy3|B%k3yf`;@^bT)KqI z42lzK;w~k5xvHjSpzD}30oCXo0i}fEb-b3T2F&up$rYZ_XhIpGi3}w-&|B~oXv8RO z;g%o0W-HU;m?JK3pa%Z~326?0!?;RLFm%8M2_m)hH@OUI2f*kXUNlNKu3F}MJ05(s z47U2u*y?31j&UwP=eQp`!AAnn{w|^28ib_%0otEs)`P|M1DYmxs5&6Qv?UH&L$d_@ zq7qOtZtf2rfO9iT|7ECSPgb)6A%yboK$(H|lDxMAu&pC#!k5%t1k;5u<~dG2#ID8k zPtZsa6}}bdaH%G*Wi17%FYOmmYkjNL$Ywv6pm#fxSLD{K|E&Vv5aJAI^e@BHKlVh= znhH*(g0aZht>^g7jU$w1E;>8?HF&$~pG!8VT`HnqGNLj ziHUUyAMzBWbs8jK_sRo{Hu6kango&Qtxgkbe7Y36vYH@0hl}b}HzBeiS~2Vb-ujXN zY;hk`7Nx5%t)Vwu!usu*{fheBmr+F3=&96!J(sTpo5LKy68{#-#(d=DGAqT$>rliq+|g6-tOq`?m-{3=5Sz0-85w!up-dolHr?TboTqzow&bG2_uw ze2~aTaW}y#@Cqv|IR013^3qU|(PWcW#VQi^Yb9-sI0RmdA&iqtzyh3cX3Ucc1EJ_E zMR@1&&Frr_!*#`Y*BD|0se#a=Gr_=*zva3d42jr6|D=hDnEmAGP(L)~gN^6wi+^X9 zMm)Z&+@)wT`&VC9v|bsbqdv>(vB$UQM>o}ji~NUMv-)cHCtuUOQx!~0H+oYA*O4_G zbUR=u(PRYDFBQ*xgQ>Y((j@NU96`1y>8BhIqAbQdo|sj<(2IT zJikF;C)t`%`whJKf04)g7O2*b^Z9CJ*+pdGo#sy~DsT(01y{IoTC_fKAXPNO!oscw zJm}6aT<7^5BnZCvM&b}i+IMK zXJ4*!KhO_;&dr6So7g3CwuwBQGRWqs(7ug@N$psRn-lVE>=Pn0AT+D88_&|&cz|p0 zkj=%5?(?^Aps(FNl0soLQ6^G@RQ>WejpYnm^iRf>N*w@Qj)u2SaHE3tV23Ij+00S| z5byVR!Ce&Je-(2+z}&=3*YIZ{D=?{UWmd zi)-Jp#3|>#7uu6`6MYAAmF}E;8E8blq_&*tq;9uC8res3ej#@#mMotCs&$jOvq^7I ze}Df^LT#P5(lLWwgn{ywQpXx0QPJs$*oJaYV#^n*4 zUl@CNDK?ReGTaNig`Q4H3w)e!5ra<@3++}LKfOn-N5=J(CVBJy6}Pc@8)r%%gL3+6 zBnLM_*)NgPES^)+^68pi+0>r85|3z;2J1bJhQqzRYMYn&{iBo?#MHibb$!e@rT>*0 zf^C<9Ed^se9n(3Vor}*`?|sqT3_7?FYae-cN+1;ejK8F-%}N&beFHR?8|p4J14wW$MKYBHK+AIS7ePkzBMtkymTo$SW#0`>_~Qn z;n}kv!W7!U{yqU}dgNcfnpFj+@g6)PDJtyIqjFuyvJv^uUj!uW+Jdw_+SR*8;(i`n zuqHbTGN@wgA`IzWS6wMVHXi$dvkN%%d1NGYAbTKX*M+ z`{52q=3Yk4pXOH`P(GbCx_~_9vX6Mgz?G)XZTqYsG<~jWc(;OK3-lkW#*4|&pEU~- z@2d+3Y;o{3nGQ`~snCCc1M5C_~XLTy!Rt+n+G%JO03y>KPfwm0){ z_NCdS;ddsCK>JbSjV7QeSwlpO_TlP#mBK0Z6`2W_4yle1$8EVkp?vI@cV($n&@T~7 z7Aq)hUyv!0V+ak$w#M04O|b4a^ZnO+nDac`$9ZyN-^trvXsrT1@nhK8vxXW{`$c^v z<}zDc!fhU4s;B2N{7lp(kj$Vb`Ied6hpea)Ut zO~epItv!(*wSjw2WpzLN$5gW~#^%FYFx|vkmH(O6wlbSx!R$O}T?!Y|3>f5Ao7AXT^0VS-7!2eyx5i- zI0>i9U|;)42X0h*cHPn(JsZf&qkV@B!x8eu&qjRoq+BF71kKZ7wX3}OcGvBL`9G!1 zF{KvFGtYv@-!4C6(SUA%YF^EBpxp19Y&_E2r|T3ui2HuX5JCN(2gdtgWW^&LKRo4< z!zXv@UC4+2de)nKdG5I?FQwSU?t}ltTvj6$&M%p7 zc)OzM%P=c8>6)=n#lfJQ5sN10x6R^tS=-L>`^=2VhnOcB8Sv_(o(512EiJi+dP|8r zlr8rra!Q)SOGhMIcGz83G@_jepeZlh>h2~r-V0EB9-;I+R_|@G<`Q)hR2lxJ=tXR{ z2m9=Bdx_5&5_vaf#(7rnAXBYHBrIeP9oiW>^U28HpE#JSS)t<6(AUu)a4G9-@i$N0 zqrAkuCt}6T1q21BKTn;$-Wv~A(At_GlEX-X%0Jwa7m5NvB!_#bKPbQOS>0tX37*{b zqQvfQCT8qDM_9bX4|vD1e%$cTwYeCNP^E=s#tB>-qcMUVYnMJ9dW~mWQ?vqIZIWUb z@#LP^>WZ@rZDcXv-bECfh#w`>hx45y~jv}5>50Xumz znvzz6(GjWdW$gcvLn$8_mh!I13qh1s-HnUUaD23lS26he_r_*Zam0>UY^{!{_5c5 zI|ZE^$9&g^uI@nxOczDh_PM;8_NYnnq6VnoQ(<%u{HMhpY#Nu(@J>ufeOG`gdMG)t(YD_bKUAZ_#i(M@_ zkeZmpA>LS_GwUGsUOL9EeJiJ@_s%0GsIeZhm0mdMj$0QL|7n!)qqb=thoMEil683C zs*zy|k|GZsK;L{BL-??cfMTorffXG0!WFIf!+?Vh(u3Ff;?qbs=1zJdRa}jqkNIR7 zLu0u=2T|U=6IB#;DAsh}>=m0$d}ij*Bf9@d5i)Bgtzmmoap8`SAK$;SFKPa{cH0Fx zO723cqAKY_YCN3A@kueV_Z_ak=iVaja~pZjLx?-ye(DB(-bGNGk{hqay9{D#qjq|{ z3SC7>DfsU7bLY+tzV^v-$M6L4A68bM0(Ne_zS{=A$gLNFN*kF;yR5uKQ6Nr_C*SAMQo}1T256Pr*L{K zQP;I^;Y;UFWt;o#jfGzfj#Xzk8#L^z*4jpBBWF@lQYDNLXZEVY+uZ!dKUZH{e9}+k zJj4gskSx!_;@QLSA~2gY>|#r8ey@eFZu%7>F5qj%6UnM$gU5ecq=T}#holT*C0bfq zgl7-D9mZEc5Upoc!<2zxgqg#5R~NrJ`_!p`EzZOG`%)v$F4YERS2&&TX*fAz=(xF< zvTbj$2Jp4Da7pbT*=tebqFEwU(fv0*rvL;o4G%O%KvEaEG+>bN6W5py(>G?L`@SbISY8c=um;U00ht@Y#&Gz8-OW{w1Z6*4TOISHhhO|~Jw+v{VSXy?AvrrfCCgbejV|^a zrw6;Qg$3Wf+78lOT zQ-6m|AVRDAQ2TGnwM{wXC!Ii_rb)vue_)vd|Gh@f0D)8P^(=R0aPjvFItm<9`4gvI zcmLDT3~R{*p^xS%vHx_GWyb??&;RN{Wd|%1rW^`)!rw?wKHoX{&0bc6z5W1SeSy&D z!nTD|=G$t~$9dDm6as-@-ObF+dFxg9GUG=8Y8gT0M|;O|oW?${xDi>-`%`8`YVh6= z)*4ed-IE(zvHV+nSVzuQZy0@Jmcv#VApg1%B>rL*z6`7#fMKZer)s{o;u5v_SjQH= zcKw8$Cp@FUatk?24VV~d?XNriVvJfwbi+z>h_~27xtXw=v;}=Fv~0NxcqWps5-HmOFNo zx5XRz#kwR&BJjCOxk5WTrtxz7%S!_NN3mJdlUti{1n7!$g|~#{PWsd?ss3(km!igF zyC3Fuep_-SVR8np!;9IjtLh7vjxJc0C0W}s>clwekaG@TJbE_*a47&V4_Z!sd~ihj z0`&btYlTDAwb$r(?~Gy>rnuTR=Il!{(w~ay-!lUUvJP6O%6sadhv&=WCJ`mzbP$Dw zhhEp#?!_-JE!o)FaYnD1Vi#K$0odxs{Zsr@V))?Mz1X@-8?zZAg0Wr+Y2dMfDZv|4 zuj;mDg$=(=BWKtV#8rvK5C(R~B)(mvk)BTO!fM!u6JRBk`#tMZTVIV@PqPF3LT+JJN5-X!z|Bbt+spI>WdmSP4Hm8{!EK6C!=ra96Wv`Z0tGkq6I z_7zu)#WBg&1-iN#8UKbuDo#X9kDlZ-7>!EHCjX3FG?GdUfgkvBhd~<26X&S$U;Lcf z+uUHbO4HJbj(h6PfXqF7`TiJ&vCCw7zI$m)ep|~^B-s~V;2xh6y%t;d=2eBE>5Ke# zOJDl5`f`!M8%v%oXal*Jog$*5_XrOjJV@%z%gBMFNez6ujBARdW@^BB+@rL@wnOtH zb%C!91kJFWOd&^w7v~y1eLKQ&ty4P*?U8-X_UZ}cuM%k|(-J8y-8#|^{4H#ZHqZ|! zgs}J+Wixf6P_U^)CUWg?dU11Vv?n@k$0=z9)&FD0@^V?8Elzq-W2Jqq^#~L6hM*~V z8wUsPllak6=|Q=JNobXj?w%f#(@mbOb+3yZ%oMIafy3GR^6bYYR)3B+`kYu=UcUEP zf+s5@)KMjdz7^%Hq-<(8$;ET#37Y_=Sk5asoag*yKC83xR-zVP$$p&_2m^X~V379}W!Q^%wuqr8g>3huR`_wVQj=j7y=;mowGR9zZ8 zTxS${w6odVN2PQ%>^{j?J~Q;pJVjJ{(d|n&urBc`{~m!VY*f~oMI6mIwFGh-?=(A! zP&wWBvFjpc<1$^JAd)1P3*J+5|NigL72YA5Zj%FeHaR;J&7d3JE0H#>Pm#;+?P*4O z3(K=Ot-I90dWTPsG`ei&LvqzeAEacEtkqAb2d{p#cYpUv#jYSdK8tDAmga4=60l34 z#Xw)}f$wUSwA`=QUg764&E`9D_Q^;#HlDQB@3dQfz57LkiL!(Lzl>4r}6T`=fdF#dkk=pc_C;MvJ|ghug5bUfKU^8BVVFRfN&P@|?i zayn;I?f7+-vrK^W%F5=eiliQ!Qvc>6F6Y7@Eqp4#&-+Yhui3-9y!mP$M(58p&YeDe z+F;1t;~n9_+7Xl9$2m7Hhyu}t71mn5vPGjX`eK@4c}TWiK}cn4Y=yC{HYl^Y_x?`L z&ldYS_>^M{YzppfO%+xpH93Yi;`ZA$KzQIjw)vUXB+4ogQ(m2RG}7txMolxm-8YN! z+m;zCy0w*}bi#PY#>SqfS{Hb}#pChGqKZ}$QhUT4l7K{oj_p_5d*@GFACI`0o4_S# zELLIuvGXqfD&K9U1u#UQTNG2~qPX?w?S@dUg}~%^B3ff>^$0deWb#(XeMyS8gRE;v zXXmlDn8Veko>^~+dj+hEk+&yc&#o3k)A28nx3q8)=Xe$pgk1TJdsD-h>vB^TP5)4E z?TSV5-INHuhA0(Es~N^1ugTA1?^sq}t<7#-%SRUDhH&>g@gw$RFVV$I|1Jx1Uz3q%&e}VX4-B==oVs#~j*jk( zj`lrcIy!nB9o-2zCVE=R{hGXow8JqkW34-MWk~KN+C_omV;!J@0o`rdITPKO&@zdHqckH2f2yaIe?xziut>F98%G#_$$#)-5kB` z`2F2n-My6jRj>Uip+q}BOcuY!|EGwzi|Vz<1`qh}f;=7h<-{b!B(ABQ;^*gA@pJ$x z8Q;_Vhn#k$dhMCFw}+CrxSyY&n4h#5$kRz&Qc+P+TtZ4*N=lSgLewk3-P_Jz)ZI(q zZzli6=bodNy{EH>w=>9{|B$cUQ;?6h>a}Z!75(?;?{+%+JO8UDcdviCMeCsWVUD<@ zn1uNMiOky>_SCFTPhn>Bnn&dwu|CaP`r4M_n z^w`+Z3*_o^INWOTQWCU}xa8q~74iQq`#(wlMfu3x*;`HOACmt_{!c24f93z5D*X5C z|0Ff?batdonm=u&b?r|B|2^&B%F}L^(p^u-Ls>Effn3%8PokwF{-34(gMk5U?mO6d z+ugJCc2tv+piNu}MNvsfQz>aBSs5i++NF%r;Yb~_`5$Hf;iDpcID!9dLjNr-e^P1U zqIQZ#`d^}_cB;wjQVt!R2A$5mzfAp)txmFhD7DX4U$2>501MxF{V878z~Iei%}=ld z&zQ5xza5_!j1PF9lad{j(Ko-ZtAD-EwDHW1;k?hUHRp}HY;f2E8z-LeT2x1XfEsb2D;sf!V|3UO|X>^bj{94c0Z1L_nJm1-7$IwCPX?t0g>J>=R!L_%dZjo?SV$p zh6?TEFcwSNEa+RwhE@HVaOj3bo~n$;<2zOvT6Wh+q2cC0ea|1Cxh-%Jqu`i)*sv}WLW z9AJ&vMa7Ov!hrVk6)^&vy!xQ-ozFYkt^RSrfI9kFv;UZvEn?hhw|>0^1tPW-}F~ zPO|iEa0FDtqb>nlHwt73A3o`Wqu7SCqzWN1?&_`wu|9X6etOIrbiH3Td4F0cy#@{L zT$4u!6P92K`{QWpjvtIL38QY86A;oyv4{!ZaX03#@H7HS9TMAh&v_|76}+Km+x+vA zm5SHClUVhyJA__kbi2wpBcS{SqK`hHaVjKl{iT_dwf3b%quh*6SzopbeRE9S;_|S1n z+pZL~l|u)!^}{QZ)IATzW&q=U_>hC0I@qLtdkkDgQAS$eQNj4=4EmxSJJ3r*kQvzb z^HMJiy)TZR0%xvi8AV0(E?*6#TDYRm`fFrf)e*>X}hhz%Ik1Ec_~8iW9& zI6>CTm^wnSM|Cn*eyI*;kX*e2s;5dr$%s_8Jx^p_UakJM z{4!FWtly|ls$1=pV8k_G$aa-N&#j1su19e-;@bzyfd4)BC}qJUd22(PaU zYFQg9=iM2M!;$-n4+6JkhppM;`|K)a-r>eh7)495Lo#@933_4;1HbiJ2$T2;yCxnf zY((etookOR59k#w(>b_0_fannNPGt*vKItub2le~MXY&xxwyP_l68EobsSf=Q~*MOttlN&N&F^ps`FC-Jp3-9;aIgL|ZIpi!3(B5ok z=~jIJHq+1h;29-CeSKyXg2{xmhOsH`TA+f5o(U#i0{4{Gxi(GK!uA%*D@V&H^~sRU zTEGXg%?ZMAI#D+{U@CK4(rT4NE#8{-T;6c>FN>cmQ|pZ=>aY{hf1fwN zQO@@FT|a>{t$P{8ev>}KCWeX&%f)5Ls4h-rT*Y6u>!S73uM}|!7WbEGtw5QOmn1JI z-+g&&NV{m=M1r#PZtOU|3%NJuQWk=0n)2Fus0CTl16V$X=L1`;*le6rtabRCGMnp3 z!)%ll4mIMNi7qcGRK=?JdELr|oc)z5BbAvS$JrD-mhw}0(T0S3z2;{V|8 z{3bT$q0p=_F$-;Q(ra&0ekz2}1)}2WV9Kj25erf+DyXWCAA2({nSFN2O)_5bf>FKw zYJR69CJBXpF;{GFLFQuQZGA@_N7LueV$kk;R#epqXG1P)59$f@9;Qxhqr!;$#r(My zwSdXKw&A{A7-d16Gkp#BL7ZnRx=`I7vv#vs?cf!G9Z&|t?Ippwu0=&Z=LVE>(UugE z_%-2S5+<3n8E2uEsqcw!Vx{QU)=*An1+2R^2w6Qddw+jz|6_}nlyEVUAv`G5g8KZe zlm)J|ZlbZ@P&peswxo#L;$x(AUdnWPKdH4NUnIeJd+K0{h<#uHjOSTwU;iysJQdKH z4QSaft_sQy5SQzruTqj|yTRcJn_Vcc-<^$0G}I*jC<*-dhND}|bK@rmq_04HEI6t+ z)do1KB~Dyyrt2LvhBVBIo7?&yFxx6)mVn5zEg@8}38wMbiB`2X9uSyQ0x6zxmbtR-9 zvM4p|YKwY3@dStUdZrhcFhy)8{wn8I!qd0EC3L&lrcX#Oeb)D7wXiV`N{JU;z_q8C zq)3QjpLT9mx(*NHGEM;3Abb5#Lsim1-a(XD+cB^JQ=+PJG2v$(Rdc>y<-G z+aBjO@_J^PbXHuT?+KGX}_lIQ)yJ@5}q_B3FAnA-2$%1DSqKs>}<}UPX+^ z?YgQ?c-lh^`0*+}?pQvqSj4N!-^~hKWl9J72aQ?=xhD)E<_~cwG1uzGncb$=aF>SE zpN3f@Hti8Xh?TM?_bLPVrq$m)p1ptVL|C}mvWnG?JVl}BN%$Z%*$m*eJ!5HX29^l9 zA5~J>bvw@LMkmQj(swBN^43STkelLXy*@+y?RvBQfG-1nraNNp6mn;#E3|BEH~uw! zjA_0Bntdk+s3<^q$rkb?ZgQu~BF$Ae4zRGH=t|x^AZ}W@w=UF!_=reIAeItFs-n2Q zzy}hWViot&RG7tKtD7Nel}5F%RImrW1hnDal1?4kmwd&@dhT;>Y`4`7!WNQwwNQO+ z2}Nyk!lqLQiQpV*g;6$#AbpAMySVok3(lO^nmTABI#noYla{jq*`o8UJ#bIknziDc zNhkD7U#fGMt6GDG)3{sh{!dO=*N;}3^y2GK;KbTruDXhdfPuQ$F`q)4h`7cTVK4YZ zECny%^>(X_Oi87CX>tBCRTKGsAOPF@a3st8N{F&vT=0jm%6EOtC4FWpmiDzcZq~=Z zbVr=uaG!^*U{Jm|7#C&nmo3<>uGe=?QBax>_XU%A(0~Ht1jR?LD`#ZM!_{sQoj?g% zj!sF7RsBe1xB9;Dakn~}XzzE8!c>(t+V`inB+d7?zfAg~-OA@TK(YpsjCMS`*p#j6fW2Lzcevg5eLK>QePd6uy#R(HBHvm zbM%Iy;LdMRz#b(Ada&cyyq`7~3$OTeuJ_qUh=^~nVxqhCZYPV^X%#jEuiP0{T2m+H zn>r!HcyYdj?4U9_?HSU=1d;THGcflC#X2t|9Li`oaMqGDeS-`3WX{gs^UYsK`N
XH@~xpBc!DP4bpgIkBLm70buylQ6x4kj1tL44OU6R1+HBhGAWvRjX4)C z@ITo3k_oCMHHXdEO1U61W#u4njABVPsH(%dlQ38wyv=MB{Jo-+H}meV1|g!;RbuT3 z#k;%QXV`+6W*-M zTrFTt2(!Ek)*SoL{T* zEvy?TX#APSrA;Dgj|_nBuZTGG-M_@6&X_T2aQ<#iORoJV;nMow>x+w~0E@}agZ(+h znvBVxE5zXaU3a@L6~sWmcN4jI{oMj(knVlO`7qcV(_Lsbfk zN&wl(`*&hZv2^XvoaCMR8oWqa;soV;0S)ID)>b}^`NZ#$@&x?lwh?h&m+VE1Fncv=ZNGvmrt z1l4JE)~>>;;4OPTn}eklECTt8MN}aqPAU3ayR*JgOuDUD&m_2MjbJPi;jrUB$!lc0 z0v}C27^fbjNaLE;YRBy&cv60{0-$FAtp+V4Grxg*-FGX6A$ulJ@Nbk+cW3)*<+vDV zWbVvp3~-GD;JHz#zQ5Go>ihW9V9l_ta)2fjl>PK*4brt1q%J-mqCXU&w#Da6amr>-jF>m&8_LOJR1PB{HHFKZ)( z(+4;rEQsa;Vgj0m5{E2(mmCX&cYyYYC}=yIvdVbZDdFp?SD)p^Ih@_wRZ5PyEvD_Cp zTd#U;ML}HS!{ieS;6(n+d57u#}#Ybs-D2xs;?% z!-f%^9_|CVsBSQ!LRdu(b~QYr2FuAiL>;O?cjLpG*RE-eRS~&weCfOUJJi`vziB(x z%In^37?GU)q$zi^m4&Qa?FrPp9lJQo&5SD$|e>PGmCoQo7 zK%GtXL;Da_7B=;JoKf?uqEz%H@@f@o&I~-Udn~%oE2#VPdp?6K#QH3em`{aqsJQz;M;y<>TMX*Y0d=RB zWIgO=E}u_BD3*J3Xg{~Qc>v(Ai+D6IGs@F0%q}f8NBFEFr+4|0(u)~)_B2uY01Q?* zwdY2?Ln1tuA2vWZ**L>%=NfM?w+XY(Iaa#TO^_QdZt+|($HeRBv^1?%SRplHSZDMt zO=~NyvETvu*zTAG^T*)f;fc9d6FOl+;LI2qkVE}U2Ul6cPKNazVsRBDnL~(-Z-Us$ zIb;UTMA<6v!aDep@AyvGbs~hsCpTM5^`(f{wL|t@0H~N=Kx2UI34@9BX!T!bXiyi^ z%hew^znrQ-Q^CHgjOLZ~++ErJt23?U@v7Rbm0aDeOT$=-5|rz`swuL0o<3DYf@l=% zKXoRFAZ~)=^uj8wlu0kdb)?2mnoSAk=sl_&X$HtZg(RuD6T90MFyy}C$DC~P?tWF} z$VMAG$iaq#fnO{|LPwuqY>WuPqbYwl}*b?BD zq3WtB_-pIQVy;Xk7Va{4S;buG=q+4im z!QOJyPfm>rkHddmV-4s)&JrYg5PuDo0xGsiFm?4FM9l#obvmLdDt&V%0EwqTKcvf< z_jXi?V_s%#a0jSI=Nhv{C$E=lZLh1Nj+}+5S++ol@>->dTJY8491G`#WOMKiTAlp* zK=mp|r|WiQ>G@$p%4j49!289QagwYunh3VXBfpYLdixw<~jgtmX=**ok!`k!+lk$m0auia?y2 z6x2OS_+@2K@5R=JuNyv1Fn9Qk6mFbS6@ojufq=Y6GmEKJisQ+2sSOKC=yJY|Z57{+ zFHW}AK};$NFIC2A_zZwB!xR9-JpS29^NV@v(2_=d%~#+lsXgoLOq=1Y5HMLCYl=64 zZVsqibb1}G?2bx{MzH(;CP=d(BCfl&Y!6|xLJVssQe8I^vMS*(J9XMM*-_KzeX3ui zK)`ow@Rpb|Uh0K?Gk$hc*WOzqz<=vTRXP>;scG*s^G_y$6qw@XchWZy;ivjg|!i&FgU@>LPyPFn%oId$M^L3zK_WA{~d`x zNF`#YwZtG6pvi4PcfrxmUS-S4<-rRUFcsmjMEllVk~pTsz#XMh?D{M~^gUZRoK$i> zjynO~1jYHu%d}>>!WtNy@cTQwEhjv;3RlnXSHb63rcx3o5>ZawPEf4LEkfBVRrFUZ zt?TWlr(P8D5I!TEf=M)^>DO%!(74TtC(e(85bib<#LvNlSPCY_^{uB5ZKr23gF{_K zi3Fr7eqDeSg%l&|TfXq+WaJ6{RToP&Q&Sh@IEj%VnZtGlt=W{vh%vGEu~!?ONH_z3 z+Y2F=UQQzE2|7(Z;;>*tdsXmYCstfbUqmfvB-j!0BV_BiRo~)63)7v16&2^~XAFV6 zLM$EOP@@d_Cd@>?IEu1h0^J!v*kucqC)x>@eEp7x9FT<%0v&C|S;apz)a4qn0q^kY zJ!#a)!D6$#41eq7I0novL}rw~?_D2Ku_pxykU%Hr&+47TYB39wn%60V?_H(%$RnMs z)ZcA$nL6MkdzJFQ!QxF0HcuzD!CR2q^HZMsmy&;C=u`3gC}MbogPH9u#)wS{UulRL zHM>pGr-m%n3=XyD!V(Z6 z1k$aS=?s+>PU9$Zxw2;M%Qga%{hvnzw1(0yI{H{Rrznq|aEz;-km^}Ll5P4glo#XH zBu9JZ2})JMDvJchg|O94m!N7s#O_2_9qDFsT=1emA%&8(Jq&<&V-;a)LY+c#hS1Ffv49Cf=Wfo>+0^ za!t>0?@YH^#kHjV&G_I4-yuBffYB5$70_V|nh@rTNcPgPJ$Nn)P=u*d==J_Od2d7GfSFd-cA{k|C>WZM8x?+kpOJq8sc(SQPcmaqqU1L-$k zWtWi>01MN4Gw=D++>P+X#7I$=UfOu9rhVU2tO9{%N522kSBxOrWE^AQ&C|&7A^qs$ zj)N!LHHd`t8^}*O!9u7wPDrZFT`_C&FmZo{gw2Kuxy1_LwwALsK}_A@RrppihF>?< zZQh=K(+v}UMyNrE50%Z9h*)?LDQJPA@}VKWQ=0lTxfb#U7q13jpgU3h;H`GP1x+yz zIMhqG)<1p$G26}_x*1^Ju!EgXG(<*4&~(iS7;+x@DaY;*<>o^5gt}^_+JG&P9rIE( z6d4H1g57S<$Y{vIpm}Vl1AU^eEW48eVJ)1;ASKgeDI$0weyw&=jISx(JHhCJjaR8` zRi-l04~v;p8ikY+tG8MAX8$79WVfZ8sNrY2K-}rahiL#9?hu*h&g+(3%TKX=9u_0l zh4xJkkYn4-DUpO;OGN$dZF=oH>YUol;@whMmKt>uNgW&|-HUNjC0hhF`^H5F#Je0? z1)`)ONbrh_?S96@Wm{qCec`$)VbqC81JQI(67IT06n#MDLT{*6@Z8%;-$~KbaiL$) zQ@b?hkl}`wk(WTHJu3zAat?A+^rc{-ntCHjtLmLAf3Dm0hk|^m@!mP=BT3^VJ$>jN z(I^Hiqm~#vtC5n`okB%UQA6L}IPg)714cxf5Z+)txKEE;L`) zX-)AysZuAk{d7_finLA*Mg$l_u?v%XC~Ni9R?Ml;v` z&nbnlPEF|YD%(Q&Y0j6sPz=4T_#(qnRHhcn`^)?Tqay!&gp zUfWL8N>>~rXa4G5_xGxI&5Vl0J-SuP`cJC&kx#WcI@qovW{*pWkbh(u!F4{Nv&l_S zVy!pv3SE!BHB8Axco9%PzDbU~#JrjI83v@j7cQ^%6yt>JeG|E=er4^c)Z|PNaU9em zCPL2WJBQzZM-L?@n#_fDLXvJcz&RzBv>Mb|5YALe4Q;bnK^)?D3nb9(?mjz#v#*%z z0kueGpqSN_ui`o3&IPMRY^tlj&OntZ_Fw~1XPfd3hJp)SiNW<(Cth^c4BG@DK`8jb zjuH5GBBAbEWu(D75t=1j&Eu$t8j@cKok$nj@o3MWo`y<-_ilLS8c3-()-f73Lh9G% z*{`_61h5|pK}Ezw#g0xVMT;O_sj(l%t~<=6rQH%Ke%8^J(|#B1+ldlD_rxLG;g%S) zgFrWEZ4Tm1NjA4ur1Y(Cckcs&l%1~{pn>CjtpvY4=%aucL2(4s)n%`Rr11&y41CLH zD;Y$%{ru@G&NFGd_-O8sahZllJ%747K58;BW;BtCH#(4as-*2Uq1?8bW9HKse<`q~ zx6u263P&lxnHIV#zqJ(2&~I5cZCtJ6lQEGnOwHa7X z9gy-=PEE*ZI4>2Tq$@{kyE? ziF@g0l5@<5VG49FV;SzH$7a~w{yS_zqd4?t|81bkKWyI9t{zJ3zxg{j;n~Hr|D(#Y zj!MtNi~g`VMqf(*NxwL4;~zF!v@5M%iHmq?)I_GaTi`p7VOP@Il?)=@l z>Qir}N}qQ86B@z8{8oxbw%zofAPBQ#4+|b4{QqGiK)X8X;!d@F%KlrbA0UYf*A8oDwNBqFc2#Y7K5<3#*eao~s z1Bvkyn9Mc3Y7JWS`h}OyVa|*>Dm!I(S(IN+MVl-hIz*9RqoIr6?(*|@t1x`Nr1J!M zu6`}H?M$7Vk^I9B4qB{)(m9$!b$;!9*584Fw{Cv=O|enMva~ptwNL*#wNTafE8=@1 zBVuk~%i%nloqzo;bM&O*8dA%3!Aw8&o51aO7e~)n=k8msI|~)~Y)wEU zLGTAxox!wKO75hgy>Tm>mnvP(>5X;Y~&}Eb~;@;cx4Zs z{QOziE016QYfe48o`Lp6OBxF;NTlKGlCI$TlM@M|t&pjaGOaVIRXzQTeBi$7ITRoH zyK@+nf}VcI72!wS26UuY`;S4W!LBg&a5Rq07G|#Qwp?X84h~r@gmA|yz96>ErM3nk zZWdWXdORu^v!r(00TK3_vUnAH+T*DHD_$q9N@Nv9V@~eMAEWom4818`=VRT%0F3+A zTgN8W;$HvR#hsV3`MV;OM`?H5EipBCUsSqd!XFPxXx!}Jw0DPkj85I`%nJHB0%T+p zYu@9HYMDc}#T`gc&^s$JAUuugdfjOMYXmkkvw&jls8PKdSoejOYRR|LY} zoJ3g$d>!%(D?X4*gX}4OU~Ep|-fo!wQh^Qjt^XXn(EK|*j<5MiP1}O}X|R9WbV(0m zf5DknUo$f$-+9*lEa$*)NM7v^;h{H8a^t=n-ezvX_+M&3OusnKDyd}DtHbGn!Hz

-t8E*w<`A{#_>v?5Ej&!e$T$nTA+oT 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 Date: Wed, 21 Sep 2022 14:19:31 -0700 Subject: [PATCH 6/7] Update Sources/SnapshotTesting/Snapshotting/UIImage.swift --- Sources/SnapshotTesting/Snapshotting/UIImage.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Sources/SnapshotTesting/Snapshotting/UIImage.swift b/Sources/SnapshotTesting/Snapshotting/UIImage.swift index 1d88b590..5e7f96b7 100644 --- a/Sources/SnapshotTesting/Snapshotting/UIImage.swift +++ b/Sources/SnapshotTesting/Snapshotting/UIImage.swift @@ -114,12 +114,13 @@ private func compare(_ old: UIImage, _ new: UIImage, precision: Float, perceptua ) guard let deltaOutputImage = deltaFilter?.outputImage else { return false } let extent = CGRect(x: 0, y: 0, width: oldCgImage.width, height: oldCgImage.height) - let thresholdOutputImage = try? ThresholdImageProcessorKernel.apply( - withExtent: extent, - inputs: [deltaOutputImage], - arguments: [ThresholdImageProcessorKernel.inputThresholdKey: (1 - perceptualPrecision) * 100] - ) - guard let thresholdOutputImage = thresholdOutputImage else { return false } + guard + let thresholdOutputImage = try? ThresholdImageProcessorKernel.apply( + withExtent: extent, + inputs: [deltaOutputImage], + arguments: [ThresholdImageProcessorKernel.inputThresholdKey: (1 - perceptualPrecision) * 100] + ) + else { return false } let averageFilter = CIFilter( name: "CIAreaAverage", parameters: [ From 8441830d3bd3031f592168d845ecf930fed74d04 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Wed, 21 Sep 2022 14:21:48 -0700 Subject: [PATCH 7/7] Update NSImage.swift --- Sources/SnapshotTesting/Snapshotting/NSImage.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Sources/SnapshotTesting/Snapshotting/NSImage.swift b/Sources/SnapshotTesting/Snapshotting/NSImage.swift index ec43acd5..886f7524 100644 --- a/Sources/SnapshotTesting/Snapshotting/NSImage.swift +++ b/Sources/SnapshotTesting/Snapshotting/NSImage.swift @@ -86,12 +86,13 @@ private func compare(_ old: NSImage, _ new: NSImage, precision: Float, perceptua ) guard let deltaOutputImage = deltaFilter?.outputImage else { return false } let extent = CGRect(x: 0, y: 0, width: oldCgImage.width, height: oldCgImage.height) - let thresholdOutputImage = try? ThresholdImageProcessorKernel.apply( - withExtent: extent, - inputs: [deltaOutputImage], - arguments: [ThresholdImageProcessorKernel.inputThresholdKey: (1 - perceptualPrecision) * 100] - ) - guard let thresholdOutputImage = thresholdOutputImage else { return false } + guard + let thresholdOutputImage = try? ThresholdImageProcessorKernel.apply( + withExtent: extent, + inputs: [deltaOutputImage], + arguments: [ThresholdImageProcessorKernel.inputThresholdKey: (1 - perceptualPrecision) * 100] + ) + else { return false } let averageFilter = CIFilter( name: "CIAreaAverage", parameters: [