Przeglądaj źródła

优化渐进式JPEG加载效果 增加模糊效果开关

lixiang1994 6 lat temu
rodzic
commit
e22ad9b68c

+ 5 - 4
Demo/Demo/Kingfisher-Demo/Base.lproj/Main.storyboard

@@ -708,14 +708,13 @@
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
                             <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="akD-zs-eTn">
-                                <rect key="frame" x="89" y="74" width="236" height="236"/>
+                                <rect key="frame" x="0.0" y="74" width="414" height="414"/>
                                 <constraints>
-                                    <constraint firstAttribute="width" constant="236" id="HYO-L6-Htj"/>
-                                    <constraint firstAttribute="height" constant="236" id="Lyz-IW-83o"/>
+                                    <constraint firstAttribute="width" secondItem="akD-zs-eTn" secondAttribute="height" multiplier="1:1" id="bvS-PE-dXe"/>
                                 </constraints>
                             </imageView>
                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="izF-cD-0cm">
-                                <rect key="frame" x="0.0" y="340" width="414" height="0.0"/>
+                                <rect key="frame" x="0.0" y="518" width="414" height="0.0"/>
                                 <fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="17"/>
                                 <nil key="textColor"/>
                                 <nil key="highlightedColor"/>
@@ -726,6 +725,8 @@
                             <constraint firstItem="akD-zs-eTn" firstAttribute="centerX" secondItem="cGe-Lq-jhl" secondAttribute="centerX" id="5kh-xV-bka"/>
                             <constraint firstItem="izF-cD-0cm" firstAttribute="width" secondItem="cGe-Lq-jhl" secondAttribute="width" id="Aut-Lw-Huc"/>
                             <constraint firstItem="akD-zs-eTn" firstAttribute="top" secondItem="yCs-FZ-4DV" secondAttribute="bottom" constant="10" id="HtJ-QY-RlR"/>
+                            <constraint firstAttribute="trailing" secondItem="akD-zs-eTn" secondAttribute="trailing" id="IbZ-qg-qTg"/>
+                            <constraint firstItem="akD-zs-eTn" firstAttribute="leading" secondItem="cGe-Lq-jhl" secondAttribute="leading" id="d4F-SH-Rkc"/>
                             <constraint firstItem="izF-cD-0cm" firstAttribute="centerX" secondItem="cGe-Lq-jhl" secondAttribute="centerX" id="i2T-YC-hzq"/>
                             <constraint firstItem="izF-cD-0cm" firstAttribute="top" secondItem="akD-zs-eTn" secondAttribute="bottom" constant="30" id="oD0-d7-geg"/>
                         </constraints>

+ 29 - 5
Demo/Demo/Kingfisher-Demo/ViewControllers/ProgressiveJPEGViewController.swift

@@ -25,23 +25,30 @@
 //  THE SOFTWARE.
 
 import UIKit
