I am new to iOS and I have been bashing head against the wall for this for the past week looking around online for tutorials such as: Dealing with Exif Images, Resizing images, and many more random questions here on StackOverflow. From these, I figured that >=iOS 4.0
, all images taken from the camera contain EXIF
-based rotation information.
What's not working: After trying different image cropping techniques, all I end up with is cropping of the image at some random corners and also, the resulting image appears to be zoomed in :( When I use a png
image from the internet (which don't contain EXIF data), the cropping is working. By random corners, I mean - the image ends up being cropped at the top-right/top-left and zoomed-in.
What I am trying to accomplish:
I am trying to crop an image 100 px
from top and 100 px
from bottom. Essentially, I am using two overlay strips - 1 at the top, and 1 at the bottom with the CGRect(0.0, 0.0, SCREEN_WIDTH, 100.0)
[a 100.0 px
tall strip at the top] and another CGRect(0.0, SCREEN_HEIGHT - 100, SCREEN_WIDTH, 100.0)
[another 100 px
tall strip at the bottom]. I need to get the image between these two strips: I assume the height of the image is: SCREEN_HEIGHT - 200.0
.
Displaying UIImagePickerController for camera with overlay:
//SCREEN_HEIGHT = 480 and SCREEN_WIDTH = 320
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == NO)
{
NSLog(@"Camera not available");
return;
}
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
imagePicker.allowsEditing = NO;
// Hide the controls
imagePicker.showsCameraControls = NO;
imagePicker.navigationBarHidden = YES;
// Make camera view full screen
imagePicker.wantsFullScreenLayout = YES;
//imagePicker.cameraViewTransform = CGAffineTransformScale(imagePicker.cameraViewTransform, CAMERA_TRANSFORM_X, CAMERA_TRANSFORM_Y);
//Overlay
//OverlayView is a plain UIView with the CGRects mentioned in the question.
OverlayView *overlay = [[OverlayView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
[overlay initOverlay:self];
imagePicker.cameraOverlayView = overlay;
[self presentModalViewController:imagePicker animated:YES];
Code to rotate image based on EXIF imageOrientation
property and cropping it
- (UIImage *) cropImage: (UIImage *) originalImage
{
CGRect cropRect = CGRectMake(0, 100.0, SCREEN_WIDTH, SCREEN_HEIGHT - 100);
CGRect transformedRect = [self TransformCGRectForUIImageOrientation:cropRect :originalImage.imageOrientation :originalImage.size];
CGImageRef resultImageRef = CGImageCreateWithImageInRect(originalImage.CGImage, transformedRect);
UIImage *newImage = [[[UIImage alloc] initWithCGImage:resultImageRef scale:1.0 orientation:originalImage.imageOrientation] autorelease];
return newImage;
}
- (CGRect) TransformCGRectForUIImageOrientation: (CGRect) source: (UIImageOrientation) orientation: (CGSize) imageSize {
switch (orientation) {
case UIImageOrientationLeft: { // EXIF #8
CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(
imageSize.height, 0.0);
CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,
M_PI_2);
return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationDown: { // EXIF #3
CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(
imageSize.width, imageSize.height);
CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,
M_PI);
return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationRight: { // EXIF #6
CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(
0.0, imageSize.width);
CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,
M_PI + M_PI_2);
return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationUp: // EXIF #1 - do nothing
default: // EXIF 2,4,5,7 - ignore
return source;
}
The cropImage
method seems to work for images downloaded from the internet (which don't contain any orientation info).
I am running out of options. Could someone PLEASE help me out?
Thanks for reading!
When you can, it is easier to skip drawing images with Core Graphics:
- (UIImage *)cropImage:(UIImage *)oldImage {
CGSize imageSize = oldImage.size
UIGraphicsBeginImageContextWithOptions( CGSizeMake( imageSize.width,
imageSize.height - 200),
NO,
0.);
[oldImage drawAtPoint:CGPointMake( 0, -100)
blendMode:kCGBlendModeCopy
alpha:1.];
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return croppedImage;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With