使用屏幕纵横比裁剪 UIImage 的一部分

Cropping part of UIImage with the screen aspect ratio

我已经为此苦苦挣扎了一段时间。当你 select 你的墙纸时,我想制作类似于 iOS 本身包含的图像裁剪器。基本上我想要用户 selects 从具有缩放和屏幕纵横比的图像中裁剪的区域(以便用户稍后可以将图像用作墙纸)。像这样:

https://gfycat.com/TornMaleAlligatorsnappingturtle

我已经成功创建了与 UIScrollView 和 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) 
} 
}.

我可以毫无问题地缩放和平移图像。问题是我不知道如何创建代表显示给用户的区域的 CGRect 矩形,这也是我想从原始图像中裁剪的区域。非常感谢任何能让我摆脱痛苦的想法!

snapshotImageFromMyView 是输出图像

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

}