星期三, 1月 18, 2017

[Objective-C] iOS 基本技能: 呼叫相機

超常用的iOS呼叫相機基本技能,測試完記錄一下。

使用UIImagePickerController (簡單、快速)

- (void) initCamera{
    
    NSLog(@"initCamera");
    dispatch_async(dispatch_get_main_queue(), ^{
        UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
        
        //檢查是否支援此Source Type(相機)
        if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
            NSLog(@"Access Camera Device");
            
            //設定影像來源為相機
            imagePicker.sourceTypeUIImagePickerControllerSourceTypeCamera;
            imagePicker.delegate = self;
            imagePicker.allowsEditing = YES;
            
            //顯示UIImagePickerController
            [self presentViewController:imagePicker animated:YES completion:nil];
        }
        else {
            //提示使用者,目前設備不支援相機
            NSLog(@"No Camera Device");
        }

    });
    
}

//使用者按下確定時
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    //取得剛拍攝的相片(或是由相簿中所選擇的相片)
    UIImage *image=[info objectForKey:UIImagePickerControllerEditedImage];
    
    //設定ImageViewImage物件,例如:
    //yourImageView.image = image;
    
    [picker dismissViewControllerAnimated:YES completion:^{}];
}

//使用者按下取消時
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    //一般情況下沒有什麼特別要做的事情
    
    [picker dismissViewControllerAnimated:YES completion:^{}];

}


使用AV Foundation

優點就是彈性比較大,速度快




//自行定義的函式,目的用來顯示Camera所擷取到的畫面
-(void)initCameraCaptureSession {
    NSLog(@"initCameraCaptureSession");
    
    //sessionAVCaptureSession型態的指標,之後將透過這個指標對Camera影像做擷取並輸出
    myCaptureSession = [[AVCaptureSession alloc] init];
    
    //設定擷取時畫面的大小,這裡提供三種等級可以選擇
    myCaptureSession.sessionPreset = AVCaptureSessionPresetMedium;
    
    //選擇Device,也就是Camera
    //建立 AVCaptureDeviceInput
    NSArray *myDevices = [AVCaptureDevice devices];
    
    for (AVCaptureDevice *device in myDevices) {
        if ([device position] == AVCaptureDevicePositionBack) {
            NSLog(@"後攝影機硬體名稱: %@", [device localizedName]);
        }
        
        if ([device position] == AVCaptureDevicePositionFront) {
            NSLog(@"前攝影機硬體名稱: %@", [device localizedName]);
        }
        
        if ([device hasMediaType:AVMediaTypeAudio]) {
            NSLog(@"麥克風硬體名稱: %@", [device localizedName]);
        }
    }
    //使用後置鏡頭當做輸入
    NSError *error = nil;
    for (AVCaptureDevice *device in myDevices) {
        if ([device position] == AVCaptureDevicePositionBack) {//指定後鏡頭
            
            AVCaptureDeviceInput *myDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
            
            if (error) {
                //裝置取得失敗時的處理常式
            } else {
                NSLog(@"設定輸入端");
                
                [myCaptureSession addInput:myDeviceInput];
            }
        }
    }
    
    //影像輸出至APP
    //建立 AVCaptureVideoPreviewLayer
    AVCaptureVideoPreviewLayer *myPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:myCaptureSession];
    [myPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    
    //輸出的目的地-產生一個rect的大小來輸出
    CGRect rect = CGRectMake(160, 180, 320, 240);
    [myPreviewLayer setBounds:rect];
    
    UIView *myView = [[UIView alloc]initWithFrame:rect];
    [myView.layer addSublayer:myPreviewLayer];
    
    [self.view addSubview:myView];
    
    
    //啟用攝影機
    [myCaptureSession startRunning];
    
    //取得攝影機連續影像
    myVideoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
    myVideoDataOutput.videoSettings = [NSDictionary dictionaryWithObject: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey: (id)kCVPixelBufferPixelFormatTypeKey];
    
    [myVideoDataOutput setAlwaysDiscardsLateVideoFrames:YES];
    [myVideoDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
    
    AVCaptureConnection *connection = [myVideoDataOutput connectionWithMediaType:AVMediaTypeVideo];
    [connection setVideoMaxFrameDuration:CMTimeMake(1, 20)];
    [connection setVideoMinFrameDuration:CMTimeMake(1, 10)];
    
    [myCaptureSession addOutput:myVideoDataOutput];
}
//丟棄延遲的影格
- (void)captureOutput:(AVCaptureOutput *)captureOutput didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    NSLog(@"丟棄延遲的影格 didDropSampleBuffer");
}

//擷取連續影像片段
- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection {
    NSLog(@"擷取連續影像片段 didOutputSampleBuffer");
    
    

}

旋轉與鏡射

可使用內建函式中的 AVCaptureConnection

做 setVideoOrientation: 旋轉影像,或 setVideoMirrored: 鏡射影像。

iOS 10的權限問題

在iOS10之後需要設定一下相機的存取權限不然會GG
打開info.plist檔加入新的KEY: Privacy - Camera Usage Description ,值就隨便設即可。
成功就能呼叫,就彈視窗說APP會想要取用你的相機!!



參考

http://furnacedigital.blogspot.tw/2010/12/cameraios4.html
http://furnacedigital.blogspot.tw/2012/11/avcapturevideodataoutput.html
http://furnacedigital.blogspot.tw/2012/11/avcapturestillimageoutput.html





沒有留言:

張貼留言

留個話吧:)

其他你感興趣的文章

Related Posts with Thumbnails