diff --git a/UIImage+Resize.swift b/UIImage+Resize.swift index 36594de..f2d3e97 100644 --- a/UIImage+Resize.swift +++ b/UIImage+Resize.swift @@ -11,57 +11,53 @@ import Foundation import UIKit extension UIImage { - + // Returns a copy of this image that is cropped to the given bounds. // The bounds will be adjusted using CGRectIntegral. // This method ignores the image's imageOrientation setting. - func croppedImage(bounds: CGRect) -> UIImage { - let imageRef:CGImageRef = CGImageCreateWithImageInRect(self.CGImage, bounds) - return UIImage(CGImage: imageRef)! + func croppedImage(_ bounds: CGRect) -> UIImage { + let imageRef:CGImage = self.cgImage!.cropping(to: bounds)! + return UIImage(cgImage: imageRef) } - - func thumbnailImage( - thumbnailSize: Int, - transparentBorder borderSize:Int, - cornerRadius:Int, - interpolationQuality quality:CGInterpolationQuality - ) -> UIImage { - var resizedImage:UIImage = self.resizedImageWithContentMode( - .ScaleAspectFill, - bounds: CGSizeMake(CGFloat(thumbnailSize), CGFloat(thumbnailSize)), + + func thumbnailImage( _ thumbnailSize: Int, transparentBorder borderSize:Int, + cornerRadius:Int, interpolationQuality quality:CGInterpolationQuality) -> UIImage { + let resizedImage:UIImage = self.resizedImageWithContentMode( + .scaleAspectFill, + bounds: CGSize(width: CGFloat(thumbnailSize), height: CGFloat(thumbnailSize)), interpolationQuality: quality ) - var cropRect:CGRect = CGRectMake( - round((resizedImage.size.width - CGFloat(thumbnailSize))/2), - round((resizedImage.size.height - CGFloat(thumbnailSize))/2), - CGFloat(thumbnailSize), - CGFloat(thumbnailSize) + let cropRect:CGRect = CGRect( + x: round((resizedImage.size.width - CGFloat(thumbnailSize))/2), + y: round((resizedImage.size.height - CGFloat(thumbnailSize))/2), + width: CGFloat(thumbnailSize), + height: CGFloat(thumbnailSize) ) - - var croppedImage:UIImage = resizedImage.croppedImage(cropRect) + + let croppedImage:UIImage = resizedImage.croppedImage(cropRect) return croppedImage } - + // Returns a rescaled copy of the image, taking into account its orientation // The image will be scaled disproportionately if necessary to fit the bounds specified by the parameter - func resizedImage(newSize:CGSize, interpolationQuality quality:CGInterpolationQuality) -> UIImage { + func resizedImage(_ newSize:CGSize, interpolationQuality quality:CGInterpolationQuality) -> UIImage { var drawTransposed:Bool - + switch(self.imageOrientation) { - case .Left: + case .left: fallthrough - case .LeftMirrored: + case .leftMirrored: fallthrough - case .Right: + case .right: fallthrough - case .RightMirrored: + case .rightMirrored: drawTransposed = true break default: drawTransposed = false break } - + return self.resizedImage( newSize, transform: self.transformForOrientation(newSize), @@ -69,111 +65,104 @@ extension UIImage { interpolationQuality: quality ) } - - func resizedImageWithContentMode( - contentMode:UIViewContentMode, - bounds:CGSize, - interpolationQuality quality:CGInterpolationQuality - ) -> UIImage { - var horizontalRatio:CGFloat = bounds.width / self.size.width - var verticalRatio:CGFloat = bounds.height / self.size.height + + func resizedImageWithContentMode( _ contentMode:UIViewContentMode, bounds:CGSize, + interpolationQuality quality:CGInterpolationQuality) -> UIImage { + let horizontalRatio:CGFloat = bounds.width / self.size.width + let verticalRatio:CGFloat = bounds.height / self.size.height var ratio:CGFloat = 1 - + switch(contentMode) { - case .ScaleAspectFill: + case .scaleAspectFill: ratio = max(horizontalRatio, verticalRatio) break - case .ScaleAspectFit: + case .scaleAspectFit: ratio = min(horizontalRatio, verticalRatio) break default: - println("Unsupported content mode \(contentMode)") + print("Unsupported content mode \(contentMode)") } - - var newSize:CGSize = CGSizeMake(self.size.width * ratio, self.size.height * ratio) + + let newSize:CGSize = CGSize(width: self.size.width * ratio, height: self.size.height * ratio) return self.resizedImage(newSize, interpolationQuality: quality) } - - func resizedImage( - newSize:CGSize, - transform:CGAffineTransform, - drawTransposed transpose:Bool, - interpolationQuality quality:CGInterpolationQuality - ) -> UIImage { - var newRect:CGRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height)) - var transposedRect:CGRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width) - var imageRef:CGImageRef = self.CGImage - - // build a context that's the same dimensions as the new size - var bitmap:CGContextRef = CGBitmapContextCreate( - nil, - UInt(newRect.size.width), - UInt(newRect.size.height), - CGImageGetBitsPerComponent(imageRef), - 0, - CGImageGetColorSpace(imageRef), - CGImageGetBitmapInfo(imageRef) - ) - - // rotate and/or flip the image if required by its orientation - CGContextConcatCTM(bitmap, transform) - - // set the quality level to use when rescaling - CGContextSetInterpolationQuality(bitmap, quality) - - // draw into the context; this scales the image - CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef) - - // get the resized image from the context and a UIImage - var newImageRef:CGImageRef = CGBitmapContextCreateImage(bitmap) - var newImage:UIImage = UIImage(CGImage: newImageRef)! - - return newImage + + func resizedImage( _ newSize:CGSize, transform:CGAffineTransform, + drawTransposed transpose:Bool, interpolationQuality quality:CGInterpolationQuality) -> UIImage { + let newRect:CGRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral + let transposedRect:CGRect = CGRect(x: 0, y: 0, width: newRect.size.height, height: newRect.size.width) + let imageRef:CGImage = self.cgImage! + + // build a context that's the same dimensions as the new size + let bitmap:CGContext = CGContext( + data: nil, + width: Int(UInt(newRect.size.width)), + height: Int(UInt(newRect.size.height)), + bitsPerComponent: imageRef.bitsPerComponent, + bytesPerRow: 0, + space: imageRef.colorSpace!, + bitmapInfo: imageRef.bitmapInfo.rawValue + )! + + // rotate and/or flip the image if required by its orientation + bitmap.concatenate(transform) + + // set the quality level to use when rescaling + bitmap.interpolationQuality = quality + + // draw into the context; this scales the image + bitmap.draw(imageRef, in: transpose ? transposedRect : newRect) + + // get the resized image from the context and a UIImage + let newImageRef:CGImage = bitmap.makeImage()! + let newImage:UIImage = UIImage(cgImage: newImageRef) + + return newImage } - - func transformForOrientation(newSize:CGSize) -> CGAffineTransform { - var transform:CGAffineTransform = CGAffineTransformIdentity + + func transformForOrientation(_ newSize:CGSize) -> CGAffineTransform { + var transform:CGAffineTransform = CGAffineTransform.identity switch (self.imageOrientation) { - case .Down: // EXIF = 3 + case .down: // EXIF = 3 fallthrough - case .DownMirrored: // EXIF = 4 - transform = CGAffineTransformTranslate(transform, newSize.width, newSize.height) - transform = CGAffineTransformRotate(transform, CGFloat(M_PI)) + case .downMirrored: // EXIF = 4 + transform = transform.translatedBy(x: newSize.width, y: newSize.height) + transform = transform.rotated(by: CGFloat(M_PI)) break - case .Left: // EXIF = 6 + case .left: // EXIF = 6 fallthrough - case .LeftMirrored: // EXIF = 5 - transform = CGAffineTransformTranslate(transform, newSize.width, 0) - transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2)) + case .leftMirrored: // EXIF = 5 + transform = transform.translatedBy(x: newSize.width, y: 0) + transform = transform.rotated(by: CGFloat(M_PI_2)) break - case .Right: // EXIF = 8 + case .right: // EXIF = 8 fallthrough - case .RightMirrored: // EXIF = 7 - transform = CGAffineTransformTranslate(transform, 0, newSize.height) - transform = CGAffineTransformRotate(transform, -CGFloat(M_PI_2)) + case .rightMirrored: // EXIF = 7 + transform = transform.translatedBy(x: 0, y: newSize.height) + transform = transform.rotated(by: -CGFloat(M_PI_2)) break default: break } - + switch(self.imageOrientation) { - case .UpMirrored: // EXIF = 2 + case .upMirrored: // EXIF = 2 fallthrough - case .DownMirrored: // EXIF = 4 - transform = CGAffineTransformTranslate(transform, newSize.width, 0) - transform = CGAffineTransformScale(transform, -1, 1) + case .downMirrored: // EXIF = 4 + transform = transform.translatedBy(x: newSize.width, y: 0) + transform = transform.scaledBy(x: -1, y: 1) break - case .LeftMirrored: // EXIF = 5 + case .leftMirrored: // EXIF = 5 fallthrough - case .RightMirrored: // EXIF = 7 - transform = CGAffineTransformTranslate(transform, newSize.height, 0) - transform = CGAffineTransformScale(transform, -1, 1) + case .rightMirrored: // EXIF = 7 + transform = transform.translatedBy(x: newSize.height, y: 0) + transform = transform.scaledBy(x: -1, y: 1) break default: break } - + return transform } - + }