From f7dd8498dfa44eb7128970527ad19ed05c347938 Mon Sep 17 00:00:00 2001 From: Amol Prabhu Date: Fri, 21 Jun 2024 15:43:28 -0400 Subject: [PATCH] Image is right oriented so lets rename it more tests use scale make scale non optional --- Nuke.xcodeproj/project.pbxproj | 16 ++++++++-------- .../Nuke/Decoding/ImageDecoders+Default.swift | 12 +++++++----- Sources/Nuke/Internal/Graphics.swift | 6 +++--- .../ImagePipelineCacheTests.swift | 4 ++-- .../ImageDownsampleTests.swift | 17 ++++++++++++++++- .../ImageProcessorsTests/ResizeTests.swift | 6 +++--- ...orientation.jpeg => right-orientation.jpeg} | Bin 7 files changed, 39 insertions(+), 22 deletions(-) rename Tests/Resources/{left-orientation.jpeg => right-orientation.jpeg} (100%) diff --git a/Nuke.xcodeproj/project.pbxproj b/Nuke.xcodeproj/project.pbxproj index 2179cfcf5..6cf60c5c5 100644 --- a/Nuke.xcodeproj/project.pbxproj +++ b/Nuke.xcodeproj/project.pbxproj @@ -49,7 +49,7 @@ 0C38DB2928568FE20027F9FF /* fixture-tiny.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0C91B0F72438E84E007F9100 /* fixture-tiny.jpeg */; }; 0C38DB2A28568FE20027F9FF /* baseline.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0C70D9702089016800A49DAC /* baseline.jpeg */; }; 0C38DB2B28568FE20027F9FF /* baseline.webp in Resources */ = {isa = PBXBuildFile; fileRef = 0C95FD532571B278008D4FC2 /* baseline.webp */; }; - 0C38DB2C28568FE20027F9FF /* left-orientation.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0CF5456A25B39A0E00B45F1E /* left-orientation.jpeg */; }; + 0C38DB2C28568FE20027F9FF /* right-orientation.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0CF5456A25B39A0E00B45F1E /* right-orientation.jpeg */; }; 0C38DB2D28568FE20027F9FF /* s-rounded-corners.png in Resources */ = {isa = PBXBuildFile; fileRef = 0C7CE28A243933550018C8C3 /* s-rounded-corners.png */; }; 0C38DB2E28568FE20027F9FF /* video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 0CA4ECA226E67E3D00BAC8E5 /* video.mp4 */; }; 0C38DB2F28568FE20027F9FF /* progressive.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0C70D96F2089016700A49DAC /* progressive.jpeg */; }; @@ -217,7 +217,7 @@ 0CB6449C28567E5400916267 /* ImageViewLoadingOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB6449B28567E5400916267 /* ImageViewLoadingOptionsTests.swift */; }; 0CB644AB28567EEA00916267 /* ImageViewExtensionsProgressiveDecodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB644AA28567EEA00916267 /* ImageViewExtensionsProgressiveDecodingTests.swift */; }; 0CB644AC28567FC000916267 /* NukeExtensions.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C55FCFD28567875000FD2C9 /* NukeExtensions.framework */; }; - 0CB644BE2856807F00916267 /* left-orientation.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0CF5456A25B39A0E00B45F1E /* left-orientation.jpeg */; }; + 0CB644BE2856807F00916267 /* right-orientation.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0CF5456A25B39A0E00B45F1E /* right-orientation.jpeg */; }; 0CB644BF2856807F00916267 /* cat.gif in Resources */ = {isa = PBXBuildFile; fileRef = 0C8DC722209B842600084AA6 /* cat.gif */; }; 0CB644C02856807F00916267 /* progressive.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0C70D96F2089016700A49DAC /* progressive.jpeg */; }; 0CB644C12856807F00916267 /* baseline.webp in Resources */ = {isa = PBXBuildFile; fileRef = 0C95FD532571B278008D4FC2 /* baseline.webp */; }; @@ -260,7 +260,7 @@ 0CF235E529A16006001BCA2F /* FetchImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C55FD1D28567926000FD2C9 /* FetchImage.swift */; }; 0CF235E629A16006001BCA2F /* LazyImageState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C38DB6F2856A4D30027F9FF /* LazyImageState.swift */; }; 0CF4DE7D1D412A9E00170289 /* ImagePrefetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF4DE7C1D412A9E00170289 /* ImagePrefetcher.swift */; }; - 0CF5456B25B39A0E00B45F1E /* left-orientation.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0CF5456A25B39A0E00B45F1E /* left-orientation.jpeg */; }; + 0CF5456B25B39A0E00B45F1E /* right-orientation.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0CF5456A25B39A0E00B45F1E /* right-orientation.jpeg */; }; 0CF58FF726DAAC3800D2650D /* ImageDownsampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF58FF626DAAC3800D2650D /* ImageDownsampleTests.swift */; }; 2DFD93B0233A6AB300D84DB9 /* ImagePipelineProcessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DFD93AF233A6AB300D84DB9 /* ImagePipelineProcessorTests.swift */; }; 4480674C2A448C9F00DE7CF8 /* DataPublisherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4480674B2A448C9F00DE7CF8 /* DataPublisherTests.swift */; }; @@ -529,7 +529,7 @@ 0CF1754B22913F9800A8946E /* ImagePipeline+Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ImagePipeline+Configuration.swift"; sourceTree = ""; }; 0CF4DE7C1D412A9E00170289 /* ImagePrefetcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImagePrefetcher.swift; sourceTree = ""; }; 0CF52DCB26516F6B0094BC66 /* FetchImageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchImageTests.swift; sourceTree = ""; }; - 0CF5456A25B39A0E00B45F1E /* left-orientation.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "left-orientation.jpeg"; sourceTree = ""; }; + 0CF5456A25B39A0E00B45F1E /* right-orientation.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "right-orientation.jpeg"; sourceTree = ""; }; 0CF58FF626DAAC3800D2650D /* ImageDownsampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageDownsampleTests.swift; sourceTree = ""; }; 2DFD93AF233A6AB300D84DB9 /* ImagePipelineProcessorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePipelineProcessorTests.swift; sourceTree = ""; }; 4480674B2A448C9F00DE7CF8 /* DataPublisherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataPublisherTests.swift; sourceTree = ""; }; @@ -629,7 +629,7 @@ isa = PBXGroup; children = ( 0C70D9702089016800A49DAC /* baseline.jpeg */, - 0CF5456A25B39A0E00B45F1E /* left-orientation.jpeg */, + 0CF5456A25B39A0E00B45F1E /* right-orientation.jpeg */, 0C4B34112572E233000FDDBA /* grayscale.jpeg */, 0C70D96F2089016700A49DAC /* progressive.jpeg */, 0C95FD532571B278008D4FC2 /* baseline.webp */, @@ -1353,7 +1353,7 @@ 0C38DB2928568FE20027F9FF /* fixture-tiny.jpeg in Resources */, 0C38DB2A28568FE20027F9FF /* baseline.jpeg in Resources */, 0C38DB2B28568FE20027F9FF /* baseline.webp in Resources */, - 0C38DB2C28568FE20027F9FF /* left-orientation.jpeg in Resources */, + 0C38DB2C28568FE20027F9FF /* right-orientation.jpeg in Resources */, 0C38DB2D28568FE20027F9FF /* s-rounded-corners.png in Resources */, 0C38DB2E28568FE20027F9FF /* video.mp4 in Resources */, 0C38DB2F28568FE20027F9FF /* progressive.jpeg in Resources */, @@ -1394,7 +1394,7 @@ 0CB644C22856807F00916267 /* image-p3.jpg in Resources */, 0CB644C92856807F00916267 /* fixture.jpeg in Resources */, 0CB644C52856807F00916267 /* fixture-tiny.jpeg in Resources */, - 0CB644BE2856807F00916267 /* left-orientation.jpeg in Resources */, + 0CB644BE2856807F00916267 /* right-orientation.jpeg in Resources */, 0CB644C72856807F00916267 /* baseline.jpeg in Resources */, 0CB644BF2856807F00916267 /* cat.gif in Resources */, ); @@ -1418,7 +1418,7 @@ 0C91B0F82438E84E007F9100 /* fixture-tiny.jpeg in Resources */, 0C70D9742089016800A49DAC /* baseline.jpeg in Resources */, 0C95FD542571B278008D4FC2 /* baseline.webp in Resources */, - 0CF5456B25B39A0E00B45F1E /* left-orientation.jpeg in Resources */, + 0CF5456B25B39A0E00B45F1E /* right-orientation.jpeg in Resources */, 0C7CE28B243933550018C8C3 /* s-rounded-corners.png in Resources */, 0CA4ECA426E67ED500BAC8E5 /* video.mp4 in Resources */, 0C70D9712089016800A49DAC /* progressive.jpeg in Resources */, diff --git a/Sources/Nuke/Decoding/ImageDecoders+Default.swift b/Sources/Nuke/Decoding/ImageDecoders+Default.swift index 9cafe07db..6f4f82871 100644 --- a/Sources/Nuke/Decoding/ImageDecoders+Default.swift +++ b/Sources/Nuke/Decoding/ImageDecoders+Default.swift @@ -27,7 +27,7 @@ extension ImageDecoders { private var scanner = ProgressiveJPEGScanner() private var isPreviewForGIFGenerated = false - private var scale: CGFloat? + private var scale: CGFloat = 1.0 private var thumbnail: ImageRequest.ThumbnailOptions? private let lock = NSLock() @@ -38,7 +38,7 @@ extension ImageDecoders { /// Returns `nil` if progressive decoding is not allowed for the given /// content. public init?(context: ImageDecodingContext) { - self.scale = context.request.scale.map { CGFloat($0) } + self.scale = context.request.scale.map { CGFloat($0) } ?? 1.0 self.thumbnail = context.request.thumbnail if !context.isCompleted && !isProgressiveDecodingAllowed(for: context.data) { @@ -52,7 +52,9 @@ extension ImageDecoders { func makeImage() -> PlatformImage? { if let thumbnail { - return makeThumbnail(data: data, options: thumbnail) + return makeThumbnail(data: data, + options: thumbnail, + scale: scale) } return ImageDecoders.Default._decode(data, scale: scale) } @@ -162,11 +164,11 @@ private struct ProgressiveJPEGScanner: Sendable { } extension ImageDecoders.Default { - private static func _decode(_ data: Data, scale: CGFloat?) -> PlatformImage? { + private static func _decode(_ data: Data, scale: CGFloat) -> PlatformImage? { #if os(macOS) return NSImage(data: data) #else - return UIImage(data: data, scale: scale ?? 1) + return UIImage(data: data, scale: scale) #endif } } diff --git a/Sources/Nuke/Internal/Graphics.swift b/Sources/Nuke/Internal/Graphics.swift index 9b370a61f..0a4fa2ee8 100644 --- a/Sources/Nuke/Internal/Graphics.swift +++ b/Sources/Nuke/Internal/Graphics.swift @@ -365,7 +365,7 @@ extension Color { } /// Creates an image thumbnail. Uses significantly less memory than other options. -func makeThumbnail(data: Data, options: ImageRequest.ThumbnailOptions) -> PlatformImage? { +func makeThumbnail(data: Data, options: ImageRequest.ThumbnailOptions, scale: CGFloat = 1.0) -> PlatformImage? { guard let source = CGImageSourceCreateWithData(data as CFData, [kCGImageSourceShouldCache: false] as CFDictionary) else { return nil } @@ -390,8 +390,8 @@ func makeThumbnail(data: Data, options: ImageRequest.ThumbnailOptions) -> Platfo } else { orientation = .up } - return PlatformImage(cgImage: image, - scale: UIScreen.main.scale, + return PlatformImage(cgImage: image, + scale: scale, orientation: orientation) #else return PlatformImage(cgImage: image) diff --git a/Tests/NukeTests/ImagePipelineTests/ImagePipelineCacheTests.swift b/Tests/NukeTests/ImagePipelineTests/ImagePipelineCacheTests.swift index 5f8890f01..5541e7a97 100644 --- a/Tests/NukeTests/ImagePipelineTests/ImagePipelineCacheTests.swift +++ b/Tests/NukeTests/ImagePipelineTests/ImagePipelineCacheTests.swift @@ -461,7 +461,7 @@ class ImagePipelineCacheTests: XCTestCase { #if canImport(UIKit) func testThatImageOrientationIsPreserved() throws { // GIVEN opaque jpeg with orientation - let image = Test.image(named: "left-orientation", extension: "jpeg") + let image = Test.image(named: "right-orientation", extension: "jpeg") XCTAssertTrue(image.cgImage!.isOpaque) XCTAssertEqual(image.imageOrientation, .right) @@ -477,7 +477,7 @@ class ImagePipelineCacheTests: XCTestCase { func testThatImageOrientationIsPreservedForProcessedImages() throws { // GIVEN opaque jpeg with orientation - let image = Test.image(named: "left-orientation", extension: "jpeg") + let image = Test.image(named: "right-orientation", extension: "jpeg") XCTAssertTrue(image.cgImage!.isOpaque) XCTAssertEqual(image.imageOrientation, .right) diff --git a/Tests/NukeTests/ImageProcessorsTests/ImageDownsampleTests.swift b/Tests/NukeTests/ImageProcessorsTests/ImageDownsampleTests.swift index 5e01b5471..07ae8ab5f 100644 --- a/Tests/NukeTests/ImageProcessorsTests/ImageDownsampleTests.swift +++ b/Tests/NukeTests/ImageProcessorsTests/ImageDownsampleTests.swift @@ -71,7 +71,7 @@ class ImageThumbnailTest: XCTestCase { // Given an image with `right` orientation. From the user perspective, // the image a landscape image with s size 640x480px. The raw pixel // data, on the other hand, is 480x640px. - let input = try XCTUnwrap(Test.data(name: "left-orientation", extension: "jpeg")) + let input = try XCTUnwrap(Test.data(name: "right-orientation", extension: "jpeg")) XCTAssertEqual(PlatformImage(data: input)?.imageOrientation, .right) // When we resize the image to fit 320x480px frame, we expect the processor @@ -86,5 +86,20 @@ class ImageThumbnailTest: XCTestCase { XCTAssertEqual(output.sizeInPixels, CGSize(width: 320, height: 240)) XCTAssertEqual(output.size, CGSize(width: 120, height: 160)) } + + func testResizeImageWithOrientationUp() throws { + let input = try XCTUnwrap(Test.data(name: "baseline", extension: "jpeg")) + XCTAssertEqual(PlatformImage(data: input)?.imageOrientation, .up) + + let options = ImageRequest.ThumbnailOptions(maxPixelSize: 300) + let output = try XCTUnwrap(options.makeThumbnail(with: input)) + + // Then the output has orientation of the original image + XCTAssertEqual(output.imageOrientation, .up) + + //verify size of the image in points and pixels (using scale) + XCTAssertEqual(output.sizeInPixels, CGSize(width: 300, height: 200)) + XCTAssertEqual(output.size, CGSize(width: 150, height: 100)) + } #endif } diff --git a/Tests/NukeTests/ImageProcessorsTests/ResizeTests.swift b/Tests/NukeTests/ImageProcessorsTests/ResizeTests.swift index bdbc566f8..444aae7b7 100644 --- a/Tests/NukeTests/ImageProcessorsTests/ResizeTests.swift +++ b/Tests/NukeTests/ImageProcessorsTests/ResizeTests.swift @@ -123,7 +123,7 @@ class ImageProcessorsResizeTests: XCTestCase { // the image a landscape image with s size 640x480px. The raw pixel // data, on the other hand, is 480x640px. macOS, however, automatically // changes image orientaiton to `up` so that you don't have to worry about it - let input = try XCTUnwrap(Test.image(named: "left-orientation.jpeg")) + let input = try XCTUnwrap(Test.image(named: "right-orientation.jpeg")) // When we resize the image to fit 320x480px frame, we expect the processor // to take image orientation into the account and produce a 320x240px. @@ -143,7 +143,7 @@ class ImageProcessorsResizeTests: XCTestCase { // Given an image with `right` orientation. From the user perspective, // the image a landscape image with s size 640x480px. The raw pixel // data, on the other hand, is 480x640px. - let input = try XCTUnwrap(Test.image(named: "left-orientation.jpeg")) + let input = try XCTUnwrap(Test.image(named: "right-orientation.jpeg")) XCTAssertEqual(input.imageOrientation, .right) // When we resize the image to fit 320x480px frame, we expect the processor @@ -162,7 +162,7 @@ class ImageProcessorsResizeTests: XCTestCase { // Given an image with `right` orientation. From the user perspective, // the image a landscape image with s size 640x480px. The raw pixel // data, on the other hand, is 480x640px. - let input = try XCTUnwrap(Test.image(named: "left-orientation.jpeg")) + let input = try XCTUnwrap(Test.image(named: "right-orientation.jpeg")) XCTAssertEqual(input.imageOrientation, .right) // When diff --git a/Tests/Resources/left-orientation.jpeg b/Tests/Resources/right-orientation.jpeg similarity index 100% rename from Tests/Resources/left-orientation.jpeg rename to Tests/Resources/right-orientation.jpeg