从 av 基础框架工作为 ios 开发自定义相机应用程序时,Camara 预览显示不正确?
Posted
技术标签:
【中文标题】从 av 基础框架工作为 ios 开发自定义相机应用程序时,Camara 预览显示不正确?【英文标题】:Camara preview not displayed in correct when developing a custom camera application for ios from av foundation frame work? 【发布时间】:2014-01-15 05:24:43 【问题描述】:我正在使用 xcode 5 为 ios 7 开发一个自定义相机应用程序。我有一个视图控制器如下的类
#import "ADMSImageUploader.h"
#import "ADMSViewController.h"
@interface ADMSImageUploader ()
@end
@implementation ADMSImageUploader
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
// Custom initialization
return self;
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view.
FrontCamera = NO;
[self initializeCamera];
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
- (void)viewDidAppear:(BOOL)animated
//AVCaptureSession to show live video feed in view
- (void) initializeCamera
session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetPhoto;
captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[self.imagePreview.layer setMasksToBounds:YES];
// CGSize landscapeSize;
// landscapeSize.width = self.imagePreview.bounds.size.width;
// landscapeSize.height = self.view.bounds.size.width;
//CGRect rect=[[UIScreen mainScreen]bounds];
captureVideoPreviewLayer.frame = CGRectMake(0.0, 0.0, self.imagePreview.frame.size.width, self.imagePreview.frame.size.height);
connection = captureVideoPreviewLayer.connection;
orientation = AVCaptureVideoOrientationLandscapeRight;
//connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
[captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
// if ([[UIDevice currentDevice] orientation] == UIInterfaceOrientationPortrait )
// captureVideoPreviewLayer.frame = CGRectMake(0.0, 0.0, self.imagePreview.frame.size.width, self.imagePreview.frame.size.height);
// connection = captureVideoPreviewLayer.connection;
// orientation = AVCaptureVideoOrientationPortrait;
// //connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
// [captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
//
// else
// captureVideoPreviewLayer.frame = CGRectMake(0.0, 0.0, self.imagePreview.frame.size.width, self.imagePreview.frame.size.height);
// connection = captureVideoPreviewLayer.connection;
// orientation = AVCaptureVideoOrientationLandscapeRight;
// //connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
// [captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
//
//
[self.imagePreview.layer addSublayer:captureVideoPreviewLayer];
NSArray *devices = [AVCaptureDevice devices];
AVCaptureDevice *frontCamera;
AVCaptureDevice *backCamera;
for (AVCaptureDevice *device in devices)
NSLog(@"Device name: %@", [device localizedName]);
if ([device hasMediaType:AVMediaTypeVideo])
if ([device position] == AVCaptureDevicePositionBack)
NSLog(@"Device position : back");
backCamera = device;
else
NSLog(@"Device position : front");
frontCamera = device;
else
if (!([device position] == AVCaptureDevicePositionBack))
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Cannot take photos using rear camera"
message:@"Your device doesnot support this feature."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
if (!FrontCamera)
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error];
if (!input)
NSLog(@"ERROR: trying to open camera: %@", error);
[session addInput:input];
if (FrontCamera)
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error];
if (!input)
NSLog(@"ERROR: trying to open camera: %@", error);
[session addInput:input];
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[_stillImageOutput setOutputSettings:outputSettings];
[session addOutput:_stillImageOutput];
[session startRunning];
- (BOOL)shouldAutorotate
return YES;
//-(void)openCamera:(NSString *)dealerId:(NSString *)inventoryId
//
//
//
- (void)viewWillAppear:(BOOL)animated
[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
_uploadButtonBehaviour.hidden = YES;
_discardButtonBehaviour.hidden = YES;
- (void)viewWillDisappear:(BOOL)animated
[self.navigationController setNavigationBarHidden:NO animated:animated];
[super viewWillDisappear:animated];
- (NSUInteger)supportedInterfaceOrientations;
return UIInterfaceOrientationMaskLandscape;
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;
captureVideoPreviewLayer.frame = CGRectMake(0.0, 0.0,self.imagePreview.frame.size.width,self.imagePreview.frame.size.height);
[captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
connection = captureVideoPreviewLayer.connection;
[captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
// connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
[connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
return UIInterfaceOrientationLandscapeRight;
- (IBAction)captureButton:(id)sender
- (IBAction)exitButton:(id)sender
[self.navigationController popToRootViewControllerAnimated:YES];
- (IBAction)uploadButton:(id)sender
- (IBAction)discardButton:(id)sender
@end
我只想在景观模式下启动这个视图控制器。我正在使用导航控制器转到不同的视图控制器。
当我以前的视图控制器处于垂直方向时,相机预览如下
当我将 ios 设备旋转到横向时,会显示以下相机预览。这里的问题是预览图像被拉伸了。
当我以前的视图控制器处于水平方向时,相机预览如下。相机预览出现倒置。 。我请求你在这个问题上帮助我。
【问题讨论】:
【参考方案1】:我曾经遇到过同样的问题。我通过检测设备方向使用CGAffineTransformMakeScale
手动旋转捕获的图像来解决这个问题。
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)
CIImage *c = [[CIImage alloc] initWithImage:imageFromCamera];
c = [c imageByApplyingTransform:CGAffineTransformTranslate(CGAffineTransformMakeScale(-1, -1), 0, c.extent.size.height)];
imageFromCamera = [UIImage imageWithCGImage:[[CIContext contextWithOptions:nil] createCGImage:c fromRect:c.extent]];
如果旋转不正确,请更改 CGAffineTransformMakeScale
的值。
【讨论】:
【参考方案2】://AVCaptureSession to show live video feed in view
- (void) initializeCamera
session = [[AVCaptureSession alloc] init];
if ([session canSetSessionPreset:AVCaptureSessionPresetPhoto])
session.sessionPreset = AVCaptureSessionPresetPhoto;
devicesArray = [AVCaptureDevice devices];
for (AVCaptureDevice *device in devicesArray)
if ([device hasMediaType:AVMediaTypeVideo])
if ([device position] == AVCaptureDevicePositionBack)
NSLog(@"Device name: %@", [device localizedName]);
NSLog(@"Device position : back");
backCamera = device;
backCameraCheck = YES;
if (backCameraCheck)
NSError *error = nil;
inputDevice = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error];
if (!inputDevice)
NSLog(@"ERROR: trying to open camera: %@", error);
else
[session addInput:inputDevice];
else
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Cannot take photos using rear camera"
message:@"Your device doesnot support this feature."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
output = [[AVCaptureVideoDataOutput alloc] init];
[session addOutput:output];
captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
connection = [output connectionWithMediaType:AVMediaTypeVideo];
connection = captureVideoPreviewLayer.connection;
if ([[UIDevice currentDevice] orientation] == UIInterfaceOrientationPortrait )
captureVideoPreviewLayer.frame = CGRectMake(0.0, 0.0, self.imagePreview.frame.size.width, self.imagePreview.frame.size.height);
if ([connection isVideoOrientationSupported])
orientation = AVCaptureVideoOrientationPortrait;
[connection setVideoOrientation:orientation];
else
NSLog(@"view width = %f %f", self.imagePreview.frame.size.width, self.imagePreview.frame.size.height);
captureVideoPreviewLayer.frame = CGRectMake(0.0, 0.0, self.imagePreview.frame.size.height,self.imagePreview.frame.size.width);
if ([connection isVideoOrientationSupported])
orientation = AVCaptureVideoOrientationLandscapeRight;
[connection setVideoOrientation:orientation];
[self.imagePreview.layer setMasksToBounds:YES];
[self.imagePreview.layer addSublayer:captureVideoPreviewLayer];
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[_stillImageOutput setOutputSettings:outputSettings];
[session addOutput:_stillImageOutput];
[session startRunning];
else
// Handle the failure.
【讨论】:
以上是关于从 av 基础框架工作为 ios 开发自定义相机应用程序时,Camara 预览显示不正确?的主要内容,如果未能解决你的问题,请参考以下文章