How to take a screenshot of part of a UIView?

I want the user to go into my application and take a screenshot after clicking the button programmatically in Swift. I know that UIGraphicsGetImageFromCurrentImageContext() takes a screenshot, but I don't need a screenshot of the whole screen. I want the rectangle to pop up (sort of like a cropping tool), and the user can drag and resize the rectangle to take a screenshot of only a specific part of the screen. I want the rectangle to go through WKWebView and WKWebView image of the web view.

+10
source share
2 answers

The standard snapshot technique is drawHierarchy(in:afterScreenUpdates:) , which draws this in the context of the image. In iOS 10 and later, you can use UIGraphicsImageRenderer :

 extension UIView { /// Create image snapshot of view. /// /// - Parameters: /// - rect: The coordinates (in the view own coordinate space) to be captured. If omitted, the entire 'bounds' will be captured. /// - afterScreenUpdates: A Boolean value that indicates whether the snapshot should be rendered after recent changes have been incorporated. Specify the value false if you want to render a snapshot in the view hierarchys current state, which might not include recent changes. Defaults to 'true'. /// /// - Returns: The 'UIImage' snapshot. func snapshot(of rect: CGRect? = nil, afterScreenUpdates: Bool = true) -> UIImage { return UIGraphicsImageRenderer(bounds: rect ?? bounds).image { _ in drawHierarchy(in: bounds, afterScreenUpdates: afterScreenUpdates) } } } 

And you would use it like this:

 let image = webView.snapshot(of: rect) 

Prior to iOS 10, you would like to get a portion of the image, you can use the cropping(to:) CGImage cropping(to:) method. For instance:

 extension UIView { /// Create snapshot /// /// - Parameters: /// - rect: The coordinates (in the view own coordinate space) to be captured. If omitted, the entire 'bounds' will be captured. /// - afterScreenUpdates: A Boolean value that indicates whether the snapshot should be rendered after recent changes have been incorporated. Specify the value false if you want to render a snapshot in the view hierarchys current state, which might not include recent changes. Defaults to 'true'. /// /// - Returns: Returns 'UIImage' of the specified portion of the view. func snapshot(of rect: CGRect? = nil, afterScreenUpdates: Bool = true) -> UIImage? { // snapshot entire view UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0) drawHierarchy(in: bounds, afterScreenUpdates: afterScreenUpdates) let wholeImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() // if no 'rect' provided, return image of whole view guard let image = wholeImage, let rect = rect else { return wholeImage } // otherwise, grab specified 'rect' of image guard let cgImage = image.cgImage?.cropping(to: rect * image.scale) else { return nil } return UIImage(cgImage: cgImage, scale: image.scale, orientation: .up) } } 

Which uses this little handy statement:

 extension CGRect { static func * (lhs: CGRect, rhs: CGFloat) -> CGRect { return CGRect(x: lhs.minX * rhs, y: lhs.minY * rhs, width: lhs.width * rhs, height: lhs.height * rhs) } } 

And to use it, you can do:

 if let image = webView.snapshot(of: rect) { // do something with 'image' here } 

To play Swift 2, see the previous version of this answer .

+28
source

This is a previously asked question in How to capture a UIView for UIImage without losing quality on the retina screen , but for quick deployment (2.3):

 extension UIView { class func image(view: UIView) -> UIImage? { UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0) guard let ctx = UIGraphicsGetCurrentContext() else { return nil } view.layer.renderInContext(ctx) let img = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return img } func image() -> UIImage? { return UIView.image(self) } } 

Thus, you can either get the image from the view using UIView.image(theView) , or by requesting the view itself let viewImage = self.view.image()

Keep in mind that this is rude and probably needs further study of thread safety, etc.

+3
source

All Articles