0

I want to crop images from the center with a specific width and height. I found this code in a SO issue but this method resize the image then it crop it. I want to only get my image cropped and not resized. I tried modifying this code but I can't get the result that I want.

//cropImage
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 = CGRect(x: posX, y: posY, width: cgwidth, height: cgheight)
// Create bitmap image from context using the rect
let imageRef: CGImage = contextImage.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
} 

How can I do that?

Md. Ibrahim Hassan
  • 5,359
  • 1
  • 25
  • 45
Ne AS
  • 1,490
  • 3
  • 26
  • 58

3 Answers3

2

It should be:

func cropImage(toRect rect:CGRect) -> UIImage? {
    var rect = rect
    rect.origin.y = rect.origin.y * self.scale
    rect.origin.x = rect.origin.x * self.scale
    rect.size.width = rect.width * self.scale
    rect.size.height = rect.height * self.scale

    guard let imageRef = self.cgImage?.cropping(to: rect) else {
        return nil
    }

    let croppedImage = UIImage(cgImage:imageRef)
    return croppedImage
}
0
  1. Make sure image will be cropped in the center.
  2. Include largest crop zone possible given by the width and height.
extension UIImage {

    func crop(width: CGFloat = 60, height: CGFloat = 60) -> UIImage {
        let scale = min(self.size.width / width, self.size.height / height)

        let x = self.size.width > self.size.height
            ? (self.size.width - width * scale) / 2 
            : 0

        let y = self.size.width > self.size.height 
            ? 0 
            : (self.size.height - height * scale) / 2

        let cropZone = CGRect(x: x, y: y, width: width * scale, height: height * scale)
        guard let image: CGImage = self.cgImage?.cropping(to: cropZone) else { return UIImage() }

        return UIImage(cgImage: image)
    }
-1

I am using this to display image which ratio is different from my frame, so I center it and crop the sides.

extension UIImage {
func cropTo(size: CGSize) -> UIImage {
    guard let cgimage = self.cgImage else { return self }

    let contextImage: UIImage = UIImage(cgImage: cgimage)

    var cropWidth: CGFloat = size.width
    var cropHeight: CGFloat = size.height

    if (self.size.height < size.height || self.size.width < size.width){
        return self
    }

    let heightPercentage = self.size.height/size.height
    let widthPercentage = self.size.width/size.width

    if (heightPercentage < widthPercentage) {
        cropHeight = size.height*heightPercentage
        cropWidth = size.width*heightPercentage
    } else {
        cropHeight = size.height*widthPercentage
        cropWidth = size.width*widthPercentage
    }

    let posX: CGFloat = (self.size.width - cropWidth)/2
    let posY: CGFloat = (self.size.height - cropHeight)/2

    let rect: CGRect = CGRect(x: posX, y: posY, width: cropWidth, height: cropHeight)

    // Create bitmap image from context using the rect
    let imageRef: CGImage = contextImage.cgImage!.cropping(to: rect)!

    // 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)

    return cropped
   }
}