Kaynağa Gözat

avoid recreating animated image representation if reloaded with same options

Yang Chao 1 yıl önce
ebeveyn
işleme
d729a94878

+ 1 - 1
Sources/General/KingfisherManager.swift

@@ -601,7 +601,7 @@ public class KingfisherManager: @unchecked Sendable {
                 // TODO: Optimize it when we can use async across all the project.
                 @Sendable func checkResultImageAndCallback(_ inputImage: KFCrossPlatformImage) {
                     var image = inputImage
-                    if image.kf.imageFrameCount != nil && image.kf.imageFrameCount != 1, let data = image.kf.animatedImageData {
+                    if image.kf.imageFrameCount != nil && image.kf.imageFrameCount != 1, options.imageCreatingOptions != image.kf.imageCreatingOptions, let data = image.kf.animatedImageData {
                         // Always recreate animated image representation since it is possible to be loaded in different options.
                         // https://github.com/onevcat/Kingfisher/issues/1923
                         image = options.processor.process(item: .data(data), options: options) ?? .init()

+ 1 - 1
Sources/Image/GIFAnimatedImage.swift

@@ -28,7 +28,7 @@ import Foundation
 import ImageIO
 
 /// Represents a set of image creation options used in Kingfisher.
-public struct ImageCreatingOptions {
+public struct ImageCreatingOptions: Equatable {
 
     /// The target scale of the image that needs to be created.
     public var scale: CGFloat

+ 9 - 0
Sources/Image/Image.swift

@@ -47,6 +47,7 @@ import UniformTypeIdentifiers
 nonisolated(unsafe) private let animatedImageDataKey = malloc(1)!
 nonisolated(unsafe) private let imageFrameCountKey = malloc(1)!
 nonisolated(unsafe) private let imageSourceKey = malloc(1)!
+nonisolated(unsafe) private let imageCreatingOptionsKey = malloc(1)!
 #if os(macOS)
 nonisolated(unsafe) private let imagesKey = malloc(1)!
 nonisolated(unsafe) private let durationKey = malloc(1)!
@@ -55,6 +56,7 @@ nonisolated(unsafe) private let durationKey = malloc(1)!
 private let animatedImageDataKey = malloc(1)!
 private let imageFrameCountKey = malloc(1)!
 private let imageSourceKey = malloc(1)!
+private let imageCreatingOptionsKey = malloc(1)!
 #if os(macOS)
 private let imagesKey = malloc(1)!
 private let durationKey = malloc(1)!
@@ -68,6 +70,11 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
         set { setRetainedAssociatedObject(base, animatedImageDataKey, newValue) }
     }
     
+    private(set) var imageCreatingOptions: ImageCreatingOptions? {
+        get { return getAssociatedObject(base, imageCreatingOptionsKey) }
+        set { setRetainedAssociatedObject(base, imageCreatingOptionsKey, newValue) }
+    }
+    
     public var imageFrameCount: Int? {
         get { return getAssociatedObject(base, imageFrameCountKey) }
         set { setRetainedAssociatedObject(base, imageFrameCountKey, newValue) }
@@ -359,6 +366,7 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
         image?.kf.animatedImageData = source.data
         image?.kf.imageFrameCount = source.frameCount
         image?.kf.frameSource = source
+        image?.kf.imageCreatingOptions = options
         return image
         #else
         
@@ -390,6 +398,7 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
         }
         
         image?.kf.imageFrameCount = source.frameCount
+        image?.kf.imageCreatingOptions = options
         return image
         #endif
     }

+ 19 - 0
Tests/KingfisherTests/KingfisherManagerTests.swift

@@ -1352,6 +1352,25 @@ class KingfisherManagerTests: XCTestCase {
         waitForExpectations(timeout: 3, handler: nil)
     }
     
+    func testAnimatedImageShouldNotRecreateWithSameOptions() {
+        let exp = expectation(description: #function)
+        let url = testURLs[0]
+        let data = testImageGIFData
+        stub(url, data: data)
+        let p = SimpleProcessor()
+        manager.retrieveImage(with: url, options: [.processor(p), .onlyLoadFirstFrame]) { result in
+            XCTAssertTrue(p.processed)
+            XCTAssertTrue(result.value!.image.creatingOptions!.onlyFirstFrame)
+            p.processed = false
+            self.manager.retrieveImage(with: url, options: [.processor(p), .onlyLoadFirstFrame]) { result in
+                XCTAssertFalse(p.processed)
+                XCTAssertTrue(result.value!.image.creatingOptions!.onlyFirstFrame)
+                exp.fulfill()
+            }
+        }
+        waitForExpectations(timeout: 3, handler: nil)
+    }
+    
     func testMissingResourceOfLivePhotoFound() {
         let resource = KF.ImageResource(downloadURL: LivePhotoURL.mov)
         let source = LivePhotoSource(resources: [resource])