Hello currently I have the code in an IBAction which saves a screenshot of the UIWebView, what I want it for it to take a screenshot of the full content of the webpage (both what is visible and what is not)
So far I have managed to get it to take a screenshot of the size of the full content with the visible content showing, however the rest of the screenshot where the non-visible content is is white.
CGSize layerSize = [_myWebView sizeThatFits:myWebView.scrollView.contentSize];
if ([UIScreen instancesRespondToSelector:#selector(scale)] && [[UIScreen mainScreen] scale] == 2.0f) {
UIGraphicsBeginImageContextWithOptions(layerSize, NO, 2.0f);
UIGraphicsBeginImageContext(layerSize);
} else {
UIGraphicsBeginImageContext(layerSize);
}
[_myWebView.scrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, self, nil, nil);
What can I do to make all the content visible in the screenshot?
This is a guess:
Try adjusting the frame.size of the webView to be equal to the scrollView contentSize. Then, reload the webview and call renderInContext: after the reload is complete. See what that gives you.
If the frame of the webview is equal to the superview(screen) then the webview wont render the content which is out of the bounds. So You have to set the frame of webview to its contentSize and take a screenshot.
ContentSize can be obtained only after the webView is loaded. So in the webviewDidFinishLoad get the height of the webview's contentsize.
CGFloat webViewHeight;
-(void)webViewDidFinishLoad:(UIWebView *)webView{
webViewHeight = webView.scrollView.contentSize.height;
}
Then set the webview height to webview contentsize as follows
webView.frame = CGRectMake(webView.frame.origin.x,webView.frame.origin.y,webView.frame.size.width,webViewHeight);
then use
UIGraphicsBeginImageContext(webview.frame.size);
Related
I'm facing a really weird problem with UIImageView, I was trying to set an image - which created by take the screenshot of the current view - to an ImageView with content mode is UIViewContentModeScaleAspectFit.
It worked fine when I set the image by the interface builder in the xib file or when I set the image created by [UIImage imageNamed:]. They both worked fine with UIViewContentModeScaleAspectFit.
But when I take the snap shot of a view and set the image to the image view, the image did not fit to the UIImageView. I've tried all the solutions I found on here like .ClipsToBound = YES but they didn't work at all. I'm really confused by now.
Here's the code when I take the screen shot and create the UIImage:
- (UIImage *)screenshotWithRect:(CGRect)captureRect
{
CGFloat scale = [[UIScreen mainScreen] scale];
UIImage *screenshot;
UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, scale);
CGContextClipToRect (UIGraphicsGetCurrentContext(),captureRect);
{
if(UIGraphicsGetCurrentContext() == nil)
{
NSLog(#"UIGraphicsGetCurrentContext is nil. You may have a UIView (%#) with no really frame (%#)", [self class], NSStringFromCGRect(self.frame));
}
else
{
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
screenshot = UIGraphicsGetImageFromCurrentImageContext();
}
}
UIGraphicsEndImageContext();
return screenshot;
}
And when I set the image to the image view
UIImage* snap = [[UIImage alloc] init];
// start snap shot
UIView* superView = [self.view superview];
CGRect cutRect = [superView convertRect:self.cutView.frame fromView:_viewToCut];
snap = [superView screenshotWithRect:cutRect];
[self.view addSubview:self.editCutFrameView];
// end snap shot -> show edit view
[self.editCutFrameView setImage:snap];
Here's a picture compare the 2 results:
Many thanks for your help.
UPDATE: As #Saheb Roy mentioned about the size, I checked the image size and it's about 400x500px and the thumbnail.png's size is 512x512px so I think it's not about the size of the image.
This is because in the second case, the snapshot image is itself exactly that size as you can see. Hence the image is not being stretched or fitted accordingly.
Earlier images are fitting to screen accordingly as the images were bigger than the imageview but with different ratio or same than that of the image.
But the one where it is not fitting to the imageview, the image itself is of that much size, i.e. smaller than that of the imageview, hence it is NOT being fitted to the bounds.
I have a large image (1920*1080), and a smaller UIImageView (320*568) that scaled to full screen size in the story board.
Now I want to display this large image full screen size, but fit to the UIImageView.
I have tried all the content mode, but they are all not working. Every time it just shows the top left part of the image full screen sized.
[self.imageView setFrame:self.view.bounds];
[self.imageView setContentMode:UIViewContentModeScaleAspectFit] ;
[self.imageView setImage:image] ;
[self.view insertSubview:_imageView aboveSubview:_previewView] ;
So what might be wrong in my case? could that be a Xcode story board configuration error ?
thanks.
If you are seeing only the image top corner in your ImageView, then the possible reasons are: Your ImageView frame is out of screen size OR Content Mode is not set. In your code you are setting the frame as the bounds of the superview. If your are using Auto-layout, check the auto-layout are set properly. If this is ok, then try setting UIImageView ContentMode before setting the frame.
// Setting the content mode.
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
// Now set the frame.
[self.imageView setFrame:self.view.bounds];
Other solution is you can downscale your image to fit your ImageView. For that you can use the following function:
- (UIImage *)scaleImage:(UIImage *)orginalImage
{
float widthFactor = photoImageView.frame.size.width / orginalImage.size.width;
CGSize destinationSize = CGSizeMake(orginalImage.size.width * widthFactor,orginalImage.size.height * widthFactor);
UIGraphicsBeginImageContext(destinationSize);
[orginalImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
photoImageView.image = scaledImage;
return scaledImage;
}
There is a problem that CIImage does somehow not respect contentMode (at least on some devices / iOS versions). Convert CIImage to a CGImage to make this work.
Swift 3 code:
func convertCIImageToCGImage(inputImage: CIImage) -> CGImage?
{
let context = CIContext(options: nil)
if let cgImage = context.createCGImage(inputImage, from: inputImage.extent)
{
return cgImage
}
return nil
}
Try this
[self.imageView setFrame:self.view.bounds];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageView.clipsToBounds = YES;
[self.imageView setImage:image] ;
[self.view insertSubview:_imageView aboveSubview:_previewView] ;
Working fine .. :)
In my case, i solved this removing some constraints that resize the imageview that i set by error.
Check your imageview constraints, try removing all of them
Basically what I am doing is taking an image of the view, applying a blur to it, and then using that as a blurred uiview overlay in reusable collection view cells in a simple uicollectionview.
// Capture Screen for blurr.
-(UIImage *) captureScreen:(CGRect)frame
{
CGRect grabRect = frame;
//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.contentView.layer renderInContext:ctx];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
viewImage = [viewImage applyBlurWithRadius:1.8f tintColor:nil saturationDeltaFactor:1.0 maskImage:viewImage atFrame:self.imageView.frame];
return viewImage;
}
// Set blurred image as image view image.
- (void) updateBlur
{
UIImage* infoViewImage = [self captureScreen:self.infoView.frame];
self.infoImageView.image = infoViewImage;
}
// Prepare for reuse.
- (void) prepareForReuse
{
self.infoImageView.image = nil;
}
Note the uiimageview is created and added as a subview to the cell's contentView in the initialization. Whenever I scroll slowly this works fine. If I scroll quickly the image will only be removed from the image view sometimes... I am not really sure why this is happening. So far I have tried a number of solutions, even removing the whole uiimageview from the superview and re-initializing/re-adding it as a subview each time but this action has the same issue. Please help!
The problem is that the reusable collection view cells are... reusable. You need to implement collectionView:cellForItemAtIndexPath: to deal with every cell it is ever handed, without making any assumptions about whether you may previously have added the subview to it.
I am working on iOS application where I need to capture the view and send MMS to particular person.Its all working fine.But I am facing problem to capture which is not visible (For more clarification I attached image).
I am getting the screen shot of the view which is visible.How to solve the problem? Is there any approach to reach my requirement? The image what I am getting is
I used the code to take screenshot is
UIGraphicsBeginImageContext(webview_pdf.bounds.size);
[webview_pdf.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *pdfImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Good suggestions are appreciable.Thanks in advance.!
Finally found the solution to this
+ (UIImage *) imageFromWebView:(UIWebView *)view
{
// tempframe to reset view size after image was created
CGRect tmpFrame = view.frame;
// set new Frame
CGRect aFrame = view.frame;
aFrame.size.height = [view sizeThatFits:[[UIScreen mainScreen] bounds].size].height;
view.frame = aFrame;
// do image magic
UIGraphicsBeginImageContext([view sizeThatFits:[[UIScreen mainScreen] bounds].size]);
CGContextRef resizedContext = UIGraphicsGetCurrentContext();
[view.layer renderInContext:resizedContext];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// reset Frame of view to origin
view.frame = tmpFrame;
return image;
}
You need to create another view that is the full size of the content. You can add this view off screen and then capture it the same way as you have done here. The reason it is cut off is because the view has only rendered that part of the content.
Currently i am making "traditional" screenshots and combine them using a graphics editor to show the full webpage at once. Is there any more efficient way of making screenshots of a full webpage, just as by using Awesome Screenshot for Google Chrome?
(No, i do not have an iPhone ;)
You have to write it on your own.
Create a fullscreen webView inside your app.
Open page you want to open
Manipulate the property webView.scrollView to move successfully to the bottom of the page.
Capture screenshot every time
If you're on the bottom merge screenshots to one large images.
I believe this is a simplest way and run on the simulator.
See the code below.
-(NSData *)getImageFromView:(UIView *)view // Mine is UIWebView but should work for any
{
NSData *pngImg;
CGFloat max, scale = 1.0;
CGSize viewSize = [view bounds].size;
// Get the size of the the FULL Content, not just the bit that is visible
CGSize size = [view sizeThatFits:CGSizeZero];
// Scale down if on iPad to something more reasonable
max = (viewSize.width > viewSize.height) ? viewSize.width : viewSize.height;
if( max > 960 )
scale = 960/max;
UIGraphicsBeginImageContextWithOptions( size, YES, scale );
// Set the view to the FULL size of the content.
[view setFrame: CGRectMake(0, 0, size.width, size.height)];
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
pngImg = UIImagePNGRepresentation( UIGraphicsGetImageFromCurrentImageContext() );
UIGraphicsEndImageContext();
return pngImg; // Voila an image of the ENTIRE CONTENT, not just visible bit
}
I got this code from this link. Hope it will help you.