自定義相機 提供兩個鏈接:
http://course.gdou.com/blog/Blog.pzs/archive/2011/12/14/10882.html (原理講解)
http://www.cnblogs.com/liangzhimy/archive/2012/10/26/2740905.html
保存相片到相冊
UIImageWriteToSavedPhotosAlbum(image, self,@selector(image:didFinishSavingWithError:contextInfo:), nil);
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
NSString *alertMessage;
if(!error)
{
alertMessage = @"圖片保存成功";
}
else
{
alertMessage = @"圖片保存失敗";
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
message:alertMessage
delegate:self
cancelButtonTitle:@"好"
otherButtonTitles:nil];
[alert show];
}
iOS中使用相機,有兩種方式:1:使用ios系統自帶的相機。( UIImagePickerController)
2:自定義相機。(利用AVFoundation.framework框架,自定義照相)
第一種:使用iOS系統自帶相機。
1:實現 <UINavigationControllerDelegate,UIImagePickerControllerDelegate>這兩個協議
2:創建UIImagePickerController實例。(以下是使用相機照相,如果只是想訪問系統相冊,則可以直接設置代理後,跳轉到vc就行,
#pragma mark --從相冊中選取圖片,然後使用濾鏡
- (IBAction)chosePicAndChange:(id)sender
{
if (!self.ipc.delegate) {
self.ipc.delegate=self;
}
[self presentViewController:self.ipc animated:YES completion:nil];
}
)
-(UIImagePickerController *)ipc
{
if (!_ipc) {
_ipc=[UIImagePickerControllernew];
}
return _ipc;
}
//判斷是否可以打開相機,模擬器此功能無法使用
if([UIImagePickerControllerisSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
self.ipc.delegate=self;
//是否可編輯
self.ipc.allowsEditing=YES;
//攝像頭
self.ipc.sourceType=UIImagePickerControllerSourceTypeCamera;
[selfpresentViewController:self.ipcanimated:YEScompletion:nil];
}else
{
UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"Error"message:@"你沒有攝像頭"delegate:nilcancelButtonTitle:@"Drat!"otherButtonTitles:nil];
[alertshow];
}
3:實現UIImagePickerControllerDelegate (保存拍攝的照片)
//拍攝完成後,要執行的方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//得到圖片
UIImage *image=[infoobjectForKey:UIImagePickerControllerOriginalImage];
/**
用於拍照時,圖片存入相冊
*/
#if 0
//圖片存入相冊
UIImageWriteToSavedPhotosAlbum(image, nil,nil, nil);
#endif
/**
單利傳值,彈出下一個viewcontroller
*/
AZChoseImage *choseImage=[AZChoseImagedefaultChoseImage];
choseImage.image=image;
[selfdismissViewControllerAnimated:NOcompletion:nil];
[self.navigationControllerpushViewController:self.filterVCanimated:YES];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[selfdismissViewControllerAnimated:YEScompletion:nil];
}
完整的代碼:
#import "ViewController.h"
#import "CustomViewController.h"
#import "AZFliterViewController.h"
#import "AZChoseImage.h"
@interface ViewController ()<UINavigationControllerDelegate,UIImagePickerControllerDelegate>
@property (nonatomic,strong)UIImagePickerController *ipc;
@property (nonatomic,strong)CustomViewController *customIpc;
@property (nonatomic,strong)AZFliterViewController *filterVC;
@end
@implementation ViewController
#pragma mark -- 懶加載
-(UIImagePickerController *)ipc
{
if (!_ipc) {
_ipc=[UIImagePickerController new];
}
return _ipc;
}
-(CustomViewController *)customIpc
{
if (!_customIpc) {
_customIpc=[[CustomViewController alloc] init];
}
return _customIpc;
}
-(AZFliterViewController *)filterVC
{
if(!_filterVC)
{
_filterVC=[[AZFliterViewController alloc] init];
}
return _filterVC;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -- 使用UIImagePickerController
- (IBAction)takePhoto:(id)sender
{
//判斷是否可以打開相機,模擬器此功能無法使用
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
self.ipc.delegate=self;
//是否可編輯
self.ipc.allowsEditing=YES;
//攝像頭
self.ipc.sourceType=UIImagePickerControllerSourceTypeCamera;
[self presentViewController:self.ipc animated:YES completion:nil];
}else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"你沒有攝像頭" delegate:nil cancelButtonTitle:@"Drat!" otherButtonTitles:nil];
[alert show];
}
}
#pragma mark -- UIImagePickerControllerDelegate
//拍攝完成後,要執行的方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//得到圖片
UIImage *image=[info objectForKey:UIImagePickerControllerOriginalImage];
/**
用於拍照時,圖片存入相冊
*/
#if 0
//圖片存入相冊
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
#endif
/**
單利傳值,彈出下一個viewcontroller
*/
AZChoseImage *choseImage=[AZChoseImage defaultChoseImage];
choseImage.image=image;
[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController pushViewController:self.filterVC animated:YES];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark -- 使用AVFoundation.framework框架自定義照相
- (IBAction)customTakePhoto:(id)sender
{
[self.navigationController pushViewController:self.customIpc animated:YES];
}
#pragma mark -- 從相冊中選取圖片,然後使用濾鏡
- (IBAction)chosePicAndChange:(id)sender
{
if (!self.ipc.delegate) {
self.ipc.delegate=self;
}
[self presentViewController:self.ipc animated:YES completion:nil];
}
@end
第二種:利用AVFoundation.framework框架,自定義照相
完整代碼:
#import "CustomViewController.h"
#import <AVFoundation/AVFoundation.h>
/**
需要導入頭文件:#import <AVFoundation/AVFoundation.h>
*/
@interface CustomViewController ()
/**
在AVFoundation框架下使用自定義照相需要的屬性
*/
//AVCaptureSession對象來執行輸入設備和輸出設備之間的數據傳遞
@property (nonatomic, strong) AVCaptureSession * session;
//AVCaptureDeviceInput對象是輸入流
@property (nonatomic, strong) AVCaptureDeviceInput * videoInput;
//照片輸出流對象
@property (nonatomic, strong) AVCaptureStillImageOutput * stillImageOutput;
//預覽圖層,來顯示照相機拍攝到的畫面
@property (nonatomic, strong) AVCaptureVideoPreviewLayer * previewLayer;
#pragma mark -- 定義相機的展示
//切換前後鏡頭的按鈕
@property (nonatomic, strong) UIBarButtonItem * changeButton;
//拍照按鈕
@property (nonatomic, strong) UIButton * takePhotoButton;
//放置預覽圖層的View
@property (nonatomic, strong) UIView * cameraShowView;
@end
@implementation CustomViewController
- (void)viewDidLoad {
[super viewDidLoad];
//初始化自定義相機的各實例
[self initialSession];
[self createCustomCaramView];
self.view.backgroundColor=[UIColor whiteColor];
}
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (self.session)
{
[self.session startRunning];
}
[self createCameraLayer];
}
- (void) viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear: animated];
if (self.session) {
[self.session stopRunning];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -- 自定義照相
/**
初始化自定義照相的相關實例
*/
- (void) initialSession
{
//01 創建session
self.session = [[AVCaptureSession alloc] init];
// 設置採集質量
if([self.session canSetSessionPreset:AVCaptureSessionPresetPhoto])
{
self.session.sessionPreset=AVCaptureSessionPresetPhoto;
}
//02 創建輸入設備,[self fronCamera]方法會返回一個AVCaptureDevice對象,因爲我初始化時是採用前攝像頭,
self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontCamera] error:nil];
//03 創建輸出設備
/**
有四類輸出設備:
1: AVCaptureMovieFileOutput to output to a movie file (輸出一個 視頻文件)
2: AVCaptureVideoDataOutput if you want to process frames from the video being captured (可以採集數據從指定的視頻中)
3: AVCaptureAudioDataOutput if you want to process the audio data being captured (採集音頻)
4: AVCaptureStillImageOutput if you want to capture still images with accompanying metadata (採集靜態圖片)
*/
self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
// 這是輸出流的設置參數AVVideoCodecJPEG參數表示以JPEG的圖片格式輸出圖片
NSDictionary * outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
[self.stillImageOutput setOutputSettings:outputSettings];
//04 添加輸入輸出設備到session中
if ([self.session canAddInput:self.videoInput]) {
[self.session addInput:self.videoInput];
}
if ([self.session canAddOutput:self.stillImageOutput]) {
[self.session addOutput:self.stillImageOutput];
}
}
#pragma mark -- 獲取設備(前 後 攝像頭)
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition) position {
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices) {
if ([device position] == position) {
return device;
}
}
return nil;
}
- (AVCaptureDevice *)frontCamera {
return [self cameraWithPosition:AVCaptureDevicePositionFront];
}
- (AVCaptureDevice *)backCamera {
return [self cameraWithPosition:AVCaptureDevicePositionBack];
}
#pragma mark -- 創建自定義照相上的按鍵以及view
-(void)createCustomCaramView
{
_changeButton =[[UIBarButtonItem alloc] initWithTitle:@"調換攝像頭" style:UIBarButtonItemStylePlain target:self action:@selector(toggleCamera)];
self.navigationItem.rightBarButtonItem=_changeButton;
_takePhotoButton=[UIButton buttonWithType:UIButtonTypeSystem];
[_takePhotoButton setTitle:@"點擊拍照" forState:UIControlStateNormal];
_takePhotoButton.frame=CGRectMake(0, 400, self.view.bounds.size.width,50);
[_takePhotoButton addTarget:self action:@selector(shutterCamera) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_takePhotoButton];
_cameraShowView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 400)];
_cameraShowView.backgroundColor=[UIColor grayColor];
[self.view addSubview:_cameraShowView];
}
#pragma mark -- 切換鏡頭的按鍵方法
- (void)toggleCamera {
NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
if (cameraCount > 1) {
NSError *error;
AVCaptureDeviceInput *newVideoInput;
AVCaptureDevicePosition position = [[_videoInput device] position];
if (position == AVCaptureDevicePositionBack)
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontCamera] error:&error];
else if (position == AVCaptureDevicePositionFront)
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backCamera] error:&error];
else
return;
if (newVideoInput != nil) {
[self.session beginConfiguration];
[self.session removeInput:self.videoInput];
if ([self.session canAddInput:newVideoInput]) {
[self.session addInput:newVideoInput];
[self setVideoInput:newVideoInput];
} else {
[self.session addInput:self.videoInput];
}
[self.session commitConfiguration];
} else if (error) {
NSLog(@"toggle carema failed, error = %@", error);
}
}
}
#pragma mark -- 拍照按鍵響應事件
- (void) shutterCamera
{
AVCaptureConnection * videoConnection = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
if (!videoConnection) {
NSLog(@"take photo failed!");
return;
}
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (imageDataSampleBuffer == NULL) {
return;
}
NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage * image = [UIImage imageWithData:imageData];
NSLog(@"image size = %@",NSStringFromCGSize(image.size));
}];
}
#pragma mark -- 創建顯示層
- (void) createCameraLayer
{
//如果不允許相機拍照,則返回
// if (_cameraAvaible == NO) return;
if (self.previewLayer == nil) {
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
UIView * view = self.cameraShowView;
CALayer * viewLayer = [view layer];
[viewLayer setMasksToBounds:YES];
CGRect bounds = [view bounds];
[self.previewLayer setFrame:bounds];
[self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
[viewLayer insertSublayer:self.previewLayer below:[[viewLayer sublayers] objectAtIndex:0]];
}
}
@end