Browse Source

Cropping support for Image processor

onevcat 9 years ago
parent
commit
9f40885cd6
2 changed files with 52 additions and 5 deletions
  1. 30 5
      Sources/Image.swift
  2. 22 0
      Sources/ImageProcessor.swift

+ 30 - 5
Sources/Image.swift

@@ -141,11 +141,11 @@ extension Kingfisher where Base: Image {
     }
     #else
     static func image(cgImage: CGImage, scale: CGFloat, refImage: Image?) -> Image {
-    if let refImage = refImage {
-        return Image(cgImage: cgImage, scale: scale, orientation: refImage.imageOrientation)
-    } else {
-        return Image(cgImage: cgImage, scale: scale, orientation: .up)
-    }
+        if let refImage = refImage {
+            return Image(cgImage: cgImage, scale: scale, orientation: refImage.imageOrientation)
+        } else {
+            return Image(cgImage: cgImage, scale: scale, orientation: .up)
+        }
     }
     
     /**
@@ -430,6 +430,21 @@ extension Kingfisher where Base: Image {
         }
     }
     
+    public func crop(to size: CGSize, anchorOn anchor: CGPoint) -> Image {
+        guard let cgImage = cgImage else {
+            assertionFailure("[Kingfisher] Crop only works for CG-based image.")
+            return base
+        }
+        
+        let rect = base.size.kf.constrainedRect(for: size, anchor: anchor)
+        guard let image = cgImage.cropping(to: rect) else {
+            assertionFailure("[Kingfisher] Cropping image failed.")
+            return base
+        }
+        
+        return Kingfisher.image(cgImage: image, scale: scale, refImage: base)
+    }
+    
     // MARK: - Blur
     
     /// Create an image with blur effect based on `self`.
@@ -716,6 +731,16 @@ extension CGSizeProxy {
     private var aspectRatio: CGFloat {
         return base.height == 0.0 ? 1.0 : base.width / base.height
     }
+    
+    
+    func constrainedRect(for size: CGSize, anchor: CGPoint) -> CGRect {
+        let x = anchor.x * base.width - anchor.x * size.width
+        let y = anchor.y * base.height - anchor.y * size.height
+        let r = CGRect(x: x, y: y, width: size.width, height: size.height)
+        
+        let ori = CGRect(origin: CGPoint.zero, size: base)
+        return ori.intersection(r)
+    }
 }
 
 extension Kingfisher where Base: Image {

+ 22 - 0
Sources/ImageProcessor.swift

@@ -366,6 +366,28 @@ public struct BlackWhiteProcessor: ImageProcessor {
     }
 }
 
+public struct CroppingImageProcessor: ImageProcessor {
+    
+    public let identifier: String
+    
+    public let size: CGSize
+    public let anchor: CGPoint
+    
+    public init(size: CGSize, anchor: CGPoint = CGPoint(x: 0.5, y: 0.5)) {
+        self.size = size
+        self.anchor = anchor
+        self.identifier = "com.onevcat.Kingfisher.CroppingImageProcessor(\(size),\(anchor))"
+    }
+    
+    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
+        switch item {
+        case .image(let image):
+            return image.kf.crop(to: size, anchorOn: anchor)
+        case .data(_): return (DefaultImageProcessor.default >> self).process(item: item, options: options)
+        }
+    }
+}
+
 /// Concatenate two `ImageProcessor`s. `ImageProcessor.appen(another:)` is used internally.
 ///
 /// - parameter left:  First processor.