Skip to content

Commit

Permalink
A little bit of updated logic for compression quality
Browse files Browse the repository at this point in the history
  • Loading branch information
alexey1312 committed Sep 7, 2024
1 parent b5f964a commit 4deb7cc
Show file tree
Hide file tree
Showing 18 changed files with 93 additions and 73 deletions.
67 changes: 38 additions & 29 deletions Sources/SnapshotTestingHEIC/HEIC/CompressionQuality.swift
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
import Foundation

public struct CompressionQuality: ExpressibleByFloatLiteral {
public typealias FloatLiteralType = Float

public let value: Float

public init(floatLiteral value: Float) {
self.value = value
}

public init(_ value: Float) {
self.value = value
}

public static var lossless: CompressionQuality {
return 1.0
}
public enum CompressionQuality: Hashable, RawRepresentable {
case lossless
case low
case medium
case high
case maximum
case custom(CGFloat)

public static var low: CompressionQuality {
return 0.8
public init?(rawValue: CGFloat) {
switch rawValue {
case 1.0:
self = .lossless
case 0.8:
self = .low
case 0.5:
self = .medium
case 0.2:
self = .high
case 0.0:
self = .maximum
default:
self = .custom(rawValue)
}
}

public static var medium: CompressionQuality {
return 0.5
}

public static var high: CompressionQuality {
return 0.2
}

public static var maximum: CompressionQuality {
return 0.0

public var rawValue: CGFloat {
switch self {
case .lossless:
return 1.0
case .low:
return 0.8
case .medium:
return 0.5
case .high:
return 0.2
case .maximum:
return 0.0
case let .custom(value):
return value
}
}
}
4 changes: 2 additions & 2 deletions Sources/SnapshotTestingHEIC/HEIC/NSImage+HEIC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import AVFoundation
import Cocoa

extension NSImage {
func heicData(compressionQuality: CompressionQuality = .lossless) -> Data? {
func heicData(compressionQuality: CompressionQuality) -> Data? {
let data = NSMutableData()

guard let imageDestination = CGImageDestinationCreateWithData(
Expand All @@ -17,7 +17,7 @@ extension NSImage {
else { return nil }

let options: NSDictionary = [
kCGImageDestinationLossyCompressionQuality: compressionQuality.value
kCGImageDestinationLossyCompressionQuality: compressionQuality.rawValue
]

CGImageDestinationAddImage(imageDestination, cgImage, options)
Expand Down
19 changes: 13 additions & 6 deletions Sources/SnapshotTestingHEIC/HEIC/UIImage+HEIC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,30 @@ import UIKit

@available(tvOSApplicationExtension 11.0, *)
extension UIImage {
func heicData(compressionQuality: CompressionQuality = .lossless) -> Data? {
func heicData(compressionQuality: CGFloat) -> Data? {
let data = NSMutableData()

guard let imageDestination = CGImageDestinationCreateWithData(
data, AVFileType.heic as CFString, 1, nil
)
else { return nil }

guard let cgImage = cgImage else { return nil }
guard let cgImage = cgImage
else { return nil }

let options: NSDictionary = [
kCGImageDestinationLossyCompressionQuality: compressionQuality.value
]
let options: NSDictionary?
if compressionQuality >= 1 {
options = nil
} else {
options = [
kCGImageDestinationLossyCompressionQuality: compressionQuality
]
}

CGImageDestinationAddImage(imageDestination, cgImage, options)

guard CGImageDestinationFinalize(imageDestination) else { return nil }
guard CGImageDestinationFinalize(imageDestination)
else { return nil }

return data as Data
}
Expand Down
17 changes: 10 additions & 7 deletions Sources/SnapshotTestingHEIC/UIImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ public extension Diffing where Value == UIImage {
} else {
imageScale = UIScreen.main.scale
}


let emptyHeicData: Data
if #available(iOS 17.0, *) {
emptyHeicData = emptyImage().heicData() ?? Data()
} else {
emptyHeicData = Data()
}
return Diffing(
toData: {
return $0.heicData(compressionQuality: compressionQuality) ?? emptyImage()
.heicData(compressionQuality: compressionQuality)!
},
fromData: { UIImage(data: $0, scale: imageScale)! },
toData: { $0.heicData(compressionQuality: compressionQuality.rawValue) ?? emptyHeicData },
fromData: { UIImage(data: $0, scale: imageScale) ?? emptyImage() },
diff: { old, new in
guard let message = compare(old, new,
precision: precision,
Expand Down Expand Up @@ -135,7 +138,7 @@ private func compare(
var newerBytes = [UInt8](repeating: 0, count: byteCount)

guard
let heicData = new.heicData(compressionQuality: compressionQuality),
let heicData = new.heicData(compressionQuality: compressionQuality.rawValue),
let newerCgImage = UIImage(data: heicData)?.cgImage,
let newerContext = context(for: newerCgImage, data: &newerBytes),
let newerData = newerContext.data
Expand Down
52 changes: 25 additions & 27 deletions Tests/SnapshotTestingHEICTests/SnapshotTestingHEICTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ final class SnapshotTestingHEICTests: XCTestCase {
override func setUp() {
super.setUp()
sut = TestViewController()
// isRecording = true
}

override func tearDown() {
Expand All @@ -23,78 +22,77 @@ final class SnapshotTestingHEICTests: XCTestCase {

// // ViewController Tests
func test_without_HEIC() {
assertSnapshot(matching: sut, as: .image(on: .iPadPro12_9))
assertSnapshot(of: sut, as: .image(on: .iPadPro12_9))
}

func test_HEIC_compressionQuality_lossless() {
assertSnapshot(matching: sut, as: .imageHEIC(on: .iPadPro12_9,
compressionQuality: .lossless))
assertSnapshot(of: sut, as: .imageHEIC(on: .iPadPro12_9, compressionQuality: .lossless))
}

func test_HEIC_compressionQuality_medium() {
assertSnapshot(matching: sut, as: .imageHEIC(on: .iPadPro12_9,
compressionQuality: .medium))
assertSnapshot(of: sut, as: .imageHEIC(on: .iPadPro12_9, compressionQuality: .medium))
}

func test_HEIC_compressionQuality_maximum() {
assertSnapshot(matching: sut, as: .imageHEIC(on: .iPadPro12_9,
compressionQuality: .maximum))
assertSnapshot(of: sut, as: .imageHEIC(on: .iPadPro12_9, compressionQuality: .maximum))
}

func test_HEIC_compressionQuality_custom() {
assertSnapshot(matching: sut, as: .imageHEIC(on: .iPadPro12_9,
compressionQuality: 0.75))
assertSnapshot(of: sut, as: .imageHEIC(on: .iPadPro12_9, compressionQuality: .custom(0.75) ))
}

func test_HEIC_compressionQuality_custom_minus() {
assertSnapshot(of: sut, as: .imageHEIC(on: .iPadPro12_9, compressionQuality: .custom(-20) ))
}

// SwiftUI Tests

func test_swiftui_without_HEIC() {
let view: some SwiftUI.View = SwiftUIView_Previews.previews
let view: some SwiftUI.View = SwiftUIView()

assertSnapshot(matching: view,
as: .imageHEIC(layout: .device(config: .iPadPro12_9)))
assertSnapshot(of: view, as: .imageHEIC(layout: .device(config: .iPadPro12_9)))
}

func test_swiftui_HEIC_compressionQuality_lossless() {
let view: some SwiftUI.View = SwiftUIView_Previews.previews
let view: some SwiftUI.View = SwiftUIView()

assertSnapshot(matching: view,
as: .imageHEIC(
assertSnapshot(of: view,
as: .imageHEIC(
layout: .device(config: .iPadPro12_9),
compressionQuality: .lossless
)
)
)
}

func test_swiftui_HEIC_compressionQuality_medium() {
let view: some SwiftUI.View = SwiftUIView_Previews.previews
let view: some SwiftUI.View = SwiftUIView()

assertSnapshot(matching: view,
as: .imageHEIC(
assertSnapshot(of: view,
as: .imageHEIC(
layout: .device(config: .iPadPro12_9),
compressionQuality: .medium
)
)
}

func test_swiftui_HEIC_compressionQuality_maximum() {
let view: some SwiftUI.View = SwiftUIView_Previews.previews
let view: some SwiftUI.View = SwiftUIView()

assertSnapshot(matching: view,
as: .imageHEIC(
assertSnapshot(of: view,
as: .imageHEIC(
layout: .device(config: .iPadPro12_9),
compressionQuality: .maximum
)
)
}

func test_swiftui_HEIC_compressionQuality_custom() {
let view: some SwiftUI.View = SwiftUIView_Previews.previews
let view: some SwiftUI.View = SwiftUIView()

assertSnapshot(matching: view,
assertSnapshot(of: view,
as: .imageHEIC(
layout: .device(config: .iPadPro12_9),
compressionQuality: 0.75
compressionQuality: .custom(0.75)
)
)
}
Expand All @@ -119,7 +117,7 @@ final class SnapshotTestingHEICTests: XCTestCase {
button.layer?.backgroundColor = NSColor.red.cgColor
button.sizeToFit()
// then
assertSnapshot(matching: view, as: .imageHEIC)
assertSnapshot(of: view, as: .imageHEIC)
}
#endif

Expand Down
7 changes: 5 additions & 2 deletions Tests/SnapshotTestingHEICTests/TestViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ class TestViewController: UIViewController {
label.text = "Test SnapshotTestingHEIC"
label.translatesAutoresizingMaskIntoConstraints = false
label.font = .systemFont(ofSize: 64)
label.textAlignment = .center
self.view.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
label.topAnchor.constraint(equalTo: self.view.topAnchor),
label.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
label.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
label.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
])
}
}
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4deb7cc

Please sign in to comment.