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
This is THE answer, credit to @awolf (Cropping an UIImage). Handles scale and orientation perfectly. Just call this method on the image you want to crop, and pass in the cropping CGRect
without worrying about scale or orientation. Feel free to check whether cgImage
is nil instead of force unwrapping it like I did here.
extension UIImage {
func croppedInRect(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)
let imageRef = self.cgImage!.cropping(to: rect.applying(rectTransform))
let result = UIImage(cgImage: imageRef!, scale: self.scale, orientation: self.imageOrientation)
return result
}
}
Another note: if you are working with imageView
embedded in a scrollView
, there is one additional step, you have to take the zoom factor into account. Assuming your imageView
spans the entire content view of the scrollView
, and you use the bounds of the scrollView
as the cropping frame, the cropped image can be obtained as
let ratio = imageView.image!.size.height / scrollView.contentSize.height
let origin = CGPoint(x: scrollView.contentOffset.x * ratio, y: scrollView.contentOffset.y * ratio)
let size = CGSize(width: scrollView.bounds.size.width * ratio, let height: scrollView.bounds.size.height * ratio)
let cropFrame = CGRect(origin: origin, size: size)
let croppedImage = imageView.image!.croppedInRect(rect: cropFrame)