可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a screenshot of the entire screen, 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'd like to crop it so that the tab bar is not included, 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 results in image
showing just a small portion of the screen, a rectangle starting at the upper-left corner of the screen (0, 0), and extending right for less than half the width of the screen, then downward for less than half the height of the screen. I'd like, though, for it to include the entire screen, except for the region occupied by the tab bar. Is there a such a way to crop it?
回答1:
According to this
The new image is created by
1) adjusting rect
to integral bounds by calling CGRectIntegral
;
2) intersecting the result with a rectangle with origin (0, 0) and size
equal to the size of image
;
3) referencing the pixels within the resulting rectangle, treating the
first pixel of the image data as the origin of the image.
If the resulting rectangle is the null rectangle, this function returns
NULL.
If W and H are the width and height of image, respectively, then the
point (0,0) corresponds to the first pixel of the image data; the point
(W-1, 0) is the last pixel of the first row of the image data; (0, H-1)
is the first pixel of the last row of the image data; and (W-1, H-1) is
the last pixel of the last row of the image data.
You will need to have a crop function like this. You may need adjust the calculation of the bottomBarHeight
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
}
回答2:
swift:
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-c:
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:
You have two options here:
First, you can take the screenshot using UIApplication.sharedApplication().keyWindow
then we will have this:
UIGraphicsBeginImageContext(UIApplication.sharedApplication().keyWindow!.bounds.size)
UIApplication.sharedApplication().keyWindow!.layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
So, you will have to crop the image like this:
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 the screenshot directly of your view, like this:
UIGraphicsBeginImageContext(self.view!.bounds.size)
self.view!.layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
In this case, you don't need to crop the navigationBar.
This is a sample code at github https://github.com/gazolla/crop
回答4:
I think your crop CGRect
is 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 the view's entire width
Height: The entire view's height plus the height of the UINavigationBar
minus the height of the UITabBar
.
回答5:
My answer in Swift 4.2, the steps are in the comments above the code in the function getScreenshot()
@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's y-axis at everything below the topBarHeight. For the height subtract the topBarHeight and tabBarHeight from the view's 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 Swift 4.2 version of the 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
}