views:

462

answers:

1

I have an app which allows the user to select an image from camera or photo library. It then places that image in a ImageView. I am then using Quartz to grab the image from that image view and render it along with some basic overlays etc.

The issue is that when the image is picked from the camera, or from the camera roll Quartz draws the image with a 90 degree rotation and stretches the image vertically. There is no issue when selecting any other photo from the photo library. And the issue does not occur if allowsImageEditing is set to YES.

If anyone can shed some light it would be helpfull, i'm a relative newbie at this.

Code in my CameraViewController

#pragma mark -
- (IBAction)getCameraPicture {
     UIImagePickerController *picker = [[UIImagePickerController alloc] init];
     picker.navigationBar.barStyle = UIBarStyleBlackOpaque;
     picker.delegate = self;
     picker.allowsImageEditing = NO; //seems to fix the weird rotation & stretching issues if set to YES
     picker.sourceType = UIImagePickerControllerSourceTypeCamera;
     [self presentModalViewController:picker animated:YES];
     //[picker release];
}
- (IBAction)selectExistingPicture {
     if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
     UIImagePickerController *picker = [[UIImagePickerController alloc] init];
     picker.navigationBar.barStyle = UIBarStyleBlackOpaque;
     picker.delegate = self;
     picker.allowsImageEditing = NO; //seems to fix the weird rotation & stretching issues if set to YES (only with camera roll)
     picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
     [self presentModalViewController:picker animated:YES];
     //[picker release];
     }
}
#pragma mark -
- (void)imagePickerController:(UIImagePickerController *)picker 
 didFinishPickingImage:(UIImage *)image
   editingInfo:(NSDictionary *)editingInfo {

     imageView.image = image;
     NSLog(@"imagePicker image size %.0f x %.0f", image.size.width, image.size.height);
     [picker dismissModalViewControllerAnimated:YES];
     [picker release];
     [quartzContextView setNeedsDisplay];
     [self setUpAndRenderImage];

}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
     [picker dismissModalViewControllerAnimated:YES];
     [picker release];
}

Code in the view that draws the Quartz

NSLog(@"Quartz image size %.0f x %.0f", drawImageTwo.size.width, drawImageTwo.size.height);
if (drawImageTwo.size.width >= drawImageTwo.size.height)
{
     scaleFactor = (insideHeight+5)/drawImageTwo.size.height;
     xOffset = (drawImageTwo.size.width*scaleFactor - insideWidth)/2;
     yOffset = 0;
     NSLog(@"Image is Landscaepe");
}
else if (drawImageTwo.size.width < drawImageTwo.size.height)
{
     scaleFactor = (insideWidth+5)/drawImageTwo.size.width;
     yOffset = (drawImageTwo.size.height*scaleFactor - insideHeight)/2;
     xOffset = 0;
     NSLog(@"Image is Portrait");
}

//draw Photo Base
CGRect baseRect = CGRectMake(0.0, 0.0, width, height);
CGContextDrawImage (context, baseRect, drawImage.CGImage);

//clip all further drawing to context clip
CGContextClipToRect(context, CGRectMake(leftOffset, (height-insideHeight-topOffset), insideWidth, insideHeight));

//draw Photo
CGRect photoRect = CGRectMake(leftOffset-xOffset, (height-insideHeight-topOffset)-yOffset, drawImageTwo.size.width*scaleFactor, drawImageTwo.size.height*scaleFactor);
CGContextDrawImage (context, photoRect, drawImageTwo.CGImage);
A: 

The problem you are experiencing comes from different coordinate systems and handling of image orientation in UIKit and CoreGraphics.

An UIImage knows about it's orientation, that is the orientation of the camera when the image was first taken. As long as you work with UIKit Classes everything works as expected, but when you get the raw CGImage of an UIImage you are loosing this information. You have to account of the image orientation for yourself, by transforming the CTM (Current Transformation Matrix) of the CGContext.

But not enough CoreGraphics uses a coordinate system were the origin lies in the left lower screen corner, whereas UIKit has it's origin in the upper left. See Quartz 2D Programming Guide Chapter "Graphics Contexts". You would have to scale the CTM by 0,-1 and translate it by its height to account for that.

In your example, as you're not doing fancy stuff with the image, it seems most appropriate to try UIImages drawInRect: method, which already accounts for both gotchas.

tonklon