원문 : http://jamesonquave.com/blog/taking-control-of-the-iphone-camera-in-ios-8-with-swift-part-1/


Taking control of the iPhone camera in iOS 8 with Swift (Part 1)


AVFoundation API를 사용하여, 우리는 캡쳐 세션을 설정 하고  iOS8에 추가된 새로운 컨트롤을 사용하는 앱을 만들것이다. 수동으로 초점, 노출, ISO 제어하는 것을 포함한다. 우선, 우리는 기본적인 카메라 미리보기를 설정해야 한다. Part 1의 끝으로 초점을 제어할수 있는 멋진 방법과 함께 장소에 대한 값을 가질수 있을것이다. 준비됐는가? 시작해 보자.


우선 새로운 XCode 프로젝트를 Swift 사용, Single View 템플릿을 사용하도록 생성한다.


이제, ViewController.swift 파일에서 viewDidLoad()에 우리의 사용자 코드 추가 할 수 있다. 


먼저 우리는 작업할 AVCaptureSession 객체를 만든다. 클래스 변수로 수행할수 있다. 

let captureSession = AVCaptureSession()

AVCaptureSession 을 찾을수 없다는 에러를 볼수 있다. 


그래서 파일의 상단에 추가되어 있는지 확인해야 한다.

import AVFoundation

이제, viewDidLoad에서 우리의 품질 설정과 저장 장치를 찾는 것을 설정할수 있다.


우선, 사용가능한 장치 목록을 살펴보자.

captureSession.sessionPreset = AVCaptureSessionPresetLow
let devices = AVCaptureDevice.devices()
println(devices)

실행하면 다음과 같이 몇 가지를 볼수 있을것이다.

이것은 iPhone 6+이다. 한개의 마이크와, 전면, 후면 카메라를 볼수 있다. 우리의 목적을 위해 후면 카메라를 잡아보자.


ViewController에 다음을 추가한다. 그리고 우리가 하나를 찾은 경우 카메라 앞면을 저장한다.

import UIKit
import AVFoundation
 
class ViewController: UIViewController {
 
    let captureSession = AVCaptureSession()
 
    // If we find a device we'll store it here for later use
    var captureDevice : AVCaptureDevice?
 
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        captureSession.sessionPreset = AVCaptureSessionPresetLow
 
        let devices = AVCaptureDevice.devices()
 
        // Loop through all the capture devices on this phone
        for device in devices {
            // Make sure this particular device supports video
            if (device.hasMediaType(AVMediaTypeVideo)) {
                // Finally check the position and confirm we've got the back camera
                if(device.position == AVCaptureDevicePosition.Back) {
                    captureDevice = device as? AVCaptureDevice
                }
            }
        }
 
    }
 
}


그리고 나서 우리는 captureDevice를 설정한다. 세션을 시작하는 기능을 구현함으로써 세션을 시작하자

if captureDevice != nil {
    beginSession()
}

클래스 내에 beginSession() 구현은 나중에 한다.

func beginSession() {
    var err : NSError? = nil
    captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err))
 
    if err != nil {
        println("error: \(err?.localizedDescription)")
    }
 
    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    self.view.layer.addSublayer(previewLayer)
    previewLayer?.frame = self.view.layer.frame
    captureSession.startRunning()
}


만약 지금 여러분의 앱을 수행하면, 카메라 미리보기를 볼수 있을 것이다. 이건 정말 표준 iOS 카메라이다. 이제 초점 모드를 수정할수 있다. configureDevice()라는 새로운 메소드를 추가하고 beginSession()을 사용하여 캡처 세션을 시작하는 첫 번째 줄에 호출한다. 

func configureDevice() {
    if let device = captureDevice {
        device.lockForConfiguration(nil)
        device.focusMode = .Locked
        device.unlockForConfiguration()
    }
}

이 메소드를 추가, 장치 잠금, 초점 모드 잠금 설정 그리고 나서, 장치 잠금을 해제한다.


앱을 실행시키고 화면의 다른 부분을 탭하여 초점을 맞춘다. 기본 초점 동작은 비활성화 되어있다. 우리가 초점 제어 할수 있다는 것을 의미한다. 초점 제어를 위해 UISlider를 추가하자.


