Swift: crop screenshot without TabBar and NavigationBar

I have a screenshot of the entire screen, a screenshot generated using the following:

 let layer = UIApplication.sharedApplication().keyWindow!.layer let scale = UIScreen.mainScreen().scale UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); layer.renderInContext(UIGraphicsGetCurrentContext()) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() 

I would like to crop it so that the tab bar is not turned on, and I tried using the following code:

 let crop = CGRectMake(0, 0, //"start" at the upper-left corner self.view.bounds.width, //include half the width of the whole screen self.view.bounds.height + self.navigationController!.navigationBar.frame.height) //include the height of the navigationBar and the height of view let cgImage = CGImageCreateWithImageInRect(screenshot.CGImage, crop) let image: UIImage = UIImage(CGImage: cgImage)! 

This code causes image show only a small part of the screen, a rectangle starting in the upper left corner of the screen (0, 0), and extending to the right less than half the width of the screen, then down less than half the height of the screen. I would like it to turn on the entire screen, except for the area occupied by the tab bar. Is there any way to crop it?

+6
source share
5 answers

In accordance with this

A new image is created using 1) rect on integral boundaries by calling CGRectIntegral ; 2) the intersection of the result with a rectangle with the beginning (0, 0) and a size equal to the size of image ,
3) a reference to the pixels in the resulting rectangle, processing the first pixel of the image data as an image source.
If the resulting rectangle is a null rectangle, this function returns NULL.

If W and H are the image width and height, respectively, then the point (0,0) corresponds to the first pixel of the image data; the meaning (W-1, 0) is the last pixel of the first row of image data; (0, H-1) - the first pixel of the last row of image data; and (W-1, H-1) is the last pixel of the last row of image data.

You will need such a crop function. You may need to adjust bottomBarHeight calculation

 func takeScreenshot(sender: AnyObject) { let layer = UIApplication.sharedApplication().keyWindow!.layer let scale = UIScreen.mainScreen().scale UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); layer.renderInContext(UIGraphicsGetCurrentContext()) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() let croppedImage = self.cropImage(screenshot) } func cropImage(screenshot: UIImage) -> UIImage { let scale = screenshot.scale let imgSize = screenshot.size let screenHeight = UIScreen.mainScreen().applicationFrame.height let bound = self.view.bounds.height let navHeight = self.navigationController!.navigationBar.frame.height let bottomBarHeight = screenHeight - navHeight - bound let crop = CGRectMake(0, 0, //"start" at the upper-left corner (imgSize.width - 1) * scale, //include half the width of the whole screen (imgSize.height - bottomBarHeight - 1) * scale) //include the height of the navigationBar and the height of view let cgImage = CGImageCreateWithImageInRect(screenshot.CGImage, crop) let image: UIImage = UIImage(CGImage: cgImage)! return image } 
+8
source

speed:

 let contextImage: UIImage = <<screenshot>>! let cropRect: CGRect = CGRectMake(x, y, width, height) let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, cropRect) let image: UIImage = UIImage(CGImage: imageRef, scale: originalImage.scale, orientation: originalImage.imageOrientation)! 

OBJ-s:

 UIImage *image = <<screenshot>>; CGRect croprect = CGRectMake(0, 0, self.view.bounds.width, self.view.bounds.height + self.navigationController!.navigationBar.frame.height)); // Draw new image in current graphics context CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], croprect); // Create new cropped UIImage UIImage *croppedImage = [UIImage imageWithCGImage:imageRef]; 
+3
source

You have two options: First, you can take a screenshot using UIApplication.sharedApplication().keyWindow , then we get the following:

  UIGraphicsBeginImageContext(UIApplication.sharedApplication().keyWindow!.bounds.size) UIApplication.sharedApplication().keyWindow!.layer.renderInContext(UIGraphicsGetCurrentContext()) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() 

