How to Take Screenshot of Portion of Uiview

How to take screenshot of portion of UIView?

The standard snapshot technique is drawHierarchy(in:afterScreenUpdates:), drawing that to an image context. In iOS 10 and later, you can use UIGraphicsImageRenderer:

extension UIView {

/// Create image snapshot of view.
///
/// - Parameters:
/// - rect: The coordinates (in the view's 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 hierarchy’s 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’d use that like so:

let image = webView.snapshot(of: rect)

Prior to iOS 10, you would to get portion of an image, you can use CGImage method cropping(to:). E.g.:

extension UIView {

/// Create snapshot
///
/// - Parameters:
/// - rect: The coordinates (in the view's 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 hierarchy’s 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 convenient operator:

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
}

For Swift 2 rendition, see previous revision of this answer.

How to take screenshot of a UIView in swift?

For drawing of one view, just use this:

    // Begin context
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.mainScreen().scale)

// Draw view in that context
drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)

// And finally, get image
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

If you want to use it multiple times, probably extension would do the job:

//Swift4

extension UIView {

func takeScreenshot() -> UIImage {

// Begin context
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)

// Draw view in that context
drawHierarchy(in: self.bounds, afterScreenUpdates: true)

// And finally, get image
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

if (image != nil)
{
return image!
}
return UIImage()
}
}

//Old Swift

extension UIView {

func takeScreenshot() -> UIImage {

// Begin context
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.mainScreen().scale)

// Draw view in that context
drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)

// And finally, get image
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

return image
}
}

To explain what those parameters do:

UIGraphicsBeginImageContextWithOptions() creates a temporary rendering
context into which the original is drawn. The first argument, size, is
the target size of the scaled image. The second argument, isOpaque is
used to determine whether an alpha channel is rendered. Setting this
to false for images without transparency (i.e. an alpha channel) may
result in an image with a pink hue. The third argument scale is the
display scale factor. When set to 0.0, the scale factor of the main
screen is used, which for Retina displays is 2.0 or higher (3.0 on the
iPhone 6 Plus).

More about it here http://nshipster.com/image-resizing/

As for the draw call, Apple Docs explains it to detail here and here

Screenshot Only Part of Screen - Swift

For example if you want to take the screen shot of the UIView rectangle at position (50,50) with height of (100,150).

First set the Image Context to the size of the rectangle. This sets the image size.

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,150), false, 0);

Now draw the view in this context in such a way that, the visible part of the screenshot starts at (50,50)

self.view.drawViewHierarchyInRect(CGRectMake(-50,-50,view.bounds.size.width,view.bounds.size.height) afterScreenUpdates: true)

This clips the screen shot at (100,150) because we set the size of our context. Now take the UIImage from this.

var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();

How to take a screenshot of UIView on a background thread?

Actually ,it is possible! But first on UIThread you need get some infos Like this:

CALayer* layer = view.layer;
CGRect frame = view.frame;

, then change to backgroundthead use codes below to get image:

UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
[layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

How Do I Take a Screen Shot of a UIView?

I think you may want renderInContext, not drawInContext. drawInContext is more a method you would override...

Note that it may not work in all views, specifically a year or so ago when I tried to use this with the live camera view it did not work.



Related Topics



Leave a reply



Submit