Taking a screenShot of view inside a cell in ios - ios

I am trying to take a screen shot of view inside a cell of UITableView but with attached code I can able only to take a screenshot of cell bounds. The problem is that by UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f). I can only make screenshot of rect size and cannot control origin of rect and
rect = [cell bounds]. so please suggest me some idea.
{
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:path];
__block CGRect rect = [cell bounds];
UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[cell.layer renderInContext:context];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}

Take the screenShot as a normal screenShot and then crop it
-(UIImage *)cropImage:(UIImage *)image rect:(CGRect)cropRect
{
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
UIImage *img = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return img;
}
Use like this:
UIImage *img = [self cropImage:viewImage rect:CGRectMake(150,150,100,100)];
To get the frame of a particular tableView Cell. Use this:
CGRect myRect = [tableView rectForRowAtIndexPath:0];//example 0,1,indexPath
Hope this helps. Refer to this link link2

- (UIImage *) screenshot {
CGSize size = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
CGRect rec = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); //set the frame
[self.view drawViewHierarchyInRect:rec afterScreenUpdates:YES];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

Related

WKWebView save to UIImage

I use the code below to save WKWebView into UIImage. But the problem is, more than 50% of the UIImage is blank/white space.
- (UIImage *)screenCapture {
UIImage *image;
UIGraphicsBeginImageContextWithOptions(self.scrollView.contentSize, TRUE, 0.0f);
{
CGPoint savedContentOffset = self.scrollView.contentOffset;
CGRect savedFrame = self.scrollView.frame;
self.scrollView.contentOffset = CGPointZero;
self.scrollView.frame = CGRectMake(0, 0, self.scrollView.contentSize.width, self.scrollView.contentSize.height);
[self.scrollView drawViewHierarchyInRect:self.scrollView.bounds afterScreenUpdates:YES];
image = UIGraphicsGetImageFromCurrentImageContext();
self.scrollView.contentOffset = savedContentOffset;
self.scrollView.frame = savedFrame;
}
UIGraphicsEndImageContext();
return image;
}
Does anyone have encountered the same problem? Any ideas for a workaround here?
I've also tried this: [self.scrollView.layer renderInContext:UIGraphicsGetCurrentContext()]; but it is much worse, the UIImage is just plain white.
UPDATE:
Here's my sample captured UIImage.
Captured UIImage
Try this:
UIGraphicsBeginImageContext(scrollView.frame.size);
[scrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Now you have the image of the scrollview in viewImage.

Take snap shot - only part of UIView, not the whole frame

I can take snapshots of the whole frame of the UIView with no problem.
Taking part of it cause to a squeezed image.
This is my UIView category method:
- (UIImage *)snapshot:(CGRect)frame
{
UIGraphicsBeginImageContextWithOptions(frame.size, YES, [[UIScreen mainScreen] scale]);
[self drawViewHierarchyInRect:frame afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
And this is the call to this method:
UIImage *img = [self.view snapshot:bottomRectToSnap];
When bottomRectToSnap is a partial frame of the view.
Note:The UIView contains UITableView if that matter.
The code you are applying is fine.
Need to add some logic, whatever part you need to take snap, It should be available on screen and hide rest of part while snapping.
Once snap shot done, remove hide code. So it will not effect to view interface too.
Use the following code.
- (void)captureView:(UIView*)view withFrame:(CGRect)frame{
UIGraphicsBeginImageContext(self.view.bounds.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect rect = frame;
CGImageRef imageRef = CGImageCreateWithImageInRect([viewImage CGImage], rect);
UIImage *img = [UIImage imageWithCGImage:imageRef];
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
CGImageRelease(imageRef);
}
You can add this code to take the snapshot of particular part..
CGRect cropRect=CGRectMake(0, 0, 100, 100);
CGImageRef imageRef = CGImageCreateWithImageInRect([_galleryimageview.image CGImage], cropRect);
UIImage *cropedImage=[UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
This code crop the part of particular image ...Hope this is helpfull for you..

Stretched UIView background gets cut off during screenshot

So, I am taking a screenshot of a subclassed UIView that I save into the device's photo stream.
Problem:
The problem is that I use resizableImageWithCapInsets to add a stretched background to my UIView, but this background gets cut off on the right side and I have no idea why. If someone could help me out it would be highly appreciated.
I add the stretched background to my UIView the following way:
[diagramBase addSubview:[self addTileBackgroundOfSize:diagramBase.frame
andType:#"ipad_diagram_border.png"]];
Which calls this method:
- (UIImageView *) addTileBackgroundOfSize:(CGRect)frame
andType:(NSString *)type
{
frame.origin.x = 0.0f;
frame.origin.y = 0.0f;
UIImageView *backgroundView = [[UIImageView alloc] initWithFrame:frame];
UIImage *image = [UIImage imageNamed:type];
UIEdgeInsets insets = UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f);
UIImage *backgroundImage = [image resizableImageWithCapInsets:insets];
backgroundView.image = backgroundImage;
return backgroundView;
}
The actual printscreen is done with this method (RINDiagramView is the name of my subclassed UIView, which I am taking a screenshot of). The rotation is in there because I need the image rotated when I save it, but I commented out that part and that is not what does the background to act weird.
- (UIImage *) createSnapshotOfView:(RINDiagram *) view
{
CGRect rect = [view bounds];
rect.size.height = rect.size.height - 81.0f;
UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImage *finalImage = [[UIImage alloc] initWithCGImage: capturedScreen.CGImage
scale: 1.0
orientation: UIImageOrientationLeft];
return finalImage;
}
I use Xcode 5.1 and everything is done programmatically (no storyboard and such). The base SDK is iOS 7.1.
If you're doing iOS 7+ you can use the new drawViewHierarchyInRect:afterScreenUpdates: and related methods which Apple says are really performant.
Even if you're targeting iOS 6 you should give it a try to see if you get the same problem.
Try using the correct scale?
UIImage *finalImage = [[UIImage alloc] initWithCGImage: capturedScreen.CGImage
scale: [[UIScreen mainScreen] scale]
orientation: UIImageOrientationLeft];
Use a different UIViewContentMode?
UIViewContentModeScaleToFill -> check if you can see the edges
UIViewContentModeScaleAspectFit -> check if you can see the edges, even if position is incorrect
UIViewContentModeScaleAspectFill -> check for edge right side
The reason you got a right-side cut image is caused by this line
UIImage *finalImage = [[UIImage alloc] initWithCGImage: capturedScreen.CGImage
scale: 1.0
orientation: UIImageOrientationLeft];
You made the image orientation to left, the context will thought the left-side is your top-side.And your size has a minus to the height value, so the result turns to the right-side is cut.
About the rotation, I added some code into your code.Hopes it is helpful.
- (UIImage *) createSnapshotOfView:(UIView *) view
{
CGRect rect = [view bounds];
rect.size.height = rect.size.height - 81.0f;
UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
view.transform = CGAffineTransformMakeRotation(M_PI_2);
[view.layer renderInContext:context];
UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImage *finalImage = [[UIImage alloc] initWithCGImage: capturedScreen.CGImage
scale: 1.0
orientation: UIImageOrientationLeft];
view.transform = CGAffineTransformMakeRotation(0);
return finalImage;
}
UIGraphicsBeginImageContext(self.window.bounds.size);
[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:#"foo.png" atomically:YES];
for retina display, change the first line into this:
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(self.window.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(self.window.bounds.size);
adjust your size, may you get help..

Can't get the screenshot of fullscreen in ios

This is my code..
extern CGImageRef UIGetScreenImage();
CGRect frame = CGRectMake(0, 0, 320, 548);
CGImageRef cgoriginal = UIGetScreenImage();
CGImageRef cgimg = CGImageCreateWithImageInRect(cgoriginal, frame);
UIImage *viewImage = [UIImage imageWithCGImage:cgimg];
CGImageRelease(cgoriginal);
CGImageRelease(cgimg);
It takes screen shot but not full screen. I know this problem in CGRect frame. But I don't know, how to fix that..
Pay attention that UIGetScreenImage is a private API, so it will be rejected. If you want to do something similar you can try to use -renderInContext on the window layer or -drawViewHierchyInRect(only ios7).
This method should be used as a category on UIView:
- (UIImage *) imageByRenderingViewOpaque:(BOOL) yesOrNO {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, yesOrNO, 0);
if ([self respondsToSelector:#selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
}
else {
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
}
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
You have also this method that you can call on UIScree instance - (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates, but that will return only a view not an image.

Snapshot of View Doesn't Render

I'm trying to get a snapshot of another controller's view to use in an animation. I'm using the following code, but I see nothing but the background color of that view, and none of its subviews (two buttons, a text view, and a label):
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
FirstPageController *fpController = [self.storyboard instantiateViewControllerWithIdentifier:#"FirstPage"];
UIGraphicsBeginImageContext(fpController.view.bounds.size);
NSLog(#"%#",fpController.view.subviews);
[fpController.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGSize destinationSize = CGSizeMake(90, 122);
UIGraphicsBeginImageContext(destinationSize);
[viewImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.imageView2 = [[UIImageView alloc] initWithImage:newImage];
self.imageView2.center = self.view.center;
[self.view addSubview:self.imageView2];
NSLog(#"%#",NSStringFromCGSize(self.imageView2.image.size));
}
I've logged all the relevant things, the fpController, the imageView, the image, and all are logging correctly.
After Edit: If I switch to the current controller's view, it works fine, so I'm thinking that this has to do with getting a snapshot of a view that's not on screen. Can that be done?
Hope this will help you:
CGSize textcontent =CGSizeMake(width, height);
UIGraphicsBeginImageContext(textcontent);
if ([UIScreen instancesRespondToSelector:#selector(scale)] && [[UIScreen mainScreen] scale] == 2.0f)
{
UIGraphicsBeginImageContextWithOptions(textcontent, YES, 1.0f);
}
else
{
UIGraphicsBeginImageContext(textcontent);
}
[image.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
UIGraphicsBeginImageContextWithOptions(fpController.view.bounds.size, NO, 0.0);
UIGraphicsBeginImageContextWithOptions(destinationSize, NO, 0.0);
Use this two lines instead of UIGraphicsBeginImageContext(fpController.view.bounds.size);
UIGraphicsBeginImageContext(destinationSize); respectively
hope it help's you
I found one way to make this work, though it seems like a hack. I add the view I want to render as a subview of my view, do the rendering, and then remove the view. It is never seen on screen, so visually, it's fine. I just wonder whether there's a better way.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.fpController = [self.storyboard instantiateViewControllerWithIdentifier:#"FirstPage"];
[self.view insertSubview:self.fpController.view belowSubview:self.view];
UIGraphicsBeginImageContext(self.fpController.view.bounds.size);
[self.fpController.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.fpController.view removeFromSuperview];
self.imageView2 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 90, 122)];
self.imageView2.image = viewImage;
[self.pageView insertSubview:self.imageView2 belowSubview:self.imageView];
}

Resources