Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cropping image with Swift and put it on center position

Tags:

ios

swift

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. :)

like image 755
jhayvi Avatar asked Aug 17 '15 00:08

jhayvi


People also ask

How do I center an image in a crop in Python?

crop() does not crop the image in-place but return the cropped image. Hence, im=im. crop((left, top, right, bottom)) is required.

How do I crop a ratio in Swift?

cropping(to: croprect) let cropped = UIImage(cgImage: cr!) context?. draw(cropped, in: rect) let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage!


2 Answers

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     } 
like image 68
Cole Avatar answered Sep 28 '22 07:09

Cole


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.

like image 25
Tanel Teemusk Avatar answered Sep 28 '22 07:09

Tanel Teemusk