+import Kingfisher
 
 class ProgressiveJPEGViewController: UIViewController {
 
     @IBOutlet weak var imageView: UIImageView!
     @IBOutlet weak var progressLabel: UILabel!
     
+    private var isBlur = true
+    private let url = URL(string: "https://demo-resources.oss-cn-beijing.aliyuncs.com/progressive.jpg")!
+    
     override func viewDidLoad() {
         super.viewDidLoad()
-        title = "Loading"
+        title = "Progressive JPEG"
         setupOperationNavigationBar()
+        loadImage()
+    }
+    
+    private func loadImage() {
+        progressLabel.text = "- / -"
         
         imageView.kf.setImage(
-//            with: ImageLoader.sampleImageURLs[indexPath.row],
-//            with: URL(string: "http://calm.chongdingdahui.com/812075.jpg"),
-            with: URL(string: "https://demo-resources.oss-cn-beijing.aliyuncs.com/progressive.jpeg"),
+            with: url,
             placeholder: nil,
-            options: [.loadDiskFileSynchronously, .progressiveJPEG],
+            options: [.loadDiskFileSynchronously, .progressiveJPEG(isBlur)],
             progressBlock: { receivedSize, totalSize in
                 print("\(receivedSize)/\(totalSize)")
                 self.progressLabel.text = "\(receivedSize) / \(totalSize)"
@@ -52,4 +59,21 @@ class ProgressiveJPEGViewController: UIViewController {
             }
         )
     }
+    
+    override func alertPopup(_ sender: Any) -> UIAlertController {
+        let alert = super.alertPopup(sender)
+        let title = isBlur ? "Close Blur" : "Enabled Blur"
+        alert.addAction(UIAlertAction(title: title, style: .default) { _ in
+            self.isBlur.toggle()
+            // Clean cache
+            KingfisherManager.shared.cache.removeImage(
+                forKey: self.url.cacheKey,
+                callbackQueue: .mainAsync,
+                completionHandler: {
+                    self.loadImage()
+                }
+            )
+        })
+        return alert
+    }
 }

+ 5 - 3
Sources/General/KingfisherOptionsInfo.swift

@@ -214,7 +214,9 @@ public enum KingfisherOptionsInfoItem {
     /// blocking the UI, especially if the processor needs a lot of time to run).
     case processingQueue(CallbackQueue)
     
-    case progressiveJPEG
+    /// Enable progressive image loading
+    /// true: Increase blur effect processing, false: No additional processing.
+    case progressiveJPEG(Bool)
 }
 
 // Improve performance by parsing the input `KingfisherOptionsInfo` (self) first.
@@ -253,7 +255,7 @@ public struct KingfisherParsedOptionsInfo {
     public var memoryCacheExpiration: StorageExpiration? = nil
     public var diskCacheExpiration: StorageExpiration? = nil
     public var processingQueue: CallbackQueue? = nil
-    public var progressiveJPEG = false
+    public var progressiveJPEG: Bool?
     
     public init(_ info: KingfisherOptionsInfo?) {
         guard let info = info else { return }
@@ -289,7 +291,7 @@ public struct KingfisherParsedOptionsInfo {
             case .memoryCacheExpiration(let expiration): memoryCacheExpiration = expiration
             case .diskCacheExpiration(let expiration): diskCacheExpiration = expiration
             case .processingQueue(let queue): processingQueue = queue
-            case .progressiveJPEG: progressiveJPEG = true
+            case .progressiveJPEG(let isBlur): progressiveJPEG = isBlur
             }
         }
 

+ 38 - 17
Sources/Image/ImageProgressive.swift

@@ -26,6 +26,9 @@
 
 import UIKit
 
+private let sharedProcessingQueue: CallbackQueue =
+    .dispatch(DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.Process"))
+
 final class ImageProgressive {
     
     private let options: KingfisherParsedOptionsInfo
@@ -38,7 +41,7 @@ final class ImageProgressive {
     }
     
     func scanning(_ data: Data) -> Data? {
-        guard options.progressiveJPEG, data.kf.contains(jpeg: .SOF2) else {
+        guard let _ = options.progressiveJPEG, data.kf.contains(jpeg: .SOF2) else {
             return nil
         }
         guard (scannedIndex + 1) < data.count else {
@@ -71,23 +74,41 @@ final class ImageProgressive {
     }
     
     func decode(_ data: Data, with callbacks: [SessionDataTask.TaskCallback], completion: @escaping (Image) -> Void) {
-        let processor = ImageDataProcessor(
-            data: data[0 ..< lastSOSIndex],
-            callbacks: callbacks,
-            processingQueue: options.processingQueue
-        )
-        processor.onImageProcessed.delegate(on: self) { (self, result) in
-            guard let image = try? result.0.get() else { return }
+        guard let isBlur = options.progressiveJPEG, data.kf.contains(jpeg: .SOF2) else {
+            return
+        }
+        
+        func processing(_ data: Data) {
+            let processor = ImageDataProcessor(
+                data: data,
+                callbacks: callbacks,
+                processingQueue: options.processingQueue
+            )
+            processor.onImageProcessed.delegate(on: self) { (self, result) in
+                guard let image = try? result.0.get() else { return }
+                
+                CallbackQueue.mainCurrentOrAsync.execute { completion(image) }
+            }
+            processor.process()
+        }
+        
+        // Blur partial images.
+        let count = scannedCount
+        if isBlur, count < 5 {
+            let queue = options.processingQueue ?? sharedProcessingQueue
+            queue.execute {
+                // Progressively reduce blur as we load more scans.
+                let radius = max(2, 14 - count * 4)
+                let image = KingfisherWrapper<Image>.image(
+                    data: data,
+                    options: self.options.imageCreatingOptions
+                )
+                let temp = image?.kf.blurred(withRadius: CGFloat(radius))
+                processing(temp?.kf.data(format: .JPEG) ?? data)
+            }
             
-            // Blur partial images.
-//            if self.scannedCount < 5 {
-//                // Progressively reduce blur as we load more scans.
-//                let radius = max(2, 14 - self.scannedCount * 4)
-//                image = image.kf.blurred(withRadius: CGFloat(radius))
-//            }
-
-            CallbackQueue.mainCurrentOrAsync.execute { completion(image) }
+        } else {
+            processing(data)
         }
-        processor.process()
     }
 }