I think I found a bug in latest iOS 7 by running an app with Base SDK set to iOS 6.1 (possibly even lower versions too, haven't tested that out yet)
I have this image in my photo library: http://i.imgur.com/7KUIGLt.jpg
I present a UIImagePickerController via:
UIImagePickerController *vc = [[UIImagePickerController alloc] init];
vc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
vc.delegate = self;
vc.allowsEditing = YES;
[self presentViewController:vc animated:YES completion:nil];
I save the chosen image to my desktop (I am running this on simulator, but this works on device too)
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage* outputImage = [info objectForKey:UIImagePickerControllerEditedImage];
if (outputImage == nil) {
outputImage = [info objectForKey:UIImagePickerControllerOriginalImage];
}
NSData *d = UIImagePNGRepresentation(outputImage);
[d writeToFile:@"/Users/Admin/Desktop/test.png" atomically:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}
This is the resulting image:
Notice the big black bar to the right. What's causing this?
To reproduce this, you need:
NOTE: Just to be clear, the black bar is part of the actual image. The image you see there is not a screenshot of a UIImageView, but the actual image saved to disk and uploaded here...
Your question is "What's causing this?" So I'll focus on that instead of giving a workaround. This is definitely a bug in iOS 7 dealing with edited images in lower base SDKs. We can also rule out that XCode 5 & Base SDK 6.1 causing this because I'm getting the same issue with XCode 4.6.3 & 6.1 SDK running on iOS 7 Simulator.
The source of the problem is that the CropRect values that are calculated by the SDK are wrong.
If you'll print out the info
NSDictionary
from imagePickerController:didFinishPickingMediaWithInfo
you'll see that:
iOS 7 running any SDK lower than 7 we'll get:
UIImagePickerControllerCropRect = "NSRect: {{154, 495}, {1705, 1705}}";
While running iOS 6 or 5 with their SDK will give us:
UIImagePickerControllerCropRect = "NSRect: {{0, 149}, {1704, 1705}}";
You're probably saying, hmm, those y values are changing between SDKs too. Well, yea, if you'll slide your pic all the way down and select it you'll also get a black bar at the bottom of the picture.
Suggested Solutions:
File a bug report to Apple here ...Did that!
Don't use UIImagePickerControllerEditedImage
and take the original picture instead.
Calculate and do the cropping your self.
Use a 3rd party cropping library such as PEPhotoCropEditor or SSPhotoCropperViewController
Edit - very simple solution added by fan of the answer!
Amazingly, it can be this simple and elegant to crop it yourself:
{
// There is a bug in iOS. When using ALBUM, you must crop it yourself:
fromAlbum = [info objectForKey:UIImagePickerControllerOriginalImage];
fromAlbum = [fromAlbum fixOrientation];
CGRect crop = [[info valueForKey:@"UIImagePickerControllerCropRect"] CGRectValue];
fromAlbum = [self ordinaryCrop:fromAlbum toRect:crop];
}
Here's the whole routine ordinaryCrop:toRect:
-(UIImage *)ordinaryCrop:(UIImage *)imageToCrop toRect:(CGRect)cropRect
{
CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], cropRect);
UIImage *cropped = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return cropped;
}
Now as Jesse points out, it is critical to rotate the image properly. This absolutely incredible piece of code by Anomie does the job:
iOS UIImagePickerController result image orientation after upload
Fixing UIImage orientation .. UIImage+fixOrientation.h
It's that simple, hope it helps someone. Thanks again for the priceless answers here.