I would like to try some image filter features on iPhone like instagram does.
I use imagePickerController to get photo from camera roll. I understand that the image return by imagePickerController was reduced to save memory. And it’s not wise to load the original image to an UIImage. But how can I processe the image then save it back as the original pixels?
I use iPhone 4S as my development device.
The original photo in camera roll is 3264 * 2448.
The image return by UIImagePickerControllerOriginalImage is 1920 * 1440
The image return by UIImagePickerControllerEditedImage is 640 * 640
imageViewOld(use UIImagePickerControllerCropRect [80,216,1280,1280] to crop the image return by UIImagePickerControllerOriginalImage) is 1280 * 1224
imageViewNew(use double sized UIImagePickerControllerCropRect [80,216,2560,2560] to crop the image return by UIImagePickerControllerOriginalImage) is 1840 * 1224.
I check the same photo proceed by instagram is 1280 * 1280
My questions are:
- Why UIImagePickerControllerOriginalImage does not return the “Original” photo? Why reduced it to 1920 * 1440?
-
Why UIImagePickerControllerEditedImage does not return the image by 1280 * 1280? As the
UIImagePickerControllerCropRect shows it is cut by 1280 * 1280 square? -
How can I do a square cut to original photo to be a 2448 * 2448 image?
Thanks in advance.
Below is my code:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:@"public.image"])
{
UIImage *imageEdited = [info objectForKey:UIImagePickerControllerEditedImage];
UIImage *imagePicked = [info objectForKey:UIImagePickerControllerOriginalImage];
CGRect cropRect;
cropRect = [[info valueForKey:@"UIImagePickerControllerCropRect"] CGRectValue];
NSLog(@"Original width = %f height= %f ",imagePicked.size.width, imagePicked.size.height);
//Original width = 1440.000000 height= 1920.000000
NSLog(@"imageEdited width = %f height = %f",imageEdited.size.width, imageEdited.size.height);
//imageEdited width = 640.000000 height = 640.000000
NSLog(@"corpRect %f %f %f %f", cropRect.origin.x, cropRect.origin.y , cropRect.size.width, cropRect.size.height);
//corpRect 80.000000 216.000000 1280.000000 1280.000000
CGRect rectNew = CGRectMake(cropRect.origin.x, cropRect.origin.y , cropRect.size.width*2, cropRect.size.height*2);
CGRect rectOld = CGRectMake(cropRect.origin.x, cropRect.origin.y , cropRect.size.width, cropRect.size.height);
CGImageRef imageRefNew = CGImageCreateWithImageInRect([imagePicked CGImage], rectNew);
CGImageRef imageRefOld = CGImageCreateWithImageInRect([imagePicked CGImage], rectOld);
UIImageView *imageViewNew = [[UIImageView alloc] initWithImage:[UIImage imageWithCGImage:imageRefNew]];
CGImageRelease(imageRefNew);
UIImageView *imageViewOld = [[UIImageView alloc] initWithImage:[UIImage imageWithCGImage:imageRefOld]];
CGImageRelease(imageRefOld);
NSLog(@"imageViewNew width = %f height = %f",imageViewNew.image.size.width, imageViewNew.image.size.height);
//imageViewNew width = 1840.000000 height = 1224.000000
NSLog(@"imageViewOld width = %f height = %f",imageViewOld.image.size.width, imageViewOld.image.size.height);
//imageViewOld width = 1280.000000 height = 1224.000000
UIImageWriteToSavedPhotosAlbum(imageEdited, nil, nil, NULL);
UIImageWriteToSavedPhotosAlbum([imageViewNew.image imageRotatedByDegrees:90.0], nil, nil, NULL);
UIImageWriteToSavedPhotosAlbum([imageViewOld.image imageRotatedByDegrees:90.0], nil, nil, NULL);
//assign the image to an UIImage Control
self.imageV.contentMode = UIViewContentModeScaleAspectFit;
self.imageV.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.width);
self.imageV.image = imageEdited;
}
[self dismissModalViewControllerAnimated:YES];
}
As you have observed the UIImagePickerController will return a scaled down edited image sometimes 640×640 sometimes 320×320 (device dependent).
Your question:
To do this you need to first use the
UIImagePickerControllerCropRectto create a new image from the original image obtained using theUIImagePickerControllerOriginalImagekey of the info dictionary. Using the Quartz Core method,CGImageCreateWithImageInRectyou can create a new image that only contains the pixels bounded by the passed rect; in this case the crop rect. You will need to take into account orientation in order for this to work properly. Then you need only scale the image to your desired size. It’s important to note that the crop rect is relative to the original image when after it has been oriented correctly, not as it comes out of the camera or photo library. This is why we need to transform the crop rect to match the orientation when we start using Quartz methods to create new images, etc.I took your code above and set it up to create a 1280×1280 image from the original image based on the crop rect. There are still some edge cases here, i.e. taking into account that the crop rect can sometimes have negative values, (the code assumes a square cropping rect) that have not been addressed.
transformCGRectForUIImageOrientationfunction is from NiftyBeanHere is your code with the changes: UPDATE New code has been added below this that should take care of the missing cases.
}
UPDATE I have made a couple of methods that will take care of the rest of the cases.
The steps are basically the same, with a couple of modifications.
the
UIImagePickerController. In these cases the square image isfilled with a color of your choosing.
New Code