소스 검색

Make image compatible with kf namespacing

onevcat 9 년 전
부모
커밋
c3ef6e5a98

+ 2 - 2
Sources/AnimatedImageView.swift

@@ -159,7 +159,7 @@ public class AnimatedImageView: UIImageView {
     /// Reset the animator.
     private func reset() {
         animator = nil
-        if let imageSource = image?.kf_imageSource?.imageRef {
+        if let imageSource = image?.kf.imageSource?.imageRef {
             animator = Animator(imageSource: imageSource, contentMode: contentMode, size: bounds.size, framePreloadCount: framePreloadCount)
             animator?.needsPrescaling = needsPrescaling
             animator?.prepareFrames()
@@ -281,7 +281,7 @@ class Animator {
         let scaledImage: Image?
         
         if needsPrescaling {
-            scaledImage = image.kf_resize(to: size, for: contentMode)
+            scaledImage = image.kf.resize(to: size, for: contentMode)
         } else {
             scaledImage = image
         }

+ 5 - 5
Sources/CacheSerializer.swift

@@ -67,10 +67,10 @@ public struct DefaultCacheSerializer: CacheSerializer {
         
         let data: Data?
         switch imageFormat {
-        case .PNG: data = image.pngRepresentation()
-        case .JPEG: data = image.jpegRepresentation(compressionQuality: 1.0)
-        case .GIF: data = image.gifRepresentation()
-        case .unknown: data = original ?? image.kf_normalized().pngRepresentation()
+        case .PNG: data = image.kf.pngRepresentation()
+        case .JPEG: data = image.kf.jpegRepresentation(compressionQuality: 1.0)
+        case .GIF: data = image.kf.gifRepresentation()
+        case .unknown: data = original ?? image.kf.normalized.kf.pngRepresentation()
         }
         
         return data
@@ -80,6 +80,6 @@ public struct DefaultCacheSerializer: CacheSerializer {
         let scale = (options ?? KingfisherEmptyOptionsInfo).scaleFactor
         let preloadAllGIFData = (options ?? KingfisherEmptyOptionsInfo).preloadAllGIFData
         
-        return Image.kf_image(data: data, scale: scale, preloadAllGIFData: preloadAllGIFData)
+        return Kingfisher<Image>.image(data: data, scale: scale, preloadAllGIFData: preloadAllGIFData)
     }
 }

+ 22 - 8
Sources/Filter.swift

@@ -46,7 +46,7 @@ extension CIImageProcessor {
         case .image(let image):
             return image.kf_apply(filter)
         case .data(let data):
-            return Image.kf_image(data: data, scale: options.scaleFactor, preloadAllGIFData: options.preloadAllGIFData)
+            return Kingfisher<Image>.image(data: data, scale: options.scaleFactor, preloadAllGIFData: options.preloadAllGIFData)
         }
     }
 }
@@ -93,8 +93,7 @@ public struct Filter {
     }
 }
 
-public extension Image {
-    
+extension Kingfisher where Base: Image {
     /// Apply a `Filter` containing `CIImage` transformer to `self`.
     ///
     /// - parameter filter: The filter used to transform `self`.
@@ -102,27 +101,42 @@ public extension Image {
     /// - returns: A transformed image by input `Filter`.
     ///
     /// - Note: Only CG-based images are supported. If any error happens during transforming, `self` will be returned.
-    public func kf_apply(_ filter: Filter) -> Image {
+    public func apply(_ filter: Filter) -> Image {
         
         guard let cgImage = cgImage else {
             assertionFailure("[Kingfisher] Tint image only works for CG-based image.")
-            return self
+            return base
         }
         
         let inputImage = CIImage(cgImage: cgImage)
         guard let outputImage = filter.transform(inputImage) else {
-            return self
+            return base
         }
         
         guard let result = ciContext.createCGImage(outputImage, from: outputImage.extent) else {
             assertionFailure("[Kingfisher] Can not make an tint image within context.")
-            return self
+            return base
         }
         
         #if os(macOS)
-            return kf_fixedForRetinaPixel(cgImage: result, to: kf_size)
+            return fixedForRetinaPixel(cgImage: result, to: size)
         #else
             return Image(cgImage: result)
         #endif
     }
+
+}
+
+public extension Image {
+    
+    /// Apply a `Filter` containing `CIImage` transformer to `self`.
+    ///
+    /// - parameter filter: The filter used to transform `self`.
+    ///
+    /// - returns: A transformed image by input `Filter`.
+    ///
+    /// - Note: Only CG-based images are supported. If any error happens during transforming, `self` will be returned.
+    public func kf_apply(_ filter: Filter) -> Image {
+        return kf.apply(filter)
+    }
 }

+ 279 - 169
Sources/Image.swift

@@ -45,103 +45,107 @@ import CoreImage
 #endif
 
 // MARK: - Image Properties
-extension Image {
-#if os(macOS)
+extension Kingfisher where Base: Image {
+    #if os(macOS)
     var cgImage: CGImage? {
-        return cgImage(forProposedRect: nil, context: nil, hints: nil)
+        return base.cgImage(forProposedRect: nil, context: nil, hints: nil)
     }
     
-    var kf_scale: CGFloat {
+    var scale: CGFloat {
         return 1.0
     }
     
-    fileprivate(set) var kf_images: [Image]? {
+    fileprivate(set) var images: [Image]? {
         get {
-            return objc_getAssociatedObject(self, &imagesKey) as? [Image]
+            return objc_getAssociatedObject(base, &imagesKey) as? [Image]
         }
         set {
-            objc_setAssociatedObject(self, &imagesKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+            objc_setAssociatedObject(base, &imagesKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
         }
     }
     
-    fileprivate(set) var kf_duration: TimeInterval {
+    fileprivate(set) var duration: TimeInterval {
         get {
-            return objc_getAssociatedObject(self, &durationKey) as? TimeInterval ?? 0.0
+            return objc_getAssociatedObject(base, &durationKey) as? TimeInterval ?? 0.0
         }
         set {
-            objc_setAssociatedObject(self, &durationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+            objc_setAssociatedObject(base, &durationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
         }
     }
     
-    var kf_size: CGSize {
-        return representations.reduce(CGSize.zero, { size, rep in
+    var size: CGSize {
+        return base.representations.reduce(CGSize.zero, { size, rep in
             return CGSize(width: max(size.width, CGFloat(rep.pixelsWide)), height: max(size.height, CGFloat(rep.pixelsHigh)))
         })
     }
     
-#else
-    var kf_scale: CGFloat {
-        return scale
+    #else
+    var cgImage: CGImage? {
+        return base.cgImage
     }
     
-    var kf_images: [Image]? {
-        return images
+    var scale: CGFloat {
+    return base.scale
     }
     
-    var kf_duration: TimeInterval {
-        return duration
+    var images: [Image]? {
+    return base.images
     }
     
-    fileprivate(set) var kf_imageSource: ImageSource? {
-        get {
-            return objc_getAssociatedObject(self, &imageSourceKey) as? ImageSource
-        }
-        set {
-            objc_setAssociatedObject(self, &imageSourceKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
+    var duration: TimeInterval {
+    return base.duration
     }
-        
-    fileprivate(set) var kf_animatedImageData: Data? {
+    
+    fileprivate(set) var imageSource: ImageSource? {
         get {
-            return objc_getAssociatedObject(self, &animatedImageDataKey) as? Data
+            return objc_getAssociatedObject(base, &imageSourceKey) as? ImageSource
         }
         set {
-            objc_setAssociatedObject(self, &animatedImageDataKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+            objc_setAssociatedObject(base, &imageSourceKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
         }
     }
     
-    var kf_size: CGSize {
-        return size
+    fileprivate(set) var animatedImageData: Data? {
+    get {
+        return objc_getAssociatedObject(base, &animatedImageDataKey) as? Data
     }
-#endif
+    set {
+        objc_setAssociatedObject(base, &animatedImageDataKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+    }
+    }
+    
+    var size: CGSize {
+        return base.size
+    }
+    #endif
 }
 
 // MARK: - Image Conversion
-extension Image {
-#if os(macOS)
-    static func kf_image(cgImage: CGImage, scale: CGFloat, refImage: Image?) -> Image {
+extension Kingfisher where Base: Image {
+    #if os(macOS)
+    static func image(cgImage: CGImage, scale: CGFloat, refImage: Image?) -> Image {
         return Image(cgImage: cgImage, size: CGSize.zero)
     }
     
     /**
-    Normalize the image. This method does nothing in OS X.
-    
-    - returns: The image itself.
-    */
-    public func kf_normalized() -> Image {
-        return self
+     Normalize the image. This method does nothing in OS X.
+     
+     - returns: The image itself.
+     */
+    public var normalized: Image {
+        return base
     }
     
-    static func kf_animated(with images: [Image], forDuration forDurationduration: TimeInterval) -> Image? {
+    static func animated(with images: [Image], forDuration forDurationduration: TimeInterval) -> Image? {
         return nil
     }
-#else
-    static func kf_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)
-        }
+    #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)
+    }
     }
     
     /**
@@ -149,25 +153,25 @@ extension Image {
      
      - returns: The normalized image with orientation set to up and correct scale.
      */
-    public func kf_normalized() -> Image {
+    public var normalized: Image {
         // prevent animated image (GIF) lose it's images
-        guard images == nil else { return self }
+        guard images == nil else { return base }
         // No need to do anything if already up
-        guard imageOrientation != .up else { return self }
+        guard base.imageOrientation != .up else { return base }
     
         return draw(cgImage: nil, to: size) {
-            draw(in: CGRect(origin: CGPoint.zero, size: size))
+            base.draw(in: CGRect(origin: CGPoint.zero, size: size))
         }
     }
     
-    static func kf_animated(with images: [Image], forDuration duration: TimeInterval) -> Image? {
+    static func animated(with images: [Image], forDuration duration: TimeInterval) -> Image? {
         return .animatedImage(with: images, duration: duration)
     }
-#endif
+    #endif
 }
 
 // MARK: - Image Representation
-extension Image {
+extension Kingfisher where Base: Image {
     // MARK: - PNG
     func pngRepresentation() -> Data? {
         #if os(macOS)
@@ -177,7 +181,7 @@ extension Image {
             let rep = NSBitmapImageRep(cgImage: cgimage)
             return rep.representation(using: .PNG, properties: [:])
         #else
-            return UIImagePNGRepresentation(self)
+            return UIImagePNGRepresentation(base)
         #endif
     }
     
@@ -190,7 +194,7 @@ extension Image {
             let rep = NSBitmapImageRep(cgImage: cgImage)
             return rep.representation(using:.JPEG, properties: [NSImageCompressionFactor: compressionQuality])
         #else
-            return UIImageJPEGRepresentation(self, compressionQuality)
+            return UIImageJPEGRepresentation(base, compressionQuality)
         #endif
     }
     
@@ -199,18 +203,18 @@ extension Image {
         #if os(macOS)
             return gifRepresentation(duration: 0.0, repeatCount: 0)
         #else
-            return kf_animatedImageData
+            return animatedImageData
         #endif
     }
     
     #if os(macOS)
     func gifRepresentation(duration: TimeInterval, repeatCount: Int) -> Data? {
-        guard let images = kf_images else {
+        guard let images = images else {
             return nil
         }
         
         let frameCount = images.count
-        let gifDuration = duration <= 0.0 ? kf_duration / Double(frameCount) : duration / Double(frameCount)
+        let gifDuration = duration <= 0.0 ? duration / Double(frameCount) : duration / Double(frameCount)
         
         let frameProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFDelayTime as String: gifDuration]]
         let imageProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: repeatCount]]
@@ -223,7 +227,7 @@ extension Image {
         CGImageDestinationSetProperties(destination, imageProperties as CFDictionary)
         
         for image in images {
-            CGImageDestinationAddImage(destination, image.cgImage!, frameProperties as CFDictionary)
+            CGImageDestinationAddImage(destination, image.kf.cgImage!, frameProperties as CFDictionary)
         }
         
         return CGImageDestinationFinalize(destination) ? data.copy() as? Data : nil
@@ -232,12 +236,11 @@ extension Image {
 }
 
 // MARK: - Create images from data
-extension Image {
-
-    static func kf_animated(with data: Data, scale: CGFloat = 1.0, duration: TimeInterval = 0.0, preloadAll: Bool) -> Image? {
+extension Kingfisher where Base: Image {
+    static func animated(with data: Data, scale: CGFloat = 1.0, duration: TimeInterval = 0.0, preloadAll: Bool) -> Image? {
         
         func decode(from imageSource: CGImageSource, for options: NSDictionary) -> ([Image], TimeInterval)? {
-
+            
             //Calculates frame duration for a gif frame out of the kCGImagePropertyGIFDictionary dictionary
             func frameDuration(from gifInfo: NSDictionary) -> Double {
                 let gifDefaultFrameDuration = 0.100
@@ -266,14 +269,14 @@ extension Image {
                 } else {
                     // Animated GIF
                     guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, i, nil),
-                          let gifInfo = (properties as NSDictionary)[kCGImagePropertyGIFDictionary as String] as? NSDictionary else
+                        let gifInfo = (properties as NSDictionary)[kCGImagePropertyGIFDictionary as String] as? NSDictionary else
                     {
                         return nil
                     }
                     gifDuration += frameDuration(from: gifInfo)
                 }
                 
-                images.append(Image.kf_image(cgImage: imageRef, scale: scale, refImage: nil))
+                images.append(Kingfisher<Image>.image(cgImage: imageRef, scale: scale, refImage: nil))
             }
             
             return (images, gifDuration)
@@ -285,47 +288,47 @@ extension Image {
             return nil
         }
         
-#if os(macOS)
-        guard let (images, gifDuration) = decode(from: imageSource, for: options) else {
-            return nil
-        }
-        let image = Image(data: data)
-        image?.kf_images = images
-        image?.kf_duration = gifDuration
-    
-        return image
-#else
-    
-        if preloadAll {
+        #if os(macOS)
             guard let (images, gifDuration) = decode(from: imageSource, for: options) else {
                 return nil
             }
-            let image = Image.kf_animated(with: images, forDuration: duration <= 0.0 ? gifDuration : duration)
-            image?.kf_animatedImageData = data
-            return image
-        } else {
-            let image = Image(data: data)
-            image?.kf_animatedImageData = data
-            image?.kf_imageSource = ImageSource(ref: imageSource)
+            var image = Image(data: data)
+            image?.kf.images = images
+            image?.kf.duration = gifDuration
+            
             return image
-        }
-#endif
+        #else
+            
+            if preloadAll {
+                guard let (images, gifDuration) = decode(from: imageSource, for: options) else {
+                    return nil
+                }
+                var image = Kingfisher<Image>.animated(with: images, forDuration: duration <= 0.0 ? gifDuration : duration)
+                image?.kf.animatedImageData = data
+                return image
+            } else {
+                var image = Image(data: data)
+                image?.kf.animatedImageData = data
+                image?.kf.imageSource = ImageSource(ref: imageSource)
+                return image
+            }
+        #endif
     }
     
-    static func kf_image(data: Data, scale: CGFloat, preloadAllGIFData: Bool) -> Image? {
+    static func image(data: Data, scale: CGFloat, preloadAllGIFData: Bool) -> Image? {
         var image: Image?
         #if os(macOS)
             switch data.kf_imageFormat {
             case .JPEG: image = Image(data: data)
             case .PNG: image = Image(data: data)
-            case .GIF: image = Image.kf_animated(with: data, scale: scale, duration: 0.0, preloadAll: preloadAllGIFData)
+            case .GIF: image = Kingfisher<Image>.animated(with: data, scale: scale, duration: 0.0, preloadAll: preloadAllGIFData)
             case .unknown: image = Image(data: data)
             }
         #else
             switch data.kf_imageFormat {
             case .JPEG: image = Image(data: data, scale: scale)
             case .PNG: image = Image(data: data, scale: scale)
-            case .GIF: image = Image.kf_animated(with: data, scale: scale, duration: 0.0, preloadAll: preloadAllGIFData)
+            case .GIF: image = Kingfisher<Image>.animated(with: data, scale: scale, duration: 0.0, preloadAll: preloadAllGIFData)
             case .unknown: image = Image(data: data, scale: scale)
             }
         #endif
@@ -335,9 +338,8 @@ extension Image {
 }
 
 // MARK: - Image Transforming
-extension Image {
+extension Kingfisher where Base: Image {
     // MARK: - Round Corner
-    
     /// Create a round corner image based on `self`.
     ///
     /// - parameter radius: The round corner radius of creating image.
@@ -347,44 +349,44 @@ extension Image {
     /// - returns: An image with round corner of `self`.
     ///
     /// - Note: This method only works for CG-based image.
-    public func kf_image(withRoundRadius radius: CGFloat, fit size: CGSize, scale: CGFloat) -> Image {
+    public func image(withRoundRadius radius: CGFloat, fit size: CGSize, scale: CGFloat) -> Image {
         
         guard let cgImage = cgImage else {
             assertionFailure("[Kingfisher] Round corder image only works for CG-based image.")
-            return self
+            return base
         }
         
         let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size)
         return draw(cgImage: cgImage, to: size) {
             #if os(macOS)
-            let path = NSBezierPath(roundedRect: rect, xRadius: radius, yRadius: radius)
-            path.windingRule = .evenOddWindingRule
-            path.addClip()
-            draw(in: rect)
+                let path = NSBezierPath(roundedRect: rect, xRadius: radius, yRadius: radius)
+                path.windingRule = .evenOddWindingRule
+                path.addClip()
+                base.draw(in: rect)
             #else
-            guard let context = UIGraphicsGetCurrentContext() else {
-                assertionFailure("[Kingfisher] Failed to create CG context for image.")
-                return
-            }
-            let path = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: radius, height: radius)).cgPath
-            context.addPath(path)
-            context.clip()
-            draw(in: rect)
+                guard let context = UIGraphicsGetCurrentContext() else {
+                    assertionFailure("[Kingfisher] Failed to create CG context for image.")
+                    return
+                }
+                let path = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: radius, height: radius)).cgPath
+                context.addPath(path)
+                context.clip()
+                base.draw(in: rect)
             #endif
         }
     }
     
     #if os(iOS) || os(tvOS)
-    func kf_resize(to size: CGSize, for contentMode: UIViewContentMode) -> Image {
+    func resize(to size: CGSize, for contentMode: UIViewContentMode) -> Image {
         switch contentMode {
         case .scaleAspectFit:
             let newSize = self.size.kf_constrained(size)
-            return kf_resize(to: newSize)
+            return resize(to: newSize)
         case .scaleAspectFill:
             let newSize = self.size.kf_filling(size)
-            return kf_resize(to: newSize)
+            return resize(to: newSize)
         default:
-            return kf_resize(to: size)
+            return resize(to: size)
         }
     }
     #endif
@@ -398,19 +400,19 @@ extension Image {
     /// - returns: An image with new size.
     ///
     /// - Note: This method only works for CG-based image.
-    public func kf_resize(to size: CGSize) -> Image {
+    public func resize(to size: CGSize) -> Image {
         
         guard let cgImage = cgImage?.fixed else {
             assertionFailure("[Kingfisher] Resize only works for CG-based image.")
-            return self
+            return base
         }
         
         let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size)
         return draw(cgImage: cgImage, to: size) {
             #if os(macOS)
-            draw(in: rect, from: NSRect.zero, operation: .copy, fraction: 1.0)
+                base.draw(in: rect, from: NSRect.zero, operation: .copy, fraction: 1.0)
             #else
-            draw(in: rect)
+                base.draw(in: rect)
             #endif
         }
     }
@@ -424,13 +426,13 @@ extension Image {
     /// - returns: An image with blur effect applied.
     ///
     /// - Note: This method only works for CG-based image.
-    public func kf_blurred(withRadius radius: CGFloat) -> Image {
+    public func blurred(withRadius radius: CGFloat) -> Image {
         #if os(watchOS)
             return self
         #else
             guard let cgImage = cgImage else {
                 assertionFailure("[Kingfisher] Blur only works for CG-based image.")
-                return self
+                return base
             }
             
             // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
@@ -453,16 +455,16 @@ extension Image {
                 iterations = 3
             }
             
-            let w = Int(kf_size.width)
-            let h = Int(kf_size.height)
+            let w = Int(size.width)
+            let h = Int(size.height)
             let rowBytes = Int(CGFloat(cgImage.bytesPerRow))
-
+            
             let inDataPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: rowBytes * Int(h))
             inDataPointer.initialize(to: 0)
             defer {
                 inDataPointer.deinitialize()
                 inDataPointer.deallocate(capacity: rowBytes * Int(h))
-            }
+        }
             
             let bitmapInfo = cgImage.bitmapInfo.fixed
             guard let context = CGContext(data: inDataPointer,
@@ -474,7 +476,7 @@ extension Image {
                                           bitmapInfo: bitmapInfo.rawValue) else
             {
                 assertionFailure("[Kingfisher] Failed to create CG context for blurring image.")
-                return self
+                return base
             }
             
             context.draw(cgImage, in: CGRect(x: 0, y: 0, width: w, height: h))
@@ -487,7 +489,7 @@ extension Image {
             defer {
                 outDataPointer.deinitialize()
                 outDataPointer.deallocate(capacity: rowBytes * Int(h))
-            }
+        }
             
             var outBuffer = vImage_Buffer(data: outDataPointer, height: vImagePixelCount(h), width: vImagePixelCount(w), rowBytes: rowBytes)
             
@@ -505,17 +507,17 @@ extension Image {
                                              bitmapInfo: bitmapInfo.rawValue) else
             {
                 assertionFailure("[Kingfisher] Failed to create CG context for blurring image.")
-                return self
+                return base
             }
             
             #if os(macOS)
-                let result = outContext.makeImage().flatMap { kf_fixedForRetinaPixel(cgImage: $0, to: kf_size) }
+                let result = outContext.makeImage().flatMap { fixedForRetinaPixel(cgImage: $0, to: size) }
             #else
                 let result = outContext.makeImage().flatMap { Image(cgImage: $0) }
             #endif
             guard let blurredImage = result else {
                 assertionFailure("[Kingfisher] Can not make an blurred image within this context.")
-                return self
+                return base
             }
             
             return blurredImage
@@ -532,29 +534,29 @@ extension Image {
     /// - returns: An image with a color overlay applied.
     ///
     /// - Note: This method only works for CG-based image.
-    public func kf_overlaying(with color: Color, fraction: CGFloat) -> Image {
-
+    public func overlaying(with color: Color, fraction: CGFloat) -> Image {
+        
         guard let cgImage = cgImage?.fixed else {
             assertionFailure("[Kingfisher] Overlaying only works for CG-based image.")
-            return self
+            return base
         }
         
-        let rect = CGRect(x: 0, y: 0, width: kf_size.width, height: kf_size.height)
+        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
         return draw(cgImage: cgImage, to: rect.size) {
             #if os(macOS)
-            draw(in: rect)
-            if fraction > 0 {
-                color.withAlphaComponent(1 - fraction).set()
-                NSRectFillUsingOperation(rect, .sourceAtop)
-            }
+                base.draw(in: rect)
+                if fraction > 0 {
+                    color.withAlphaComponent(1 - fraction).set()
+                    NSRectFillUsingOperation(rect, .sourceAtop)
+                }
             #else
-            color.set()
-            UIRectFill(rect)
-            draw(in: rect, blendMode: .destinationIn, alpha: 1.0)
-            
-            if fraction > 0 {
-                draw(in: rect, blendMode: .sourceAtop, alpha: fraction)
-            }
+                color.set()
+                UIRectFill(rect)
+                base.draw(in: rect, blendMode: .destinationIn, alpha: 1.0)
+                
+                if fraction > 0 {
+                    base.draw(in: rect, blendMode: .sourceAtop, alpha: fraction)
+                }
             #endif
         }
     }
@@ -566,11 +568,11 @@ extension Image {
     /// - parameter color: The color should be used to tint `self`
     ///
     /// - returns: An image with a color tint applied.
-    public func kf_tinted(with color: Color) -> Image {
+    public func tinted(with color: Color) -> Image {
         #if os(watchOS)
-        return self
+            return self
         #else
-        return kf_apply(.tint(color))
+            return apply(.tint(color))
         #endif
     }
     
@@ -584,45 +586,45 @@ extension Image {
     /// - parameter inputEV:    InputEV changing to image.
     ///
     /// - returns: An image with color control applied.
-    public func kf_adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image {
+    public func adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image {
         #if os(watchOS)
-        return self
+            return base
         #else
-        return kf_apply(.colorControl(brightness, contrast, saturation, inputEV))
+            return apply(.colorControl(brightness, contrast, saturation, inputEV))
         #endif
     }
 }
 
 // MARK: - Decode
-extension Image {
-    func kf_decoded() -> Image? {
-        return self.kf_decoded(scale: kf_scale)
+extension Kingfisher where Base: Image {
+    var decoded: Image? {
+        return decoded(scale: scale)
     }
     
-    func kf_decoded(scale: CGFloat) -> Image {
+    func decoded(scale: CGFloat) -> Image {
         // prevent animated image (GIF) lose it's images
-#if os(iOS)
-        if kf_imageSource != nil { return self }
-#else
-        if kf_images != nil { return self }
-#endif
+        #if os(iOS)
+            if imageSource != nil { return base }
+        #else
+            if images != nil { return base }
+        #endif
         
         guard let imageRef = self.cgImage else {
             assertionFailure("[Kingfisher] Decoding only works for CG-based image.")
-            return self
+            return base
         }
         let colorSpace = CGColorSpaceCreateDeviceRGB()
         let bitmapInfo = imageRef.bitmapInfo.fixed
         
         guard let context = CGContext(data: nil, width: imageRef.width, height: imageRef.height, bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) else {
             assertionFailure("[Kingfisher] Decoding fails to create a valid context.")
-            return self
+            return base
         }
         
         let rect = CGRect(x: 0, y: 0, width: imageRef.width, height: imageRef.height)
         context.draw(imageRef, in: rect)
         let decompressedImageRef = context.makeImage()
-        return Image.kf_image(cgImage: decompressedImageRef!, scale: scale, refImage: self)
+        return Kingfisher<Image>.image(cgImage: decompressedImageRef!, scale: scale, refImage: base)
     }
 }
 
@@ -728,7 +730,7 @@ extension CGBitmapInfo {
 }
 
 
-extension Image {
+extension Kingfisher where Base: Image {
     
     func draw(cgImage: CGImage?, to size: CGSize, draw: ()->()) -> Image {
         #if os(macOS)
@@ -745,7 +747,7 @@ extension Image {
             bitsPerPixel: 0) else
         {
             assertionFailure("[Kingfisher] Image representation cannot be created.")
-            return self
+            return base
         }
         rep.size = size
         
@@ -764,18 +766,18 @@ extension Image {
         UIGraphicsBeginImageContextWithOptions(size, false, scale)
         defer { UIGraphicsEndImageContext() }
         draw()
-        return UIGraphicsGetImageFromCurrentImageContext() ?? self
+        return UIGraphicsGetImageFromCurrentImageContext() ?? base
         
         #endif
     }
     
     #if os(macOS)
-    func kf_fixedForRetinaPixel(cgImage: CGImage, to size: CGSize) -> Image {
+    func fixedForRetinaPixel(cgImage: CGImage, to size: CGSize) -> Image {
         
-        let image = Image(cgImage: cgImage, size: self.size)
+        let image = Image(cgImage: cgImage, size: base.size)
         let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size)
         
-        return draw(cgImage: cgImage, to: kf_size) {
+        return draw(cgImage: cgImage, to: self.size) {
             image.draw(in: rect, from: NSRect.zero, operation: .copy, fraction: 1.0)
         }
     }
@@ -818,4 +820,112 @@ extension Double {
     }
 }
 
-
+// MARK: - Deprecated. Only for back compatibility.
+extension Image {
+    /**
+     Normalize the image. This method does nothing in OS X.
+     
+     - returns: The image itself.
+     */
+    @available(*, deprecated,
+    message: "Extensions directly on Image are deprecated. Use `kf.normalized` instead.",
+    renamed: "kf.normalized")
+    public func kf_normalized() -> Image {
+        return kf.normalized
+    }
+    
+    // MARK: - Round Corner
+    
+    /// Create a round corner image based on `self`.
+    ///
+    /// - parameter radius: The round corner radius of creating image.
+    /// - parameter size:   The target size of creating image.
+    /// - parameter scale:  The image scale of creating image.
+    ///
+    /// - returns: An image with round corner of `self`.
+    ///
+    /// - Note: This method only works for CG-based image.
+    @available(*, deprecated,
+    message: "Extensions directly on Image are deprecated. Use `kf.image(withRoundRadius:fit:scale:)` instead.",
+    renamed: "kf.image")
+    public func kf_image(withRoundRadius radius: CGFloat, fit size: CGSize, scale: CGFloat) -> Image {
+        return kf.image(withRoundRadius: radius, fit: size, scale: scale)
+    }
+    
+    // MARK: - Resize
+    /// Resize `self` to an image of new size.
+    ///
+    /// - parameter size: The target size.
+    ///
+    /// - returns: An image with new size.
+    ///
+    /// - Note: This method only works for CG-based image.
+    @available(*, deprecated,
+    message: "Extensions directly on Image are deprecated. Use `kf.resize(to:)` instead.",
+    renamed: "kf.resize")
+    public func kf_resize(to size: CGSize) -> Image {
+        return kf.resize(to: size)
+    }
+    
+    // MARK: - Blur
+    /// Create an image with blur effect based on `self`.
+    ///
+    /// - parameter radius: The blur radius should be used when creating blue.
+    ///
+    /// - returns: An image with blur effect applied.
+    ///
+    /// - Note: This method only works for CG-based image.
+    @available(*, deprecated,
+    message: "Extensions directly on Image are deprecated. Use `kf.blurred(withRadius:)` instead.",
+    renamed: "kf.blurred")
+    public func kf_blurred(withRadius radius: CGFloat) -> Image {
+        return kf.blurred(withRadius: radius)
+    }
+    
+    // MARK: - Overlay
+    /// Create an image from `self` with a color overlay layer.
+    ///
+    /// - parameter color:    The color should be use to overlay.
+    /// - parameter fraction: Fraction of input color. From 0.0 to 1.0. 0.0 means solid color, 1.0 means transparent overlay.
+    ///
+    /// - returns: An image with a color overlay applied.
+    ///
+    /// - Note: This method only works for CG-based image.
+    @available(*, deprecated,
+    message: "Extensions directly on Image are deprecated. Use `kf.overlaying(with:fraction:)` instead.",
+    renamed: "kf.overlaying")
+    public func kf_overlaying(with color: Color, fraction: CGFloat) -> Image {
+        return kf.overlaying(with: color, fraction: fraction)
+    }
+    
+    // MARK: - Tint
+    
+    /// Create an image from `self` with a color tint.
+    ///
+    /// - parameter color: The color should be used to tint `self`
+    ///
+    /// - returns: An image with a color tint applied.
+    @available(*, deprecated,
+    message: "Extensions directly on Image are deprecated. Use `kf.tinted(with:)` instead.",
+    renamed: "kf.tinted")
+    public func kf_tinted(with color: Color) -> Image {
+        return kf.tinted(with: color)
+    }
+    
+    // MARK: - Color Control
+    
+    /// Create an image from `self` with color control.
+    ///
+    /// - parameter brightness: Brightness changing to image.
+    /// - parameter contrast:   Contrast changing to image.
+    /// - parameter saturation: Saturation changing to image.
+    /// - parameter inputEV:    InputEV changing to image.
+    ///
+    /// - returns: An image with color control applied.
+    @available(*, deprecated,
+    message: "Extensions directly on Image are deprecated. Use `kf.adjusted` instead.",
+    renamed: "kf.adjusted")
+    public func kf_adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image {
+        return kf.adjusted(brightness: brightness, contrast: contrast, saturation: saturation, inputEV: inputEV)
+    }
+}

+ 7 - 7
Sources/ImageCache.swift

@@ -174,7 +174,7 @@ extension ImageCache {
     {
         
         let computedKey = key.computedKey(with: identifier)
-        memoryCache.setObject(image, forKey: computedKey as NSString, cost: image.kf_imageCost)
+        memoryCache.setObject(image, forKey: computedKey as NSString, cost: image.kf.imageCost)
 
         func callHandlerInMainQueue() {
             if let handler = completionHandler {
@@ -280,7 +280,7 @@ extension ImageCache {
                 if let image = sSelf.retrieveImageInDiskCache(forKey: key, options: options) {
                     if options.backgroundDecode {
                         sSelf.processQueue.async {
-                            let result = image.kf_decoded(scale: options.scaleFactor)
+                            let result = image.kf.decoded(scale: options.scaleFactor)
                             
                             sSelf.store(result,
                                         forKey: key,
@@ -640,11 +640,11 @@ extension ImageCache {
     }
 }
 
-extension Image {
-    var kf_imageCost: Int {
-        return kf_images == nil ?
-            Int(size.height * size.width * kf_scale * kf_scale) :
-            Int(size.height * size.width * kf_scale * kf_scale) * kf_images!.count
+extension Kingfisher where Base: Image {
+    var imageCost: Int {
+        return images == nil ?
+            Int(size.height * size.width * scale * scale) :
+            Int(size.height * size.width * scale * scale) * images!.count
     }
 }
 

+ 1 - 1
Sources/ImageDownloader.swift

@@ -487,7 +487,7 @@ class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, Authentic
                 downloader.delegate?.imageDownloader(downloader, didDownload: image, for: url, with: task.response)
                 
                 if options.backgroundDecode {
-                    self.callback(with: image.kf_decoded(scale: options.scaleFactor), error: nil, url: url, originalData: data)
+                    self.callback(with: image.kf.decoded(scale: options.scaleFactor), error: nil, url: url, originalData: data)
                 } else {
                     self.callback(with: image, error: nil, url: url, originalData: data)
                 }

+ 8 - 8
Sources/ImageProcessor.swift

@@ -116,7 +116,7 @@ public struct DefaultImageProcessor: ImageProcessor {
         case .image(let image):
             return image
         case .data(let data):
-            return Image.kf_image(data: data, scale: options.scaleFactor, preloadAllGIFData: options.preloadAllGIFData)
+            return Kingfisher<Image>.image(data: data, scale: options.scaleFactor, preloadAllGIFData: options.preloadAllGIFData)
         }
     }
 }
@@ -153,8 +153,8 @@ public struct RoundCornerImageProcessor: ImageProcessor {
     public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
         switch item {
         case .image(let image):
-            let size = targetSize ?? image.kf_size
-            return image.kf_image(withRoundRadius: cornerRadius, fit: size, scale: options.scaleFactor)
+            let size = targetSize ?? image.kf.size
+            return image.kf.image(withRoundRadius: cornerRadius, fit: size, scale: options.scaleFactor)
         case .data(_):
             return (DefaultImageProcessor() >> self).process(item: item, options: options)
         }
@@ -181,7 +181,7 @@ public struct ResizingImageProcessor: ImageProcessor {
     public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
         switch item {
         case .image(let image):
-            return image.kf_resize(to: targetSize)
+            return image.kf.resize(to: targetSize)
         case .data(_):
             return (DefaultImageProcessor() >> self).process(item: item, options: options)
         }
@@ -210,7 +210,7 @@ public struct BlurImageProcessor: ImageProcessor {
         switch item {
         case .image(let image):
             let radius = blurRadius * options.scaleFactor
-            return image.kf_blurred(withRadius: radius)
+            return image.kf.blurred(withRadius: radius)
         case .data(_):
             return (DefaultImageProcessor() >> self).process(item: item, options: options)
         }
@@ -244,7 +244,7 @@ public struct OverlayImageProcessor: ImageProcessor {
     public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
         switch item {
         case .image(let image):
-            return image.kf_overlaying(with: overlay, fraction: fraction)
+            return image.kf.overlaying(with: overlay, fraction: fraction)
         case .data(_):
             return (DefaultImageProcessor() >> self).process(item: item, options: options)
         }
@@ -272,7 +272,7 @@ public struct TintImageProcessor: ImageProcessor {
     public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
         switch item {
         case .image(let image):
-            return image.kf_tinted(with: tint)
+            return image.kf.tinted(with: tint)
         case .data(_):
             return (DefaultImageProcessor() >> self).process(item: item, options: options)
         }
@@ -316,7 +316,7 @@ public struct ColorControlsProcessor: ImageProcessor {
     public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
         switch item {
         case .image(let image):
-            return image.kf_adjusted(brightness: brightness, contrast: contrast, saturation: saturation, inputEV: inputEV)
+            return image.kf.adjusted(brightness: brightness, contrast: contrast, saturation: saturation, inputEV: inputEV)
         case .data(_):
             return (DefaultImageProcessor() >> self).process(item: item, options: options)
         }

+ 16 - 16
Tests/KingfisherTests/ImageExtensionTests.swift

@@ -58,51 +58,51 @@ class ImageExtensionTests: XCTestCase {
     }
     
     func testGenerateGIFImage() {
-        let image = Image.kf_animated(with: testImageGIFData, preloadAll: false)
+        let image = Kingfisher<Image>.animated(with: testImageGIFData, preloadAll: false)
         XCTAssertNotNil(image, "The image should be initiated.")
 #if os(iOS) || os(tvOS)
-        let count = CGImageSourceGetCount(image!.kf_imageSource!.imageRef!)
+        let count = CGImageSourceGetCount(image!.kf.imageSource!.imageRef!)
         XCTAssertEqual(count, 8, "There should be 8 frames.")
 #else
-        XCTAssertEqual(image!.kf_images!.count, 8, "There should be 8 frames.")
+        XCTAssertEqual(image!.kf.images!.count, 8, "There should be 8 frames.")
         
-        XCTAssertEqualWithAccuracy(image!.kf_duration, 0.8, accuracy: 0.001, "The image duration should be 0.8s")
+        XCTAssertEqualWithAccuracy(image!.kf.duration, 0.8, accuracy: 0.001, "The image duration should be 0.8s")
 #endif
     }
     
     func testGIFRepresentation() {
-        let image = Image.kf_animated(with: testImageGIFData, preloadAll: false)!
-        let data = image.gifRepresentation()
+        let image = Kingfisher<Image>.animated(with: testImageGIFData, preloadAll: false)!
+        let data = image.kf.gifRepresentation()
         
         XCTAssertNotNil(data, "Data should not be nil")
         XCTAssertEqual(data?.kf_imageFormat, ImageFormat.GIF)
         
-        let allLoadImage = Image.kf_animated(with: data!, preloadAll: true)!
-        let allLoadData = allLoadImage.gifRepresentation()
+        let allLoadImage = Kingfisher<Image>.animated(with: data!, preloadAll: true)!
+        let allLoadData = allLoadImage.kf.gifRepresentation()
         XCTAssertNotNil(allLoadData, "Data1 should not be nil")
         XCTAssertEqual(allLoadData?.kf_imageFormat, ImageFormat.GIF)
     }
     
     func testGenerateSingleFrameGIFImage() {
-        let image = Image.kf_animated(with: testImageSingleFrameGIFData, preloadAll: false)
+        let image = Kingfisher<Image>.animated(with: testImageSingleFrameGIFData, preloadAll: false)
         XCTAssertNotNil(image, "The image should be initiated.")
 #if os(iOS) || os(tvOS)
-        let count = CGImageSourceGetCount(image!.kf_imageSource!.imageRef!)
+        let count = CGImageSourceGetCount(image!.kf.imageSource!.imageRef!)
         XCTAssertEqual(count, 1, "There should be 1 frames.")
 #else
-        XCTAssertEqual(image!.kf_images!.count, 1, "There should be 1 frames.")
+        XCTAssertEqual(image!.kf.images!.count, 1, "There should be 1 frames.")
         
-        XCTAssertEqual(image!.kf_duration, Double.infinity, "The image duration should be 0 since it is not animated image.")
+        XCTAssertEqual(image!.kf.duration, Double.infinity, "The image duration should be 0 since it is not animated image.")
 #endif
     }
     
     func testPreloadAllGIFData() {
-        let image = Image.kf_animated(with: testImageSingleFrameGIFData, preloadAll: true)!
+        let image = Kingfisher<Image>.animated(with: testImageSingleFrameGIFData, preloadAll: true)!
         XCTAssertNotNil(image, "The image should be initiated.")
 #if os(iOS) || os(tvOS)
-        XCTAssertNil(image.kf_imageSource, "Image source should be nil")
+        XCTAssertNil(image.kf.imageSource, "Image source should be nil")
 #endif
-        XCTAssertEqual(image.kf_duration, image.kf_duration)
-        XCTAssertEqual(image.kf_images!.count, image.kf_images!.count)
+        XCTAssertEqual(image.kf.duration, image.kf.duration)
+        XCTAssertEqual(image.kf.images!.count, image.kf.images!.count)
     }
 }

+ 7 - 7
Tests/KingfisherTests/KingfisherTestHelper.swift

@@ -34,8 +34,8 @@ var testImage: Image = Image(data: testImageData! as Data)!
 
 let testImageData = NSData(base64Encoded: testImageString, options: [])
 
-let testImagePNGData = testImage.pngRepresentation()!
-let testImageJEPGData = testImage.jpegRepresentation(compressionQuality: 1.0)!
+let testImagePNGData = testImage.kf.pngRepresentation()!
+let testImageJEPGData = testImage.kf.jpegRepresentation(compressionQuality: 1.0)!
 let testImageGIFData = try! Data(contentsOf: URL(fileURLWithPath: Bundle(for: ImageExtensionTests.self).path(forResource: "dancing-banana", ofType: "gif")!))
 let testImageSingleFrameGIFData = try! Data(contentsOf: URL(fileURLWithPath: Bundle(for: ImageExtensionTests.self).path(forResource: "single-frame", ofType: "gif")!))
 
@@ -64,11 +64,11 @@ extension Image {
     func renderEqual(to image: Image, withinTolerance tolerance: UInt8 = 3) -> Bool {
         
         guard size == image.size else { return false }
-        guard let imageData1 = pngRepresentation(), let imageData2 = image.pngRepresentation() else { return false }
+        guard let imageData1 = kf.pngRepresentation(), let imageData2 = image.kf.pngRepresentation() else { return false }
         guard let unifiedImage1 = Image(data: imageData1), let unifiedImage2 = Image(data: imageData2) else { return false }
         
         guard let rendered1 = unifiedImage1.rendered(), let rendered2 = unifiedImage2.rendered() else { return false }
-        guard let data1 = rendered1.cgImage?.dataProvider?.data, let data2 = rendered2.cgImage?.dataProvider?.data else { return false }
+        guard let data1 = rendered1.kf.cgImage?.dataProvider?.data, let data2 = rendered2.kf.cgImage?.dataProvider?.data else { return false }
         
         let length1 = CFDataGetLength(data1)
         let length2 = CFDataGetLength(data2)
@@ -92,7 +92,7 @@ extension Image {
     
     func rendered() -> Image? {
         // Ignore non CG images
-        guard let cgImage = cgImage else {
+        guard let cgImage = kf.cgImage else {
             return nil
         }
         
@@ -128,7 +128,7 @@ extension Image {
         context.draw(cgImage, in: CGRect(origin: CGPoint.zero, size: size))
         
         #if os(macOS)
-        return context.makeImage().flatMap { Image(cgImage: $0, size: kf_size) }
+        return context.makeImage().flatMap { Image(cgImage: $0, size: kf.size) }
         #else
         return context.makeImage().flatMap { Image(cgImage: $0) }
         #endif
@@ -146,7 +146,7 @@ extension Image {
         let path = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).last!
         let p = ((path) as NSString).appendingPathComponent(name)
         print(p)
-        try! pngRepresentation()?.write(to: URL(fileURLWithPath: p))
+        try! kf.pngRepresentation()?.write(to: URL(fileURLWithPath: p))
         return p
     }
 }