Dick Thunder
Dick Thunder

Reputation: 376

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:

https://gfycat.com/TornMaleAlligatorsnappingturtle

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! {
    didSet{
        cropButton.backgroundColor = UIColor.gray
    }
}


override func viewDidLoad() {

    super.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 = UIColor.black
    scrollView.contentSize = imageView.bounds.size

    scrollView.delegate = self

    setZoomScale()
    //centerScrollViewContents()

    scrollView.addSubview(imageView)
    view.addSubview(scrollView)
    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

    print(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!

Upvotes: 1

Views: 832

Answers (1)

Divyesh Gondaliya
Divyesh Gondaliya

Reputation: 904

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()
     UIGraphicsEndImageContext()

}

Upvotes: 1

Related Questions