이제, 0.0~1.0 값에 기초하여 수동 초점 기능을 추가하자.

func focusTo(value : Float) {
    if let device = captureDevice {
        if(device.lockForConfiguration(nil)) {
            device.setFocusModeLockedWithLensPosition(value, completionHandler: { (time) -> Void in
                //
            })
            device.unlockForConfiguration()
        }
    }
}

첫째, 우리는 장치가 존재한다는 것을 검증한다. 그리고 나서 우리는 장치를 잠금처리 한다. 만약 잠금이 성공한다면 우리는 렌즈 초점의 포인트 '값'을 말하는 setFocusModeLockedWithLensPosition() API를 호출하며, focusTo() 메소드에 전달 된다. 

let screenWidth = UIScreen.mainScreen().bounds.size.width
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    var anyTouch = touches.anyObject() as UITouch
    var touchPercent = anyTouch.locationInView(self.view).x / screenWidth
    focusTo(Float(touchPercent))
}
 
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
    var anyTouch = touches.anyObject() as UITouch
    var touchPercent = anyTouch.locationInView(self.view).x / screenWidth
    focusTo(Float(touchPercent))
}


이것은 화면 가로 방향으로 얼마나 멀리 터치하는지에 따라 기본으로 0.0~1.0 값을 가져온다. 실행하고 화면을 왼쪽에서 오른쪽으로 손가락을 밀어 넣는다. 여러분은 이제 이 방법으로 초점 수동 조절 할 수 있다. 쉽죠?


다음 시간에는 ISO와 노출을 수동 설정하는 옵션을 추가 할것이다. 


GitHub 소스 다운로드 : Part 1 on Github


import UIKit
import AVFoundation
 
class ViewController: UIViewController {
 
    let captureSession = AVCaptureSession()
    var previewLayer : AVCaptureVideoPreviewLayer?
 
    // If we find a device we'll store it here for later use
    var captureDevice : AVCaptureDevice?
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        // Do any additional setup after loading the view, typically from a nib.
        captureSession.sessionPreset = AVCaptureSessionPresetHigh
 
        let devices = AVCaptureDevice.devices()
 
        // Loop through all the capture devices on this phone
        for device in devices {
            // Make sure this particular device supports video
            if (device.hasMediaType(AVMediaTypeVideo)) {
                // Finally check the position and confirm we've got the back camera
                if(device.position == AVCaptureDevicePosition.Back) {
                    captureDevice = device as? AVCaptureDevice
                    if captureDevice != nil {
                        println("Capture device found")
                        beginSession()
                    }
                }
            }
        }
 
    }
 
    func focusTo(value : Float) {
        if let device = captureDevice {
            if(device.lockForConfiguration(nil)) {
                device.setFocusModeLockedWithLensPosition(value, completionHandler: { (time) -> Void in
                    //
                })
                device.unlockForConfiguration()
            }
        }
    }
 
    let screenWidth = UIScreen.mainScreen().bounds.size.width
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        var anyTouch = touches.anyObject() as UITouch
        var touchPercent = anyTouch.locationInView(self.view).x / screenWidth
        focusTo(Float(touchPercent))
    }
 
    override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
        var anyTouch = touches.anyObject() as UITouch
        var touchPercent = anyTouch.locationInView(self.view).x / screenWidth
        focusTo(Float(touchPercent))
    }
 
    func configureDevice() {
        if let device = captureDevice {
            device.lockForConfiguration(nil)
            device.focusMode = .Locked
            device.unlockForConfiguration()
        }
 
    }
 
    func beginSession() {
 
        configureDevice()
 
        var err : NSError? = nil
        captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err))
 
        if err != nil {
            println("error: \(err?.localizedDescription)")
        }
 
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        self.view.layer.addSublayer(previewLayer)
        previewLayer?.frame = self.view.layer.frame
        captureSession.startRunning()
    }
 
}
저작자 표시 비영리 변경 금지
신고
Posted by 까칠코더.


티스토리 툴바