以编程方式截取特定区域的屏幕截图

Posted

技术标签:

【中文标题】以编程方式截取特定区域的屏幕截图【英文标题】:Programmatically take a screenshot of specific area 【发布时间】:2012-01-31 22:27:41 【问题描述】:

就像您在我的代码中看到的那样,我截取了一个屏幕截图并将其保存到相册中。

//for retina displays
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) 
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
 else 
    UIGraphicsBeginImageContext(self.view.bounds.size);

[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);

一开始我使用webview.size 而不是self.view.bounds.size,它工作正常,因为视图位于0/0。但现在我将 WebView 居中,但图片从给定大小的0/0 开始。

对于给定的大小,我如何配置屏幕截图从另一个location(例如300/150)开始?

或者还有其他方法可以给UIWebView 拍照吗?

【问题讨论】:

这适用于桌面 OSX 还是仅适用于 iphone? 【参考方案1】:

您需要进行两项更改才能只抓取屏幕的一部分:

    创建较小的图像 - 使用您要捕获的矩形大小。 将要渲染的上下文的原点移动到要捕获的矩形的负 x/y 位置。

之后,您只需将图层渲染到您正在执行的上下文中,您应该会得到您正在寻找的内容。应该这样做:

CGRect grabRect = CGRectMake(40,40,300,200);

//for retina displays
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) 
    UIGraphicsBeginImageContextWithOptions(grabRect.size, NO, [UIScreen mainScreen].scale);
 else 
    UIGraphicsBeginImageContext(grabRect.size);

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, -grabRect.origin.x, -grabRect.origin.y);
[self.view.layer renderInContext:ctx];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);

【讨论】:

这会使我的应用程序崩溃。知道为什么吗?我已经添加了 QuartzCore 框架并将这段代码放在一个函数中,但仍然不行。 @rebellion - 我已经让它工作了。虽然相册里没有。请参阅下面的我的改编作为 UIView 类别方法。 谢谢,这对我很有用。只是图像背景颜色是白色的小问题,我希望它透明。我怎样才能做到这一点。请帮忙 图像背景颜色为白色,因为我上传的是 jpeg 图像而不是 png 图像。上面的代码很完美:)【参考方案2】:

我已经接受并测试了上面@escrafford 的答案,并让它正常工作。我确实在使其成为 UIView 上的类别方法的上下文中对其进行了测试,以便可以参数化“grabRect”。这是代码,作为返回 UIImageView 的 UIView 类别:

/**
 Takes a screenshot of a UIView at a specific point and size, as denoted by
 the provided croppingRect parameter. Returns a UIImageView of this cropped
 region.

 CREDIT: This is based on @escrafford's answer at http://***.com/a/15304222/535054
*/
- (UIImageView *)rp_screenshotImageViewWithCroppingRect:(CGRect)croppingRect 
    // For dealing with Retina displays as well as non-Retina, we need to check
    // the scale factor, if it is available. Note that we use the size of teh cropping Rect
    // passed in, and not the size of the view we are taking a screenshot of.
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) 
        UIGraphicsBeginImageContextWithOptions(croppingRect.size, YES, [UIScreen mainScreen].scale);
     else 
        UIGraphicsBeginImageContext(croppingRect.size);
    

    // Create a graphics context and translate it the view we want to crop so
    // that even in grabbing (0,0), that origin point now represents the actual
    // cropping origin desired:
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, -croppingRect.origin.x, -croppingRect.origin.y);
    [self.layer renderInContext:ctx];

    // Retrieve a UIImage from the current image context:
    UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // Return the image in a UIImageView:
    return [[UIImageView alloc] initWithImage:snapshotImage];

【讨论】:

这段代码当然是假设 ARC 并且在 ios6.1 上是最新的(一个有效的解决方案)。【参考方案3】:

我解决了我的问题,但没有回答问题:

我创建了一个UIView 的子类并将我的UIWebView 移到其中,使其相对于子类位于0/0。然后使用WebView的大小:

UIGraphicsBeginImageContext(webview.frame.size);

以及上面的其他代码。

现在您可以将子类移动到您想要的每个位置。

注意:如果您有日期/时间标签之类的标签,您也必须移动它们,否则图片上将看不到它们。

所以创建一个UIView 的子类并移动你想成为的每个IBOutlet 在里面的图片上看到。

问题仍然悬而未决: 那么是否可以对屏幕的特定区域进行拍照呢?

亲切的问候。 $h@rky

【讨论】:

【参考方案4】:
- (void)drawRect:(CGRect)rect 
  UIGraphicsBeginImageContext(self.bounds.size);    
  [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);  

您可以将其称为您的视图:]

【讨论】:

在创建 web 视图时调用 drawRect 方法 - 所以我在开始时有一个灰色的图片。我从中得到的想法是将代码拖放到我的 Web 视图位于 0/0 的自定义 UIView 类中。那行得通,但我再也看不到标签了,因为它是“根视图”的一部分。

以上是关于以编程方式截取特定区域的屏幕截图的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式截取可扩展的uitableview的屏幕截图

iOS - 以编程方式截取跳板(主屏幕)的屏幕截图

如何在 Android 上以编程方式截取屏幕截图? [复制]

以编程方式从服务中截取屏幕截图

我如何同时传递 x 和 y 轴以及屏幕的高度和宽度以快速以编程方式截取屏幕截图

您如何以编程方式在 Android ICS 及更高版本上截取屏幕截图?