In Swift programming , how do you crop an image and put it on the center afterwards?
This is what I've got so far ... I've successfully crop the image but I want to put it on the center after
ImgView.image = OrigImage var masklayer = CAShapeLayer() masklayer.frame = ImgView.frame masklayer.path = path.CGPath masklayer.fillColor = UIColor.whiteColor().CGColor masklayer.backgroundColor = UIColor.clearColor().CGColor ImgView.layer.mask = masklayer UIGraphicsBeginImageContext(ImgView.bounds.size); ImgView.layer.renderInContext(UIGraphicsGetCurrentContext()) var image = UIGraphicsGetImageFromCurrentImageContext() ImgView.image = image UIGraphicsEndImageContext();
UPDATE :
let rect: CGRect = CGRectMake(path.bounds.minX, path.bounds.minY, path.bounds.width, path.bounds.height) // Create bitmap image from context using the rect let imageRef: CGImageRef = CGImageCreateWithImageInRect(image.CGImage, rect) ImgView.bounds = rect ImgView.image = UIImage(CGImage: imageRef)
I was able to center it by getting the path.bound and size and change the bounds of my ImageView. :)
crop() does not crop the image in-place but return the cropped image. Hence, im=im. crop((left, top, right, bottom)) is required.
cropping(to: croprect) let cropped = UIImage(cgImage: cr!) context?. draw(cropped, in: rect) let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage!
To get a centered position for your crop, you can halve the difference of the height and width. Then you can assign the bounds for the new width and height after checking the orientation of the image (which part is longer)
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage { let contextImage: UIImage = UIImage(CGImage: image.CGImage)! let contextSize: CGSize = contextImage.size var posX: CGFloat = 0.0 var posY: CGFloat = 0.0 var cgwidth: CGFloat = CGFloat(width) var cgheight: CGFloat = CGFloat(height) // See what size is longer and create the center off of that if contextSize.width > contextSize.height { posX = ((contextSize.width - contextSize.height) / 2) posY = 0 cgwidth = contextSize.height cgheight = contextSize.height } else { posX = 0 posY = ((contextSize.height - contextSize.width) / 2) cgwidth = contextSize.width cgheight = contextSize.width } let rect: CGRect = CGRectMake(posX, posY, cgwidth, cgheight) // Create bitmap image from context using the rect let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect) // Create a new image based on the imageRef and rotate back to the original orientation let image: UIImage = UIImage(CGImage: imageRef, scale: image.scale, orientation: image.imageOrientation)! return image }
I found most of this info over at this website in case you wanted to read further.
Updated for Swift 4
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage { let cgimage = image.cgImage! let contextImage: UIImage = UIImage(cgImage: cgimage) let contextSize: CGSize = contextImage.size var posX: CGFloat = 0.0 var posY: CGFloat = 0.0 var cgwidth: CGFloat = CGFloat(width) var cgheight: CGFloat = CGFloat(height) // See what size is longer and create the center off of that if contextSize.width > contextSize.height { posX = ((contextSize.width - contextSize.height) / 2) posY = 0 cgwidth = contextSize.height cgheight = contextSize.height } else { posX = 0 posY = ((contextSize.height - contextSize.width) / 2) cgwidth = contextSize.width cgheight = contextSize.width } let rect: CGRect = CGRect(x: posX, y: posY, width: cgwidth, height: cgheight) // Create bitmap image from context using the rect let imageRef: CGImage = cgimage.cropping(to: rect)! // Create a new image based on the imageRef and rotate back to the original orientation let image: UIImage = UIImage(cgImage: imageRef, scale: image.scale, orientation: image.imageOrientation) return image }
The accepted answer only does squares for me. I needed a bit more flexible cropping mechanism so I wrote an extension as follows:
import UIKit
extension UIImage { func crop(to:CGSize) -> UIImage { guard let cgimage = self.cgImage else { return self } let contextImage: UIImage = UIImage(cgImage: cgimage) guard let newCgImage = contextImage.cgImage else { return self } let contextSize: CGSize = contextImage.size //Set to square var posX: CGFloat = 0.0 var posY: CGFloat = 0.0 let cropAspect: CGFloat = to.width / to.height var cropWidth: CGFloat = to.width var cropHeight: CGFloat = to.height if to.width > to.height { //Landscape cropWidth = contextSize.width cropHeight = contextSize.width / cropAspect posY = (contextSize.height - cropHeight) / 2 } else if to.width < to.height { //Portrait cropHeight = contextSize.height cropWidth = contextSize.height * cropAspect posX = (contextSize.width - cropWidth) / 2 } else { //Square if contextSize.width >= contextSize.height { //Square on landscape (or square) cropHeight = contextSize.height cropWidth = contextSize.height * cropAspect posX = (contextSize.width - cropWidth) / 2 }else{ //Square on portrait cropWidth = contextSize.width cropHeight = contextSize.width / cropAspect posY = (contextSize.height - cropHeight) / 2 } } let rect: CGRect = CGRect(x: posX, y: posY, width: cropWidth, height: cropHeight) // Create bitmap image from context using the rect guard let imageRef: CGImage = newCgImage.cropping(to: rect) else { return self} // Create a new image based on the imageRef and rotate back to the original orientation let cropped: UIImage = UIImage(cgImage: imageRef, scale: self.scale, orientation: self.imageOrientation) UIGraphicsBeginImageContextWithOptions(to, false, self.scale) cropped.draw(in: CGRect(x: 0, y: 0, width: to.width, height: to.height)) let resized = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return resized ?? self } }
You can use it so:
let size = CGSize(width: 300, height: 200) let image = UIImage(named: "my_great_photo")?.crop(size)
If anyone has ideas how to make the landscape, portrait and square handling a bit better let me know.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With