Although I resize my images once the UIImagePickerController has finished taking a photo, my instruments profile says that calls to ImageIO_PNG are taking massive amounts of memory (40 MB+) each time I take a photo. This is my code:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
#autoreleasepool {
if (myImageView.image == nil) {
myImageView.contentMode = UIViewContentModeScaleAspectFill;
UIImage *topImage = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
CGRect rect = CGRectMake(0,0,320,440);
UIGraphicsBeginImageContext( rect.size );
// use the local image variable to draw in context
[topImage drawInRect:rect];
UIImage *topResized = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
myImageView.image = topResized;
image = nil;
info = nil;
[picker dismissViewControllerAnimated:NO completion:nil];
[picker removeFromParentViewController];
remove below line from your code that might help:
image = nil;
info = nil;
Related
When I take a photo from UIImagePickerController, the camera focuses, and when a picture is taken, it is immediately very blurry. Is there a way to change the statements used in the method in order to produce a sharper image?
#pragma mark - Image picker delegate methods
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
// Resize the image from the camera
UIImage *scaledImage = [image resizedImageWithContentMode:UIViewContentModeScaleAspectFill bounds:CGSizeMake(photo.frame.size.width, photo.frame.size.height) interpolationQuality:kCGInterpolationHigh];
// Crop the image to a square
UIImage *croppedImage = [scaledImage croppedImage:CGRectMake((scaledImage.size.width -photo.frame.size.width)/2, (scaledImage.size.height -photo.frame.size.height)/2, photo.frame.size.width, photo.frame.size.height)];
// Show the photo on the screen
photo.image = croppedImage;
[picker dismissModalViewControllerAnimated:NO];
photo.transform=CGAffineTransformMakeRotation(M_PI*0.5);
}
how to crop image from UIImagePickerController in selected area when capturing image. overlayview to UIImagePickerController
Below the Code
-(UIImage *)centerCropImage:(UIImage *)image
{
// Use smallest side length as crop square length
CGFloat squareLength = MIN(image.size.width, image.size.height);
// Center the crop area
CGRect clippedRect = CGRectMake((image.size.width - squareLength) / 2, (image.size.height - squareLength) / 2, squareLength, squareLength);
// Crop logic
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], clippedRect);
UIImage * croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}
After that in imagePickerViewDelegate Method
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey: #"UIImagePickerControllerOriginalImage"];
[self centerCropImage:image]; //Just give your image here for cropping
yourImage.image=image;
picker.delegate =self;
[picker dismissViewControllerAnimated:YES completion:nil];
}
WorkGround
I have an image (.JPG format) of size of 53kb in simulator.
Now I am selecting this image using UIImagePickerController and save it to local.
Code for selecting image and storing it local is below:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
NSString *mediaType = info[UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
// Media is an image
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
if (image) {
NSData *jpegData = UIImageJPEGRepresentation(image, 1);
// Store image.
BOOL isImageSave = [jpegData writeToFile:filePath atomically:NO];
if (isImageSave) {
DLog(#"Image saved");
} else {
DLog(#"Error");
}
}
}
[self.view dismissViewControllerAnimated:YES completion:nil];
}
Problem:
Here original image is of 53kb but when i select this image the image size will increase and store image is of size 142kb. Here i used compression to reduce size. But i check twice that in UIImagePickerController delegate method it returns bigger size image.
Does any one have idea, Why it select bigger image. Is there any way to get original size image in terms of size?
You can resize to image view in particular frame. using below code
- (UIImage*)imageWithImage:(UIImage*)image
scaledToSize:(CGSize)newSize;
{
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Then call this method as :
UIImage *myIcon = [self imageWithImage:myUIImageInstance scaledToSize:CGSizeMake(20, 20)];
As far as storage of the image, the fastest image format to use with the iPhone is PNG, because it has optimizations for that format. However, if you want to store these images as JPEGs, you can take your UIImage and do the following:
NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);
You're using a JPEG encoding quality of 1 which corresponds to 100% quality. Try using a setting of 0.2-0.8 when you perform the JPEG encoding and check the file size then.
I load an image from the camera roll and send it to a function which returns a section of the original image based on a rectangle I create. I can then add this to the scene with no issues.
The problem occurs when I want to load another section of the original image. I want to create 2 sprites, each with different sections of the original image, like a jigsaw, but when I send the original image and a different rectangle, I get the same image as the first time and have two images the same added to the scene.
Any ideas would be appreciated?
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// newImage is a UIImage do not try to use a UIImageView
UIImage *newImage = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
UIImage *newImage2 = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
//newImage2 = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
// Dismiss UIImagePickerController and release it
[picker dismissModalViewControllerAnimated:YES];
[picker.view removeFromSuperview];
[picker release];
CGRect newRect = CGRectMake(0, 0, 320, 460);
CGRect newRect2 = CGRectMake(600, 600, 100, 100);
UIImage *testImage = [self imageFromImage:newImage inRect:newRect];
UIImage *testImage2 = [self imageFromImage:newImage2 inRect:newRect2];
CCSprite *scaledImage = [CCSprite spriteWithCGImage:testImage.CGImage key:#"ImageFromPicker"];
scaledImage.position = ccp(s.width/2, s.height/2);
[self addChild:scaledImage];
CCSprite *scaledImage2 = [CCSprite spriteWithFile:#"play.png"];//[CCSprite spriteWithCGImage:testImage2.CGImage key:#"ImageFromPicker"];
scaledImage2.position = ccp(560,40);
[self addChild:scaledImage2];
}
And the method that crops the image:
- (UIImage *)imageFromImage:(UIImage *)image inRect:(CGRect)rect
{
CGImageRef sourceImageRef = [image CGImage];
CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);
UIImage *tempImage = [UIImage imageWithCGImage:newImageRef];
return tempImage;
}
Thanks to LearnCocos, you were spot on with your answer. Created 2 separate textures from different part of the larger image and could then add them separately.
EDIT 1: This problem specially happens on iOS7.
I'm trying to crop an image that was already taken by the UIImagePickerController using some Core Graphics methods inside the imagePickerController method:
- (void)imagePickerController:(UIImagePickerController *)photoPicker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
if(modeSelected == kModeTypeAutomatic){
//cropping image
if(image.imageOrientation == UIImageOrientationUp){
CGImageRef tmpImgRef = [image CGImage];
CGImageRef topImgRef = CGImageCreateWithImageInRect(tmpImgRef, CGRectMake(image.size.width/2, 0, image.size.width/2, image.size.height));
secondImage = [UIImage imageWithCGImage:topImgRef];
CGImageRelease(topImgRef);
}
else{
CGImageRef tmpImgRef = [image CGImage];
CGImageRef topImgRef = CGImageCreateWithImageInRect(tmpImgRef, CGRectMake(0, 0, image.size.width, image.size.height/2.0));
secondImage = [UIImage imageWithCGImage:topImgRef scale:image.scale orientation:UIImageOrientationRight];
CGImageRelease(topImgRef);
}
}
image = nil;
[photoPicker dismissViewControllerAnimated:NO completion:nil];
if (secondImage) {
[self performSegueWithIdentifier:#"SecondPicTakenSegue" sender:nil];
}
}
I made some allocations and memory leaks using Instrument, and I verified that the problem is inside this method.
Am I not releasing something here? Is something missing?
Thanks!
Hard to tell from that code snippet, but secondImage could be what's being leaked. No harm in explicitly setting it to nil in your dealloc method to see if that helps:
-(void)dealloc {
secondImage = nil;
}
This may be your issue (from the CGImage reference, under CGImageCreateWithImageInRect):
The resulting image retains a reference to the original image, which means you may release the original image after calling this function.
https://developer.apple.com/library/ios/documentation/graphicsimaging/reference/CGImage/Reference/reference.html#jumpTo_6
So you may want to try a CGImageRelease(tmpImgRef) since it sounds like you may be incrementing the reference count with that call to CGImageCreateWithImageInRect. I haven't tested this myself to ensure that this is the case, but perhaps worth a shot.