UIWebView to UIImage

对着背影说爱祢 提交于 2019-12-03 09:56:02

问题


I tried to capture image from UIWebView using this method but the image contains only visible area of the screen. How do I capture full content of UIWebView including invisible areas, i.e. the entire web page into one single image?

-(UIImage*)captureScreen:(UIView*) viewToCapture{
  UIGraphicsBeginImageContext(viewToCapture.bounds.size);
  [viewToCapture.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return viewImage;
}

回答1:


EDIT (from a comment by Vad)

Solution was to call

webView.scalesPageToFit = YES;

in the initialization, and

[webView sizeToFit]

when the page did finish loading.

You are currently capturing only the visible part because you are limiting the image context to what's visible. You should limit it to what's available.

UIView has a scrollView property that has contentSize, telling you what is the size of the web view inside the scroll view. You can use that size to set your image context like this:

-(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;
}



回答2:


Check this out Rendering a UIWebView into an ImageContext

or just use this :) :

    (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;
}



回答3:


EDIT : New answer from me with tested code.

Add below method to capture UIWebViewinto UIImage. It will also capture unvisible area as well.

- (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;
}

Also add these macro for checking if iOS is retina display

#define IS_RETINA ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))


来源:https://stackoverflow.com/questions/12040560/uiwebview-to-uiimage

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!