So you need to crop the image as follows:

  let yPosition = self.navigationController!.navigationBar.frame.height + UIApplication.sharedApplication().statusBarFrame.size.height let crop = CGRectMake(0, yPosition, self.view.bounds.width, self.view.bounds.height) let cgImage = CGImageCreateWithImageInRect(screenshot.CGImage, crop) let image: UIImage = UIImage(CGImage: cgImage)! 

The second option is to take a screenshot directly from your view, for example:

  UIGraphicsBeginImageContext(self.view!.bounds.size) self.view!.layer.renderInContext(UIGraphicsGetCurrentContext()) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() 

In this case, you do not need to trim the navigation bar.

This is sample code on github https://github.com/gazolla/crop

+2
source

I think your crop of CGRect wrong.

 let crop = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height + self.navigationController!.navigationBar.frame.height - self.tabBar.frame.size.height ) 

X: 0 and Y: 0 - start at 0, 0, respectively.

Width: Capture full width view

Height: The entire height of the view plus the height of the UINavigationBar minus the height of the UITabBar .

0
source

My answer is in Swift 4.2, the steps in the comments above the code in the getScreenshot() function

 @IBAction fileprivate func takeScreenshotButtonTapped(_ sender: UIButton) { guard let croppedScreenshotImage = getScreenshot() else { return } // do something with the croppedScreenshotImage } func getScreenshot() -> UIImage? { // 1. get screenshot of the entire screen UIGraphicsBeginImageContext(UIApplication.shared.keyWindow!.bounds.size) UIApplication.shared.keyWindow!.layer.render(in: UIGraphicsGetCurrentContext()!) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() // 2. height of statusBar let statusBarHeight = UIApplication.shared.statusBarFrame.size.height // 3. height of navigationBar var navBarHeight: CGFloat = 0 if let navigationBarHeight = navigationController?.navigationBar.frame.height { navBarHeight = navigationBarHeight } // 4. total height of statusBar + navigationBar let topBarHeight = statusBarHeight + navBarHeight // 5. get the height of the tabBar var tabBarHeight: CGFloat = 0 if let tabBarController = tabBarController { tabBarHeight = tabBarController.tabBar.frame.size.height } // 6. to exclude the navigationBar, statusBar, and tabBar from your screenshot start the rect y-axis at everything below the topBarHeight. For the height subtract the topBarHeight and tabBarHeight from the view height let rectWithoutNavStatusAndTabBar = CGRect(x: 0, y: topBarHeight, width: self.view.bounds.width, height: self.view.bounds.height - topBarHeight - tabBarHeight) guard let safeScreenshot = screenshot else { return nil } // 7. crop the screenshot to the rectWithoutNavStatusAndTabBar guard let cgImage = safeScreenshot.cgImage?.cropping(to: rectWithoutNavStatusAndTabBar) else { return nil } // 8. create an image from the cgImage let yourCroppedScreenshotImage = UIImage(cgImage: cgImage) return yourCroppedScreenshotImage } 

This is also the version of Swift 4.2 accepted answer:

 func takeScreenshot(sender: AnyObject) { let layer = UIApplication.shared.keyWindow!.layer let scale = UIScreen.main.scale UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); layer.render(in: UIGraphicsGetCurrentContext()!) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() let croppedImage = self.cropImage(screenshot: screenshot!) } func cropImage(screenshot: UIImage) -> UIImage { let scale = screenshot.scale let imgSize = screenshot.size let screenHeight = UIScreen.main.bounds.height let bound = self.view.bounds.height let navHeight = self.navigationController!.navigationBar.frame.height let bottomBarHeight = screenHeight - navHeight - bound let crop = CGRect(x: 0, y: 0, width: (imgSize.width - 1) * scale, height: (imgSize.height - bottomBarHeight - 1) * scale) let cgImage = screenshot.cgImage?.cropping(to: crop) let image: UIImage = UIImage(cgImage: cgImage!) return image } 
0
source

All Articles