Low memory waning while taking screenshot of a view in iPhone - iphone

I am having an app in which I am taking a screenshot of a view and saving that image on documents folder.
I am using the following code.
CGSize size = self.view.bounds.size;
CGRect cropRect;
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if([self isPad])
{
cropRect = CGRectMake(145, 110, 476, 476);
}
else
{
if (screenBounds.size.height ==568)
{
cropRect = CGRectMake(40, 69, 240, 240);
}
else
{
cropRect = CGRectMake(40, 62, 240, 240);
}
}
/* Get the entire on screen map as Image */
UIGraphicsBeginImageContext(size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * mapImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
/* Crop the desired region */
CGImageRef imageRef = CGImageCreateWithImageInRect(mapImage.CGImage, cropRect);
UIImage * cropImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
/* Save the cropped image
UIImageWriteToSavedPhotosAlbum(cropImage, nil, nil, nil);*/
//save to document folder
NSData * imageData = UIImageJPEGRepresentation(cropImage, 1.0);
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
imagename=[NSString stringWithFormat:#"Fff.jpg"];
NSString* fullPathToFile = [documentsDirectory stringByAppendingPathComponent:imagename];
////NSLog(#"full path %#",fullPathToFile);
[imageData writeToFile:fullPathToFile atomically:NO];
It works fine if I take the screenshot 15 to 20 times but after that It gives me low memory warning and the app crashes after that on this code.
Is there a more optimized code that I can use which does not cause such memory problems.
Please help me.

Capture screen with my bellow method..
- (UIImage *)captureView {
//hide controls if needed
CGRect rect = [self.view bounds];// Here define CGRect with your requirement of take screenshot of some part
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.view.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
See my another answer howe-to-capture-uiview-top-uiview

Related

Issue with attaching an Image file with mail

I am trying to capture a view as an image and then attach that image through mail , but the problem is after capturing the view a white border appears around the image ! , this problem happens only on iPhone 5 device ! here is my code :
Sharing.m
- (void)mailAttachmentWithImage:(UIView*)view openInView:(UIViewController*)viewCont {
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
UIView* captureView = view;
captureView.backgroundColor = [UIColor clearColor];
/* Capture the screen shoot at native resolution */
UIGraphicsBeginImageContextWithOptions(captureView.bounds.size, NO, 0.0);
[captureView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
/* Render the screen shot at custom resolution */
CGRect cropRect = CGRectMake(0 ,0 ,1024 ,1024);
UIGraphicsBeginImageContextWithOptions(cropRect.size, NO, 1.0f);
[screenshot drawInRect:cropRect];
UIImage * customScreenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *myData = UIImagePNGRepresentation(customScreenShot);
[controller addAttachmentData:myData mimeType:#"image/png" fileName:#"Image"];
[viewCont presentViewController:controller animated:YES completion:nil];
}
ViewController.m
and then capture view :
- (IBAction)mail:(id)sender {
[shareIt mailAttachmentWithImage:_captureView openInView:self];
}
you need to capture image of Image-view instead of UIView. your posted answer is not enough to help's Other. as my bellow code you can capture image of your Image-view Frame try with Bellow code:-
-(void)imageWithView:(UIView *)view
{
CGRect rect = CGRectMake(imgview.frame.origin.x, imgview.frame.origin.y,imgview.frame.size.width, imgview.frame.size.height);
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, YES, 1.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
// CGRect rect = CGRectMake(0,0,10,10);
CGImageRef imageRef = CGImageCreateWithImageInRect([screenshot CGImage], rect);
UIImage *croppedScreenshot = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.png"];
NSData *imageData = UIImagePNGRepresentation(croppedScreenshot);
[controller addAttachmentData:imageData mimeType:#"image/png" fileName:#"Image"];
[viewCont presentViewController:controller animated:YES completion:nil];
}
So this Captured image not contain Border and you can attach this image Without Border in to E-mail.
Problem Solved ! because my View was bigger than targeted image size !!!!

Printing and saving a web page Using iPhone

I want my WebView to save as image or pdf of any formate,
I tried with saving the web page using the code :
UIGraphicsBeginImageContext(WebPage.frame.size);
[WebPage.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
but i'm getting the part which is visible..
i want to know how to get the entire web page image or how the apple people giving the air print so that the entire web page can b printed.. i dont want to know the "AirPrint function" i want to know how to get web page image using the iPhone..
As i'm fresher to iOS development.
can any one help me with he working code of saving web page?
- (void)printAndSave
{
webViewHeight = [[self.myWebView stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight;"] integerValue];
CGRect screenRect = self.myWebView.frame;
double currentWebViewHeight = webViewHeight;
while (currentWebViewHeight > 0)
{
imageName ++;
UIGraphicsBeginImageContext(screenRect.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextFillRect(ctx, screenRect);
[self.myWebView.layer renderInContext:ctx];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pngPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%d.png",imageName]];
if(currentWebViewHeight < 460)
{
CGRect lastImageRect = CGRectMake(0, 457 - currentWebViewHeight, self.myWebView.frame.size.width, currentWebViewHeight);
CGImageRef lastImageRef = CGImageCreateWithImageInRect([newImage CGImage], lastImageRect);
newImage = [UIImage imageWithCGImage:lastImageRef];
CGImageRelease(lastImageRef);
}
[UIImagePNGRepresentation(newImage) writeToFile:pngPath atomically:YES];
[self.myWebView stringByEvaluatingJavaScriptFromString:#"window.scrollBy(0,460);"];
currentWebViewHeight -= 460;
}
}
- (IBAction)printSaveTheWebView:(id)sender
{
UIImage *viewImage;
UIScrollView *Scroll_view = webView.scrollView;
CGRect savedFrame;
UIGraphicsBeginImageContext(Scroll_view.contentSize);
{
CGPoint savedContentOffset = Scroll_view.contentOffset;
savedFrame = Scroll_view.frame;
Scroll_view.contentOffset = CGPointZero;
Scroll_view.frame = CGRectMake(0, 0, Scroll_view.contentSize.width, Scroll_view.contentSize.height);
[Scroll_view.layer renderInContext: UIGraphicsGetCurrentContext()];
viewImage = UIGraphicsGetImageFromCurrentImageContext();
Scroll_view.contentOffset = savedContentOffset;
Scroll_view.frame = savedFrame;
}
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, self, nil, nil);
[UIImagePNGRepresentation(viewImage) writeToFile:[NSHomeDirectory() stringByAppendingPathComponent:#"view.png"] atomically:YES];
}
Call this method when you click your button
For getting your reqirement you have to change the context of the webview by changing the frame ,for that take one for loop and loop it according to the number of pages by changing the contex.
once check this one

Take screenshot from UIVIEW+ipad

I want to take the screenhot of viewcontroller
I had write this:-
- (UIImage *)captureScreenInRectWOScroll:(CGRect)captureFrame {
CALayer *layer;
layer = self.view.layer;
UIGraphicsBeginImageContext(captureFrame.size);
CGContextClipToRect (UIGraphicsGetCurrentContext(),captureFrame);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return screenImage;
}
The way i am calling this method:-
UIImage *img_woscroll1 =[self captureScreenInRectWOScroll:CGRectMake(35,147,497,260)];
I wann to take screenshot of Address from below attached image:-
When i am taking hte screenshot from the above code i Got the image with lot of blank space(greencolor image at top) at top side if image:-
Please help me..How to take proper screenshot from image such that i will not get blank image on topside.
Try This
UIGraphicsBeginImageContext(myView.frame.size);
[myView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *data=UIImagePNGRepresentation(viewImage);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *strPath = [documentsDirectory stringByAppendingPathComponent:#"myimage.png"];
[data writeToFile:strPath atomically:YES];
Try This:-
CGRect screenRect = CGRectMake(0, 90, 320,460);
UIGraphicsBeginImageContext(screenRect.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextFillRect(ctx, screenRect);
//you probably need an offset, adjust here
CGContextTranslateCTM(ctx, -20, -20);
[self.view.layer renderInContext:ctx];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
It may help you. Thanks :)
Try with this. This may help you.
- (UIImage *)captureView:(UIView *)view {
CGRect screenRect = [[UIScreen mainScreen] bounds];
UIGraphicsBeginImageContext(screenRect.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextFillRect(ctx, screenRect);
[view.layer renderInContext:ctx];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

Taking a picture from the camera and show it in a UIImageView

I have a view with some fields (name, price, category) and a segmented control, plus this button to take picture.
If I try this on the simulator (no camera) it works properly: I can select the image from the camera roll, edit it and go back to the view, which will show all the fields with their contents .
But on my iphone, when I select the image after the editing and go back to the view, all the fields are empty exept for the UIImageView.I also tried to save the content of the fields in variables and put them back in the "viewWillApper" method, but the app crashes.
Start to thinking that maybe there is something wrong methods below
EDIT
I found the solution here. I defined a new method to the UIImage class. (follow the link for more information).Then I worked on the frame of the UIImageView to adapt itself to the new dimension, in landscape or portrait.
-(IBAction)takePhoto:(id)sender {
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
self.imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.imgPicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
} else {
imgPicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
}
[self presentModalViewController:self.imgPicker animated:YES];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissModalViewControllerAnimated:YES];
NSDate *date = [NSDate date];
NSString *photoName = [dateFormatter stringFromDate:date];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUs erDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
imagePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png", photoName]];
UIImage *picture = [info objectForKey:UIImagePickerControllerOriginalImage];
// ---------RESIZE CODE--------- //
if (picture.size.width == 1936) {
picture = [picture scaleToSize:CGSizeMake(480.0f, 720.0f)];
} else {
picture = [picture scaleToSize:CGSizeMake(720.0f, 480.0f)];
}
// --------END RESIZE CODE-------- //
photoPreview.image = picture;
// ---------FRAME CODE--------- //
photoPreview.contentMode = UIViewContentModeScaleAspectFit;
CGRect frame = photoPreview.frame;
if (picture.size.width == 480) {
frame.size.width = 111.3;
frame.size.height =167;
} else {
frame.size.width = 167;
frame.size.height =111.3;
}
photoPreview.frame = frame;
// --------END FRAME CODE-------- //
NSData *webData = UIImagePNGRepresentation(picture);
CGImageRelease([picture CGImage]);
[webData writeToFile:imagePath atomically:YES];
imgPicker = nil;
}
Now I have a new issue! If I take a picture in landscape, and try to take another one in portrait, the app crashs. Do I have to release something?
I had the same issue, there is no edited image when using the camera, you must use the original image :
originalimage = [editingInfo objectForKey:UIImagePickerControllerOriginalImage];
if ([editingInfo objectForKey:UIImagePickerControllerMediaMetadata]) {
// test to chek that the camera was used
// especially I fund out htat you then have to rotate the photo
...
If it was cropped when usign the album you have to re-crop it of course :
if ([editingInfo objectForKey:UIImagePickerControllerCropRect] != nil) {
CGRect cropRect = [[editingInfo objectForKey:UIImagePickerControllerCropRect] CGRectValue];
CGImageRef imageRef = CGImageCreateWithImageInRect([originalimage CGImage], cropRect);
chosenimage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
} else {
chosenimage = originalimage;
}
The croprect info is also present for the camera mode, you need to check how you want it to behave.
To Crop image i think this may help you
UIImage *croppedImage = [self imageByCropping:photo.image toRect:tempview.frame];
CGSize size = CGSizeMake(croppedImage.size.height, croppedImage.size.width);
UIGraphicsBeginImageContext(size);
CGPoint pointImg1 = CGPointMake(0,0);
[croppedImage drawAtPoint:pointImg1 ];
[[UIImage imageNamed:appDelegete.strImage] drawInRect:CGRectMake(0,532, 150,80) ];
UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
croppedImage = result;
UIImageView *mainImageView = [[UIImageView alloc] initWithImage:croppedImage];
CGRect clippedRect = CGRectMake(0, 0, croppedImage.size.width, croppedImage.size.height);
CGFloat scaleFactor = 0.5;
UIGraphicsBeginImageContext(CGSizeMake(croppedImage.size.width * scaleFactor, croppedImage.size.height * scaleFactor));
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextClipToRect(currentContext, clippedRect);
//this will automatically scale any CGImage down/up to the required thumbnail side (length) when the CGImage gets drawn into the context on the next line of code
CGContextScaleCTM(currentContext, scaleFactor, scaleFactor);
[mainImageView.layer renderInContext:currentContext];
appDelegete.appphoto = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Capturing Screen

I am trying to capture (screen shot) a view. For that I am using a piece of code shown below that saves it to my document directory as a PNG image.
UIGraphicsBeginImageContextWithOptions(highlightViewController.fhView.centerView.frame.size, YES, 1.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"1.png"];
NSData *imageData = UIImagePNGRepresentation(screenshot);
[imageData writeToFile:appFile atomically:YES];
UIGraphicsEndImageContext();
Question: can I capture part of the view? Because in the above code I can't change the origin (frame). If anyone has other approach to capture a particular part of view please share it.
You could crop the image:
http://iosdevelopertips.com/graphics/how-to-crop-an-image.html
CGRect rect = CGRectMake(0,0,10,10);
CGImageRef imageRef = CGImageCreateWithImageInRect([screenshot CGImage], rect);
UIImage *croppedScreenshot = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
Try this code. This surely works as I have implemented it in many of my projects:
- (UIImage *)image
{
if (cachedImage == nil) {
//YOU CAN CHANGE THE FRAME HERE TO WHATEVER YOU WANT TO CAPTURE
CGRect imageFrame = CGRectMake(0, 0, 400, 300);
UIView *imageView = [[UIView alloc] initWithFrame:imageFrame];
[imageView setOpaque:YES];
[imageView setUserInteractionEnabled:NO];
[self renderInView:imageView withTheme:nil];
UIGraphicsBeginImageContext(imageView.bounds.size);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextGetCTM(c);
CGContextScaleCTM(c, 1, -1);
CGContextTranslateCTM(c, 0, -imageView.bounds.size.height);
[imageView.layer renderInContext:c];
cachedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
// rescale graph
UIImage* bigImage = UIGraphicsGetImageFromCurrentImageContext();
CGImageRef scaledImage = [self newCGImageFromImage:[bigImage CGImage] scaledToSize:CGSizeMake(100.0f, 75.0f)];
cachedImage = [[UIImage imageWithCGImage:scaledImage] retain];
CGImageRelease(scaledImage);
UIGraphicsEndImageContext();
[imageView release];
}
return cachedImage;
}
I hope this will help you.
See if you can specify the rect like this and then take screenshot.
CGRect requiredRect = CGRectMake(urView.frame.origin.x, urView.frame.origin.y, urView.bounds.size.width, urView.bounds.size.height);
UIGraphicsBeginImageContext(requiredRect.size);
You can alter the origin and see if it works.
If this doesn't work out, you can try cropping the image as mentioned by #mcb
You can use this code
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect rect;
rect = CGRectMake(250,61 ,410, 255);
CGImageRef imageRef = CGImageCreateWithImageInRect([viewImage CGImage], rect);
UIImage *img = [UIImage imageWithCGImage:imageRef];
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
CGImageRelease(imageRef);