MHCsk MHCsk -3 years ago 168
iOS Question

Cropping part of UIImage with the screen aspect ratio

I've been struggling with this for quite some time now. I'd like to make image cropper similar to the one included in iOS itself when you select your wallpaper. Basically I want the area that user selects cropped from the image with zoom and aspect ratio of the screen (so the user can use the image as a wallpaper later on). Like this:

I've managed to create the interface with UIScrollView and UIImageView:

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

var scrollView: UIScrollView!
var imageView: UIImageView!

var croppedImage: UIImage?

@IBOutlet weak var cropButton: UIButton! {
cropButton.backgroundColor = UIColor.gray

override func viewDidLoad() {


let image = UIImage(named: "mountains")!

imageView = UIImageView(image: image)
imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size:image.size)
imageView.contentMode = .scaleAspectFill

scrollView = UIScrollView(frame: view.bounds)
scrollView.backgroundColor =
scrollView.contentSize = imageView.bounds.size

scrollView.delegate = self


view.bringSubview(toFront: cropButton)


func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView

@IBAction func crop(_ sender: UIButton) {

let rect = CGRect(x: ?, y: ?, width: ?, height: ?)
let croppedCGImage = imageView.image?.cgImage?.cropping(to: rect)
self.croppedImage = UIImage(cgImage: croppedCGImage!)

func setZoomScale() {
let imageViewSize = imageView.bounds.size
let scrollViewSize = scrollView.bounds.size
//let widthScale = scrollViewSize.width / imageViewSize.width
let heightScale = scrollViewSize.height / imageViewSize.height

scrollView.minimumZoomScale = heightScale //min(widthScale, heightScale)
scrollView.maximumZoomScale = 3
scrollView.zoomScale = heightScale


I can zoom and pan around the image no problem. The problem is I don't know how to create the CGRect rectangle that represents the area that is displayed to the user, which is also the area I want to crop from the original image. Any ideas that will put me out of my misery are greatly appreciated!

Answer Source

snapshotImageFromMyView is the output image

self.btn.isHidden = true

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        UIGraphicsBeginImageContextWithOptions(self.YourView.bounds.size, self.YourView.isOpaque, 0.0)
        self.YourView.drawHierarchy(in: self.YourView.bounds, afterScreenUpdates: false)
    let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download