I\'m facing an image orientation issue when cropping a square portion of an image out of a rectangular original image. When image is in landscape, it\'s fine. But when it is
@JGuo has the only answer that has actually worked. I've updated only a little bit to return an optional UIImage? and for swift-er syntax. I prefer to never implicitly unwrap.
extension UIImage {
func crop(to rect: CGRect) -> UIImage? {
func rad(_ degree: Double) -> CGFloat {
return CGFloat(degree / 180.0 * .pi)
}
var rectTransform: CGAffineTransform
switch imageOrientation {
case .left:
rectTransform = CGAffineTransform(rotationAngle: rad(90)).translatedBy(x: 0, y: -self.size.height)
case .right:
rectTransform = CGAffineTransform(rotationAngle: rad(-90)).translatedBy(x: -self.size.width, y: 0)
case .down:
rectTransform = CGAffineTransform(rotationAngle: rad(-180)).translatedBy(x: -self.size.width, y: -self.size.height)
default:
rectTransform = .identity
}
rectTransform = rectTransform.scaledBy(x: self.scale, y: self.scale)
guard let imageRef = self.cgImage?.cropping(to: rect.applying(rectTransform)) else { return nil }
let result = UIImage(cgImage: imageRef, scale: self.scale, orientation: self.imageOrientation)
return result
}
}
Here's its implementation as a computed property in my ViewController.
var croppedImage: UIImage? {
guard let image = self.image else { return nil }
let ratio = image.size.height / self.contentSize.height
let origin = CGPoint(x: self.contentOffset.x * ratio, y: self.contentOffset.y * ratio)
let size = CGSize(width: self.bounds.size.width * ratio, height: self.bounds.size.height * ratio)
let cropFrame = CGRect(origin: origin, size: size)
let croppedImage = image.crop(to: cropFrame)
return croppedImage
}