Iphone UIWebView到UIImage
我尝试使用此方法从UIWebView捕获图像,但图像仅包含屏幕的可见区域。如何将UIWebView的全部内容(包括不可见区域,即整个网页)捕获到单个图像中Iphone UIWebView到UIImage,iphone,objective-c,xcode,uiwebview,Iphone,Objective C,Xcode,Uiwebview,我尝试使用此方法从UIWebView捕获图像,但图像仅包含屏幕的可见区域。如何将UIWebView的全部内容(包括不可见区域,即整个网页)捕获到单个图像中 -(UIImage*)captureScreen:(UIView*) viewToCapture{ UIGraphicsBeginImageContext(viewToCapture.bounds.size); [viewToCapture.layer renderInContext:UIGraphicsGetCurrentConte
-(UIImage*)captureScreen:(UIView*) viewToCapture{
UIGraphicsBeginImageContext(viewToCapture.bounds.size);
[viewToCapture.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
}
编辑(摘自作者的评论)
解决办法是打电话
webView.scalesPageToFit = YES;
在初始化中,以及
[webView sizeToFit]
当页面完成加载时
您当前仅捕获可见部分,因为您将图像上下文限制为可见部分。你应该把它限制在可用的范围内
UIView
有一个scrollView
属性,该属性具有contentSize
,告诉您滚动视图中的web视图的大小。您可以使用该大小设置图像上下文,如下所示:
-(UIImage*)captureScreen:(UIView*) viewToCapture{
CGSize overallSize = overallSize;
UIGraphicsBeginImageContext(viewToCapture.scrollView.contentSize);
// Save the current bounds
CGRect tmp = viewToCapture.bounds;
viewToCapture.bounds = CGRectMake(0, 0, overallSize.width, overallSize.height);
// Wait for the view to finish loading.
// This is not very nice, but it should work. A better approach would be
// to use a delegate, and run the capturing on the did finish load event.
while (viewToCapture.loading) {
[NSThread sleepForTimeInterval:0.1];
}
[viewToCapture.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Restore the bounds
viewToCapture.bounds = tmp;
return viewImage;
}
编辑:我用测试过的代码给出了新答案 将下面的
方法添加到捕获UIWebView
到UIImage
中。它还将捕获不可见区域
- (UIImage*)webviewToImage:(UIWebView*)webView
{
int currentWebViewHeight = webView.scrollView.contentSize.height;
int scrollByY = webView.frame.size.height;
[webView.scrollView setContentOffset:CGPointMake(0, 0)];
NSMutableArray* images = [[NSMutableArray alloc] init];
CGRect screenRect = webView.frame;
int pages = currentWebViewHeight/scrollByY;
if (currentWebViewHeight%scrollByY > 0) {
pages ++;
}
for (int i = 0; i< pages; i++)
{
if (i == pages-1) {
if (pages>1)
screenRect.size.height = currentWebViewHeight - scrollByY;
}
if (IS_RETINA)
UIGraphicsBeginImageContextWithOptions(screenRect.size, NO, 0);
else
UIGraphicsBeginImageContext( screenRect.size );
if ([webView.layer respondsToSelector:@selector(setContentsScale:)]) {
webView.layer.contentsScale = [[UIScreen mainScreen] scale];
}
//UIGraphicsBeginImageContext(screenRect.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextFillRect(ctx, screenRect);
[webView.layer renderInContext:ctx];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (i == 0)
{
scrollByY = webView.frame.size.height;
}
else
{
scrollByY += webView.frame.size.height;
}
[webView.scrollView setContentOffset:CGPointMake(0, scrollByY)];
[images addObject:newImage];
}
[webView.scrollView setContentOffset:CGPointMake(0, 0)];
UIImage *resultImage;
if(images.count > 1) {
//join all images together..
CGSize size;
for(int i=0;i<images.count;i++) {
size.width = MAX(size.width, ((UIImage*)[images objectAtIndex:i]).size.width );
size.height += ((UIImage*)[images objectAtIndex:i]).size.height;
}
if (IS_RETINA)
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
else
UIGraphicsBeginImageContext(size);
if ([webView.layer respondsToSelector:@selector(setContentsScale:)]) {
webView.layer.contentsScale = [[UIScreen mainScreen] scale];
}
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextFillRect(ctx, screenRect);
int y=0;
for(int i=0;i<images.count;i++) {
UIImage* img = [images objectAtIndex:i];
[img drawAtPoint:CGPointMake(0,y)];
y += img.size.height;
}
resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
} else {
resultImage = [images objectAtIndex:0];
}
[images removeAllObjects];
return resultImage;
}
看看这个
或者用这个:):
这部分地解决了问题。生成的图像大小正确,但不可见区域全是白色。@Vad我认为问题与viewToCapture.layer
有关。查看临时设置边界是否可以解决此问题(请参阅更新)。我认为问题在于,在您滚动到web视图之前,web视图不会显示所有内容。@如果您是对的,则在调用renderContext:
时,web视图可能仍在加载其他内容。您能否添加NSLog(@“%d”,viewToCapture.loading)
并查看它是否打印1
或0
?解决方案是在页面完成加载时调用[webView sizeToFit],webView.scalesPageToFit=YES;在初始化中。这会导致图像上的可见内容被拉伸,而不可见内容仍然全部为白色/空白。我测试了一个很长的页面,但当if(images.count>1){~UIGraphicsBeginImageContextWithOptions(size,NO,0)时,应用程序崩溃;由于内存压力。分割是个好主意,但我想在聚合图像时会产生内存压力。你有什么解决方案吗?
#define IS_RETINA ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))
(UIImage*) imageFromWebview:(UIWebView*) webview{
//store the original framesize to put it back after the snapshot
CGRect originalFrame = webview.frame;
//get the width and height of webpage using js (you might need to use another call, this doesn't work always)
int webViewHeight = [[webview stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"] integerValue];
int webViewWidth = [[webview stringByEvaluatingJavaScriptFromString:@"document.body.scrollWidth;"] integerValue];
//set the webview's frames to match the size of the page
[webview setFrame:CGRectMake(0, 0, webViewWidth, webViewHeight)];
//make the snapshot
UIGraphicsBeginImageContextWithOptions(webview.frame.size, false, 0.0);
[webview.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//set the webview's frame to the original size
[webview setFrame:originalFrame];
//and VOILA :)
return image;
}