iOS--相機(自定義相機) 保存照片到相冊

自定義相機  提供兩個鏈接:

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章