diff --git a/AF+Image+Helper.podspec b/AF+Image+Helper.podspec index e0b7a60..847c32f 100644 --- a/AF+Image+Helper.podspec +++ b/AF+Image+Helper.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'AF+Image+Helper' - s.version = '1.02' + s.version = '1.03' s.platform = :ios s.license = 'MIT' s.summary = 'Convenience extension for UIImage and UIImageView in Swift' diff --git a/AF+Image+Helper/AF+Image+Extension.swift b/AF+Image+Helper/AF+Image+Extension.swift index fc5855a..7495396 100644 --- a/AF+Image+Helper/AF+Image+Extension.swift +++ b/AF+Image+Helper/AF+Image+Extension.swift @@ -1,7 +1,7 @@ // // AF+Image+Extension.swift // -// Version 1.02 +// Version 1.03 // // Created by Melvin Rivera on 7/5/14. // Copyright (c) 2014 All Forces. All rights reserved. @@ -33,7 +33,7 @@ extension UIImage { } // MARK: Image from solid color - convenience init(color:UIColor, size:CGSize = CGSizeMake(10, 10) ) + convenience init?(color:UIColor, size:CGSize = CGSizeMake(10, 10)) { let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height) UIGraphicsBeginImageContextWithOptions(rect.size, false, 0) @@ -45,7 +45,7 @@ extension UIImage { } // MARK: Image from gradient colors - convenience init(gradientColors:[UIColor], size:CGSize = CGSizeMake(10, 10) ) + convenience init?(gradientColors:[UIColor], size:CGSize = CGSizeMake(10, 10) ) { UIGraphicsBeginImageContextWithOptions(size, false, 0) var context = UIGraphicsGetCurrentContext() @@ -80,7 +80,7 @@ extension UIImage { } // MARK: Image with Text - convenience init(text: String, font: UIFont = UIFont.systemFontOfSize(18), color: UIColor = UIColor.whiteColor(), backgroundColor: UIColor = UIColor.grayColor(), size:CGSize = CGSizeMake(100, 100), offset: CGPoint = CGPoint(x: 0, y: 0)) + convenience init?(text: String, font: UIFont = UIFont.systemFontOfSize(18), color: UIColor = UIColor.whiteColor(), backgroundColor: UIColor = UIColor.grayColor(), size:CGSize = CGSizeMake(100, 100), offset: CGPoint = CGPoint(x: 0, y: 0)) { UIGraphicsBeginImageContextWithOptions(size, false, 0) let context = UIGraphicsGetCurrentContext() @@ -96,7 +96,7 @@ extension UIImage { } // MARK: Image from uiview - convenience init(fromView view: UIView) { + convenience init?(fromView view: UIView) { UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0) //view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true) view.layer.renderInContext(UIGraphicsGetCurrentContext()) @@ -107,7 +107,7 @@ extension UIImage { // MARK: Image with Radial Gradient // Render a radial background // Originally from: http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_shadings/dq_shadings.html - convenience init(startColor: UIColor, endColor: UIColor, radialGradientCenter: CGPoint = CGPoint(x: 0.5, y: 0.5), radius:Float = 0.5, size:CGSize = CGSizeMake(100, 100)) + convenience init?(startColor: UIColor, endColor: UIColor, radialGradientCenter: CGPoint = CGPoint(x: 0.5, y: 0.5), radius:Float = 0.5, size:CGSize = CGSizeMake(100, 100)) { // Init @@ -152,7 +152,7 @@ extension UIImage { // Returns a copy of the given image, adding an alpha channel if it doesn't already have one - func applyAlpha() -> UIImage + func applyAlpha() -> UIImage? { if hasAlpha() { return self @@ -164,8 +164,8 @@ extension UIImage { let colorSpace = CGImageGetColorSpace(imageRef) // The bitsPerComponent and bitmapInfo values are hard-coded to prevent an "unsupported parameter combination" error - let bitmapInfo = CGBitmapInfo.fromRaw(CGBitmapInfo.ByteOrderDefault.toRaw() | CGImageAlphaInfo.PremultipliedFirst.toRaw()) - let offscreenContext = CGBitmapContextCreate(nil, width, height, 8, 0, colorSpace, bitmapInfo!) + let bitmapInfo = CGBitmapInfo(CGBitmapInfo.ByteOrderDefault.rawValue | CGImageAlphaInfo.PremultipliedFirst.rawValue) + let offscreenContext = CGBitmapContextCreate(nil, width, height, 8, 0, colorSpace, bitmapInfo) // Draw the image into the context and retrieve the new image, which will now have an alpha layer CGContextDrawImage(offscreenContext, CGRectMake(0, 0, CGFloat(width), CGFloat(height)), imageRef) @@ -174,10 +174,13 @@ extension UIImage { } // Returns a copy of the image with a transparent border of the given size added around its edges. - func applyPadding(padding: CGFloat) -> UIImage + func applyPadding(padding: CGFloat) -> UIImage? { // If the image does not have an alpha layer, add one var image = self.applyAlpha() + if image == nil { + return nil + } let rect = CGRect(x: 0, y: 0, width: size.width + padding * 2, height: size.height + padding * 2) // Build a context that's the same dimensions as the new size @@ -187,12 +190,10 @@ extension UIImage { let context = CGBitmapContextCreate(nil, UInt(rect.size.width), UInt(rect.size.height), bitsPerComponent, 0, colorSpace, bitmapInfo) // Draw the image in the center of the context, leaving a gap around the edges - - let imageLocation = CGRect(x: padding, y: padding, width: image.size.width, height: image.size.height) + let imageLocation = CGRect(x: padding, y: padding, width: image!.size.width, height: image!.size.height) CGContextDrawImage(context, imageLocation, self.CGImage) // Create a mask to make the border transparent, and combine it with the image - var transparentImage = UIImage(CGImage: CGImageCreateWithMask(CGBitmapContextCreateImage(context), imageRefWithPadding(padding, size: rect.size))) return transparentImage } @@ -204,8 +205,8 @@ extension UIImage { { // Build a context that's the same dimensions as the new size let colorSpace = CGColorSpaceCreateDeviceGray() - let bitmapInfo = CGBitmapInfo.fromRaw(CGBitmapInfo.ByteOrderDefault.toRaw() | CGImageAlphaInfo.None.toRaw()) - let context = CGBitmapContextCreate(nil, UInt(size.width), UInt(size.height), 8, 0, colorSpace, bitmapInfo!) + let bitmapInfo = CGBitmapInfo(CGBitmapInfo.ByteOrderDefault.rawValue | CGImageAlphaInfo.None.rawValue) + let context = CGBitmapContextCreate(nil, UInt(size.width), UInt(size.height), 8, 0, colorSpace, bitmapInfo) // Start with a mask that's entirely transparent CGContextSetFillColorWithColor(context, UIColor.blackColor().CGColor) CGContextFillRect(context, CGRect(x: 0, y: 0, width: size.width, height: size.height)) @@ -220,12 +221,12 @@ extension UIImage { // MARK: Crop - func crop(bounds: CGRect) -> UIImage + func crop(bounds: CGRect) -> UIImage? { return UIImage(CGImage: CGImageCreateWithImageInRect(self.CGImage, bounds)) } - func cropToSquare() -> UIImage { + func cropToSquare() -> UIImage? { let shortest = min(size.width, size.height) let left: CGFloat = size.width > shortest ? (size.width-shortest)/2 : 0 let top: CGFloat = size.height > shortest ? (size.height-shortest)/2 : 0 @@ -236,7 +237,7 @@ extension UIImage { // MARK: Resize - func resize(size:CGSize, contentMode: UIImageContentMode = .ScaleToFill) -> UIImage + func resize(size:CGSize, contentMode: UIImageContentMode = .ScaleToFill) -> UIImage? { let horizontalRatio = size.width / self.size.width; let verticalRatio = size.height / self.size.height; @@ -257,8 +258,8 @@ extension UIImage { // images. See here: http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/comment-page-2/#comment-39951 let colorSpace = CGColorSpaceCreateDeviceRGB() - let bitmapInfo = CGBitmapInfo.fromRaw(CGImageAlphaInfo.PremultipliedLast.toRaw()) - let context = CGBitmapContextCreate(nil, UInt(rect.size.width), UInt(rect.size.height), 8, 0, colorSpace, bitmapInfo!) + let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedLast.rawValue) + let context = CGBitmapContextCreate(nil, UInt(rect.size.width), UInt(rect.size.height), 8, 0, colorSpace, bitmapInfo) let transform = CGAffineTransformIdentity @@ -282,17 +283,20 @@ extension UIImage { // MARK: Corner Radius - func roundCorners(cornerRadius:CGFloat) -> UIImage + func roundCorners(cornerRadius:CGFloat) -> UIImage? { // If the image does not have an alpha layer, add one var imageWithAlpha = applyAlpha() + if imageWithAlpha == nil { + return nil + } UIGraphicsBeginImageContextWithOptions(size, false, 0) - let width = CGImageGetWidth(imageWithAlpha.CGImage) - let height = CGImageGetHeight(imageWithAlpha.CGImage) - let bits = CGImageGetBitsPerComponent(imageWithAlpha.CGImage) - let colorSpace = CGImageGetColorSpace(imageWithAlpha.CGImage) - let bitmapInfo = CGImageGetBitmapInfo(imageWithAlpha.CGImage) + let width = CGImageGetWidth(imageWithAlpha?.CGImage) + let height = CGImageGetHeight(imageWithAlpha?.CGImage) + let bits = CGImageGetBitsPerComponent(imageWithAlpha?.CGImage) + let colorSpace = CGImageGetColorSpace(imageWithAlpha?.CGImage) + let bitmapInfo = CGImageGetBitmapInfo(imageWithAlpha?.CGImage) let context = CGBitmapContextCreate(nil, width, height, bits, 0, colorSpace, bitmapInfo) let rect = CGRect(x: 0, y: 0, width: size.width*scale, height: size.height*scale) @@ -315,32 +319,32 @@ extension UIImage { CGContextClosePath(context) CGContextClip(context) - CGContextDrawImage(context, rect, imageWithAlpha.CGImage) + CGContextDrawImage(context, rect, imageWithAlpha?.CGImage) var image = UIImage(CGImage: CGBitmapContextCreateImage(context), scale:scale, orientation: .Up) UIGraphicsEndImageContext() return image } - func roundCorners(cornerRadius:CGFloat, border:CGFloat, color:UIColor) -> UIImage + func roundCorners(cornerRadius:CGFloat, border:CGFloat, color:UIColor) -> UIImage? { - return roundCorners(cornerRadius).applyBorder(border, color: color) + return roundCorners(cornerRadius)?.applyBorder(border, color: color) } - func roundCornersToCircle() -> UIImage + func roundCornersToCircle() -> UIImage? { let shortest = min(size.width, size.height) - return cropToSquare().roundCorners(shortest/2) + return cropToSquare()?.roundCorners(shortest/2) } - func roundCornersToCircle(#border:CGFloat, color:UIColor) -> UIImage + func roundCornersToCircle(#border:CGFloat, color:UIColor) -> UIImage? { let shortest = min(size.width, size.height) - return cropToSquare().roundCorners(shortest/2, border: border, color: color) + return cropToSquare()?.roundCorners(shortest/2, border: border, color: color) } // MARK: Border - func applyBorder(border:CGFloat, color:UIColor) -> UIImage { + func applyBorder(border:CGFloat, color:UIColor) -> UIImage? { UIGraphicsBeginImageContextWithOptions(size, false, 0) let width = CGImageGetWidth(self.CGImage) let height = CGImageGetHeight(self.CGImage) @@ -374,25 +378,26 @@ extension UIImage { } // Fetch Image let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) - session.dataTaskWithURL(NSURL(string: url), completionHandler: { - (response: NSData!, data: NSURLResponse!, error: NSError!) in - if (error != nil) { - dispatch_async(dispatch_get_main_queue()) { - closure(image: nil) + if let nsURL = NSURL(string: url) { + session.dataTaskWithURL(nsURL, completionHandler: { + (response: NSData!, data: NSURLResponse!, error: NSError!) in + if (error != nil) { + dispatch_async(dispatch_get_main_queue()) { + closure(image: nil) + } } - } - let image = UIImage(data: response) - if shouldCacheImage { - UIImage.sharedCache().setObject(image, forKey: url) - } - dispatch_async(dispatch_get_main_queue()) { - closure(image: image) - } - }).resume() + if let image = UIImage(data: response) { + if shouldCacheImage { + UIImage.sharedCache().setObject(image, forKey: url) + } + dispatch_async(dispatch_get_main_queue()) { + closure(image: image) + } + } + + }).resume() + } return placeholder } - - - } \ No newline at end of file diff --git a/AF+Image+Helper/AF+ImageVIew+Extension.swift b/AF+Image+Helper/AF+ImageVIew+Extension.swift index 954433c..aa69857 100644 --- a/AF+Image+Helper/AF+ImageVIew+Extension.swift +++ b/AF+Image+Helper/AF+ImageVIew+Extension.swift @@ -1,7 +1,7 @@ // // AF+ImageView+Extension.swift // -// Version 1.01 +// Version 1.03 // // Created by Melvin Rivera on 7/23/14. // Copyright (c) 2014 All Forces. All rights reserved. diff --git a/Demo AF+Image+Helper/Demo AF+Image+Helper.xcodeproj/project.xcworkspace/xcuserdata/melvinrivera.xcuserdatad/UserInterfaceState.xcuserstate b/Demo AF+Image+Helper/Demo AF+Image+Helper.xcodeproj/project.xcworkspace/xcuserdata/melvinrivera.xcuserdatad/UserInterfaceState.xcuserstate index 590fde1..4a383b2 100644 Binary files a/Demo AF+Image+Helper/Demo AF+Image+Helper.xcodeproj/project.xcworkspace/xcuserdata/melvinrivera.xcuserdatad/UserInterfaceState.xcuserstate and b/Demo AF+Image+Helper/Demo AF+Image+Helper.xcodeproj/project.xcworkspace/xcuserdata/melvinrivera.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Demo AF+Image+Helper/Demo AF+Image+Helper/ViewController.swift b/Demo AF+Image+Helper/Demo AF+Image+Helper/ViewController.swift index 9e18f01..3d98f87 100644 --- a/Demo AF+Image+Helper/Demo AF+Image+Helper/ViewController.swift +++ b/Demo AF+Image+Helper/Demo AF+Image+Helper/ViewController.swift @@ -21,8 +21,8 @@ class Cell: UICollectionViewCell { class ViewController: UICollectionViewController { - let imageWidth = 140 - let imageHeight = 140 + let imageWidth = 140.0 + let imageHeight = 140.0 var sections = [String]() var items = [[CellItem]]() @@ -31,47 +31,75 @@ class ViewController: UICollectionViewController { super.viewDidLoad() + // Colors & Gradients sections.append("Colors & Gradients") - items.append([ - CellItem(text: "Solid Color", image: UIImage(color: UIColor(red: 0, green: 0.502, blue: 1, alpha: 1), size: CGSize(width: imageWidth, height: imageHeight))), - CellItem(text: "Gradient Color", image: UIImage(gradientColors: [UIColor(red: 0.808, green: 0.863, blue: 0.902, alpha: 1), UIColor(red: 0.349, green: 0.412, blue: 0.443, alpha: 1)], size: CGSize(width: imageWidth, height: imageHeight))), - CellItem(text: "Gradient Overlay", image: UIImage(named: "beach").applyGradientColors([UIColor(red: 0.996, green: 0.769, blue: 0.494, alpha: 1), UIColor(red: 0.969, green: 0.608, blue: 0.212, alpha: 0.2)])), - CellItem(text: "Radial Gradient", image: UIImage(startColor: UIColor(red: 0.996, green: 1, blue: 1, alpha: 1), endColor: UIColor(red: 0.627, green: 0.835, blue: 0.922, alpha: 1), radialGradientCenter: CGPoint(x: 0.5, y: 0.5), radius: 0.5, size: CGSize(width: imageWidth, height: imageHeight))) - ]) + var colors = [CellItem]() + if let image = UIImage(color: UIColor(red: 0.0, green: 0.502, blue: 1.0, alpha: 1.0), size: CGSize(width: imageWidth, height: imageHeight)) { + colors.append(CellItem(text: "Solid Color", image: image)) + } + if let image = UIImage(gradientColors: [UIColor(red: 0.808, green: 0.863, blue: 0.902, alpha: 1.0), UIColor(red: 0.349, green: 0.412, blue: 0.443, alpha: 1.0)], size: CGSize(width: imageWidth, height: imageHeight)) { + colors.append(CellItem(text: "Gradient Color", image: image)) + } + if let image = UIImage(named: "beach")?.applyGradientColors([UIColor(red: 0.996, green: 0.769, blue: 0.494, alpha: 1.0), UIColor(red: 0.969, green: 0.608, blue: 0.212, alpha: 0.2)]) { + colors.append(CellItem(text: "Gradient Overlay", image: image)) + } + if let image = UIImage(startColor: UIColor(red: 0.996, green: 1.0, blue: 1.0, alpha: 1.0), endColor: UIColor(red: 0.627, green: 0.835, blue: 0.922, alpha: 1.0), radialGradientCenter: CGPoint(x: 0.5, y: 0.5), radius: 0.5, size: CGSize(width: imageWidth, height: imageHeight)) { + colors.append(CellItem(text: "Radial Gradient", image: image)) + } + items.append(colors) + // Text sections.append("Text") - items.append([ - CellItem(text: "Text Image", image: UIImage(text: "M", font: UIFont.systemFontOfSize(64), color: UIColor.whiteColor(), backgroundColor: UIColor.redColor(), size: CGSize(width: imageWidth, height: imageHeight), offset: CGPoint(x: 0, y: 30))) - ]) - + var text = [CellItem]() + if let image = UIImage(text: "M", font: UIFont.systemFontOfSize(64), color: UIColor.whiteColor(), backgroundColor: UIColor.redColor(), size: CGSize(width: imageWidth, height: imageHeight), offset: CGPoint(x: 0.0, y: 30.0)) { + text.append(CellItem(text: "Text Image", image: image)) + } + items.append(text) + // Rounded Edges & Borders sections.append("Rounded Edges & Borders") - items.append([ - CellItem(text: "Circle", image: UIImage(named: "beach").roundCornersToCircle()), - CellItem(text: "Circle + Border", image: UIImage(named: "beach").roundCornersToCircle(border: 60, color: UIColor.grayColor())), - CellItem(text: "Round Corners", image: UIImage(named: "beach").roundCorners(12)) - ]) + var corners = [CellItem]() + if let image = UIImage(named: "beach")?.roundCornersToCircle() { + corners.append(CellItem(text: "Circle", image: image)) + } + if let image = UIImage(named: "beach")?.roundCornersToCircle(border: 60.0, color: UIColor.grayColor()) { + corners.append(CellItem(text: "Circle + Border", image: image)) + } + if let image = UIImage(named: "beach")?.roundCorners(12.0) { + corners.append(CellItem(text: "Round Corners", image: image)) + } + items.append(corners) + // Cropping sections.append("Cropping") - items.append([ - CellItem(text: "Crop + Resize", image: UIImage(named: "beach").crop(CGRect(x: 40, y: 40, width: 320, height: 100)).applyPadding(6)) - ]) + var cropping = [CellItem]() + if let image = UIImage(named: "beach")?.crop(CGRect(x: 40.0, y: 40.0, width: 320.0, height: 100.0))?.applyPadding(6.0) { + cropping.append(CellItem(text: "Crop + Resize", image: image)) + } + items.append(cropping) + // Screenshot sections.append("Screenshot") - items.append([ - CellItem(text: "From View", image: UIImage(fromView: self.view).resize(CGSize(width: imageWidth, height: imageHeight), contentMode: .ScaleAspectFill)) - ]) - + var screenshot = [CellItem]() + if let image = UIImage(fromView: self.view)?.resize(CGSize(width: imageWidth, height: imageHeight), contentMode: .ScaleAspectFill) { + screenshot.append(CellItem(text: "From View", image: image)) + } + items.append(screenshot) + + // Web Image sections.append("Web Image") - items.append([ - CellItem(text: "From URL", image: UIImage(color: UIColor.redColor())) - ]) + var web = [CellItem]() + if let image = UIImage(color: UIColor.redColor()) { + web.append(CellItem(text: "From URL", image: image)) + } + items.append(web) + } override func viewWillAppear(animated: Bool) { diff --git a/README.md b/README.md index 756dc3d..b115fbd 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -AF+Image+Helper 1.02 +AF+Image+Helper 1.03 ============================= Convenience extension for UIImage and UIImageView in Swift A collection of extensions for handling image creation from colors and gradients, cropping, scaling and fetching from the web with support for caching. -Tested with Xcode 6 Beta 7 +Tested with Xcode 6.1 GM ![Sample Project Screenshot](Screenshot.png?raw=true "Sample Project Screenshot")