iphone中UIImagePickerController组件默认拍照后的预览画面会将图像按比例压缩旋转到纵屏模式(即Home键朝下)。如下图:
如果项目中要求图像不旋转。即怎么拍照怎么显示,该怎么办呢?
UIImagePickerController组件封装的比较严实,看不到源代码,也没有提供可以修改是否旋转的参数。既然不能从根源解决问题,就只能采取应对措施。它默认压缩旋转,就取压缩旋转后的图片,经等比例放大后旋转回去。
第一步:自定义一个拍照并预览的画面。关键代码如下:
viewController.h文件:
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#import "ImageCropViewController.h"
@interface BIDViewController : UIViewController
<UIImagePickerControllerDelegate, UINavigationControllerDelegate,ImageCropViewControllerDelegate>{
ImageCropViewController *imageCropViewController;
UIImagePickerController * imagePickerCamera;
UIImagePickerController * imagePickerPhoto;
UIImagePickerController * imagePicker;
}
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@property (strong, nonatomic) IBOutlet UIButton *takePictureButton;
@property (strong, nonatomic) UIImage *image;
@property (strong, nonatomic) NSURL *movieURL;
@property (copy, nonatomic) NSString *lastChosenMediaType;
@property (assign, nonatomic) CGRect imageFrame;
@property CGRect imageCropRect;
@property (retain, nonatomic) IBOutlet ImageCropViewController *imageCropViewController;
- (IBAction)shootPictureOrVideo:(id)sender;
@end
viewController.m文件:
- (IBAction)shootPictureOrVideo:(id)sender {
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
imagePickerCamera = [[UIImagePickerController alloc] init];
imagePickerCamera.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerCamera.delegate = self;
imagePicker = imagePickerCamera;
[self presentModalViewController:imagePicker animated:YES];
}
}
#pragma mark UIImagePickerController delegate methods
-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
NSLog(@"willShowViewController:%@, %@, %@", viewController, viewController.toolbarItems, viewController.tabBarItem);
}
-(void)captureButtonAction:(id)sender
{
imagePickerCamera.showsCameraControls = NO;
[imagePickerCamera takePicture];
}
-(void)skipPreviewInImagePickerCamera:(UIViewController*)viewController;
{
/* Skip capture page 跳过拍照画面*/
NSString * systemVer = [[UIDevice currentDevice] systemVersion];
NSArray * verArray = [systemVer componentsSeparatedByString:@"."];
int majorver = [[verArray objectAtIndex:0] intValue];
UIButton *button = nil; /* 计算拍照button在view的subview中的位置 */
if(majorver >= 5){
UIView *view = viewController.view;
int index;
index = 3;
if(view.subviews.count<=index){return;}
view = [view.subviews objectAtIndex:index];
if(![view isKindOfClass:[UIView class]]){return;}
index = 1;
if(view.subviews.count<=index){return;}
view = [view.subviews objectAtIndex:index];
if(![view isKindOfClass:[UIView class]]){return;}
index = 1;
if(view.subviews.count<=index){return;}
view = [view.subviews objectAtIndex:index];
if(![view isKindOfClass:[UIView class]]){return;}
index = 0;
if(view.subviews.count<=index){return;}
view = [view.subviews objectAtIndex:index];
if(![view isKindOfClass:[UIView class]]){return;}
if(![view isKindOfClass:[UIButton class]]){return;}
button = (UIButton*)view;
}else{
UIView *view = viewController.view;
int index;
index = 2;
if(view.subviews.count<=index){return;}
view = [view.subviews objectAtIndex:index];
if(![view isKindOfClass:[UIView class]]){return;}
index = 1;
if(view.subviews.count<=index){return;}
view = [view.subviews objectAtIndex:index];
if(![view isKindOfClass:[UIView class]]){return;}
index = 1;
if(view.subviews.count<=index){return;}
view = [view.subviews objectAtIndex:index];
if(![view isKindOfClass:[UIView class]]){return;}
index = 0;
if(view.subviews.count<=index){return;}
view = [view.subviews objectAtIndex:index];
if(![view isKindOfClass:[UIView class]]){return;}
if(![view isKindOfClass:[UIButton class]]){return;}
button = (UIButton*)view;
}
id target = [[button allTargets] anyObject];
NSString *str = [[button actionsForTarget:target forControlEvent:UIControlEventTouchUpInside] objectAtIndex:0];
SEL action = NSSelectorFromString(str);
[button removeTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[button addTarget:self action:@selector(captureButtonAction:) forControlEvents:UIControlEventTouchUpInside];//触发拍照时间
}
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if(imagePicker == imagePickerCamera){
[self skipPreviewInImagePickerCamera:viewController];//跳过原有的预览画面
}
sleep(0);
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissModalViewControllerAnimated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissModalViewControllerAnimated:YES];
//获取拍照后的图像,此时图像已经压缩旋转了。后面的处理就是将此图片放大旋转回去
UIImage *image2 = (UIImage*)[info objectForKey:UIImagePickerControllerOriginalImage];
self.imageCropRect = CGRectMake(0, 0, 1.0, 1.0);
[imageCropViewController show:self image:image2 cropRect:self.imageCropRect delegate:self];//拍完照进入自定义的预览画面imageCropViewController
}
//截取完图片
-(void)didFinishImageCropViewController:(id)sender cropImage:(UIImage *)cropImage cropRect:(CGRect)cropRect;
{
((ImageCropViewController*)sender).view.window.rootViewController = self;
}
//取消截取
-(void)didCancelImageCropViewController:(id)sender{
((ImageCropViewController*)sender).view.window.rootViewController = self;
}
自定义的预览画面imageCropViewController中关键代码:
imageCropViewController.h文件:
#import <UIKit/UIKit.h>
@protocol ImageCropViewControllerDelegate;
@interface ImageCropViewController : UIViewController
@property(retain) id<ImageCropViewControllerDelegate> delegate;
@property(retain) UIImage *image;
@property(retain) UIImageView *imageView;
- (IBAction)ok:(id)sender;
- (IBAction)cancel:(id)sender;
- (void)show:(UIViewController*)parent image:(UIImage*)image cropRect:(CGRect)cropRect delegate:(id<ImageCropViewControllerDelegate>)delegate;
@end
@protocol ImageCropViewControllerDelegate <NSObject>
- (void)didFinishImageCropViewController:(id)sender cropImage:(UIImage*)cropImage cropRect:(CGRect)cropRect;
- (void)didCancelImageCropViewController:(id)sender;
@end
imageCropViewController.m文件:
-(void)viewWillAppear:(BOOL)animated{
for(UIView *view in [self.view subviews])
{
if ([view isKindOfClass:[self.imageView class]]==YES) {
[view removeFromSuperview];
}
}
CGRect frame2 = CGRectMake(-50, 50, 420, 320);//根据旋转后图像的坐标和大小计算旋转前图像应设置的坐标和大小。注意,旋转时以图像中心点为中心
self.imageView = [[[UIImageView alloc] initWithFrame:frame2] autorelease];
self.imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.imageView.image = self.image;
//将imageView逆时针旋转90度。向哪个方向旋转多少度取决于拍照时手机的旋转模式
self.imageView.transform = CGAffineTransformMakeRotation(-M_PI_2);
[self.view addSubview:self.imageView];
}
- (IBAction)ok:(id)sender {//预览画面后点选OK
UIImage * cropImage = [self.imageView image];
[self dismissModalViewControllerAnimated:YES];
[self.delegate didFinishImageCropViewController:self cropImage:cropImage cropRect:CGRectMake(0, 0, 420, 320)];
}
- (IBAction)cancel:(id)sender {//预览画面后点选取消
[self dismissModalViewControllerAnimated:YES];
[self.delegate didCancelImageCropViewController:self];
}
#if 0
- (void)showModal:(UIViewController*)parent image:(UIImage*)image delegate:(id<ImageCropViewControllerDelegate>)delegate
{
self.delegate = delegate;
self.imageView.image = self.image = image;
[parent presentModalViewController:self animated:YES];
}
#endif
- (void)show:(UIViewController*)parent image:(UIImage*)image cropRect:(CGRect)cropRect delegate:(id<ImageCropViewControllerDelegate>)delegate//viewCOntroller中调用的delegate中方法
{
self.delegate = delegate;
self.imageView.image = self.image = image;
parent.view.window.rootViewController = self;
}
最后,将imageCropViewController添加到viewController的容器中就可以了。
最终效果如图: