Swift: 在没有 TabBar 和 NavigationBar 的情况下裁剪屏幕截图
Swift: Cropping a Screenshot without TabBar and NavigationBar
我有整个屏幕的屏幕截图,screenshot
,使用以下内容生成:
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 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)!
此代码导致 image
仅显示屏幕的一小部分,一个从屏幕左上角 (0, 0) 开始并向右延伸不到一半宽度的矩形屏幕的高度,然后向下移动不到屏幕高度的一半。不过,我希望它包括 整个 屏幕,但选项卡栏占据的区域除外。有没有这样的方法来裁剪它?
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];
这里有两种选择:
首先,您可以使用 UIApplication.sharedApplication().keyWindow
截取屏幕截图,然后我们将得到:
UIGraphicsBeginImageContext(UIApplication.sharedApplication().keyWindow!.bounds.size)
UIApplication.sharedApplication().keyWindow!.layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
因此,您必须像这样裁剪图像:
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)!
第二个选项是直接截取您的视图,如下所示:
UIGraphicsBeginImageContext(self.view!.bounds.size)
self.view!.layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
在这种情况下,您不需要裁剪导航栏。
这是 github https://github.com/gazolla/crop
处的示例代码
我认为你的作物 CGRect
是错误的。
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 和 Y: 0 - 分别从 0、0 开始。
宽度:捕获视图的整个宽度
高度:整个视图的高度加上UINavigationBar
的高度减去UITabBar
的高度。
据此
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.
您将需要像这样的裁剪功能。您可能需要调整 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
}
我的回答在Swift4.2,步骤在函数中代码上面的注释里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
}
这也是Swift 4.2 版接受的答案:
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
}
我有整个屏幕的屏幕截图,screenshot
,使用以下内容生成:
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 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)!
此代码导致 image
仅显示屏幕的一小部分,一个从屏幕左上角 (0, 0) 开始并向右延伸不到一半宽度的矩形屏幕的高度,然后向下移动不到屏幕高度的一半。不过,我希望它包括 整个 屏幕,但选项卡栏占据的区域除外。有没有这样的方法来裁剪它?
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];
这里有两种选择:
首先,您可以使用 UIApplication.sharedApplication().keyWindow
截取屏幕截图,然后我们将得到:
UIGraphicsBeginImageContext(UIApplication.sharedApplication().keyWindow!.bounds.size)
UIApplication.sharedApplication().keyWindow!.layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
因此,您必须像这样裁剪图像:
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)!
第二个选项是直接截取您的视图,如下所示:
UIGraphicsBeginImageContext(self.view!.bounds.size)
self.view!.layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
在这种情况下,您不需要裁剪导航栏。
这是 github https://github.com/gazolla/crop
处的示例代码我认为你的作物 CGRect
是错误的。
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 和 Y: 0 - 分别从 0、0 开始。
宽度:捕获视图的整个宽度
高度:整个视图的高度加上UINavigationBar
的高度减去UITabBar
的高度。
据此
The new image is created by
1) adjustingrect
to integral bounds by callingCGRectIntegral
;
2) intersecting the result with a rectangle with origin (0, 0) and size equal to the size ofimage
;
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.
您将需要像这样的裁剪功能。您可能需要调整 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
}
我的回答在Swift4.2,步骤在函数中代码上面的注释里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
}
这也是Swift 4.2 版接受的答案:
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
}