対象:
Swift4

カメラの利用(AVFoundation)(Swift)

iOSでカメラを利用して、加えて画像処理等も行いたい場合、AVFoundationを利用することになるだろう。

AVFoundationを利用せずとも、UIImagePickerControllerを使えばより簡単にカメラの機能を利用できる。とにかくカメラを使いたいという場合はこちらを利用しても良いだろう。また、iOS 10以降でカメラを使用する場合、Info.plistでNSCameraUsageDescriptionキーにカメラ初回使用時のメッセージを設定等しておく必要がある。それについても以下をご参照いただきたい。

カメラの利用(UIImagePickerController)(Swift)

AVFoundationの機能を利用してカメラを利用するには、ViewController.swiftの冒頭でAVFoundationをimportする。

import UIKit
import AVFoundation

AVFoundationで重要となるのがセッション(AVCaptureSession)である。これを媒介として背面カメラとAVCaptureStillImageOutput等の出力をつなぐことになる。まずは背面カメラの取得である。

        // バックカメラを選択
        for d in AVCaptureDevice.devices() {
            // Swift 3まで
            // if (d as AnyObject).position == AVCaptureDevicePosition.back {
            if (d as AnyObject).position == AVCaptureDevice.Position.back {
                // Swift 3まで
                // device = d as? AVCaptureDevice
                device = d as AVCaptureDevice
                print("\(device!.localizedName) found.")
            }
        }

取得した背面カメラからセッションにつなぐ入力を生成する。

        // バックカメラからキャプチャ入力生成
        // Swift 3まで
        // let input: AVCaptureDeviceInput?
        let input: AVCaptureDeviceInput
        do {
            input = try AVCaptureDeviceInput(device: device)
        } catch {
            print("Caught exception!")
            return
        }

後は、先ほどの入力と出力をセッションにつなぎ、プレビュー用のAVCaptureVideoPreviewLayerを生成してViewControllerにサブレイヤとして追加する。最後にセッションをstartRunningすれば完成である。

コード全体を以下に示す。

import UIKit
import AVFoundation

class ViewController: UIViewController {
    var device: AVCaptureDevice!
    var session: AVCaptureSession!
    var output: AVCaptureStillImageOutput!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        // セッションを生成
        session = AVCaptureSession()
        // バックカメラを選択
        for d in AVCaptureDevice.devices() {
            // Swift 3まで
            // if (d as AnyObject).position == AVCaptureDevicePosition.back {
            if (d as AnyObject).position == AVCaptureDevice.Position.back {
                // Swift 3まで
                // device = d as? AVCaptureDevice
                device = d as AVCaptureDevice
                print("\(device!.localizedName) found.")
            }
        }
        // バックカメラからキャプチャ入力生成
        // Swift 3まで
        // let input: AVCaptureDeviceInput?
        let input: AVCaptureDeviceInput
        do {
            input = try AVCaptureDeviceInput(device: device)
        } catch {
            print("Caught exception!")
            return
        }
        session.addInput(input)
        output = AVCaptureStillImageOutput()
        session.addOutput(output)
        // Swift 3まで
        // session.sessionPreset = AVCaptureSessionPresetPhoto
        session.sessionPreset = .photo
        // プレビューレイヤを生成
        let previewLayer = AVCaptureVideoPreviewLayer(session: session)
        // Swift 3まで
        // previewLayer?.frame = view.bounds
        // view.layer.addSublayer(previewLayer!)
        previewLayer.frame = view.bounds
        view.layer.addSublayer(previewLayer)
        // セッションを開始
        session.startRunning()
        // 撮影ボタンを生成
        let button = UIButton()
        button.setTitle("撮影", for: .normal)
        button.contentMode = .center
        button.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
        button.backgroundColor = UIColor.blue
        //button.tintColor = UIColor.grayColor()
        //button.setTitleColor(UIColor.blue, for: UIControlState())
        button.layer.position = CGPoint(x: view.frame.width / 2, y: self.view.bounds.size.height - 80)
        button.addTarget(self, action: #selector(ViewController.shot(_:)), for: .touchUpInside)
        view.addSubview(button)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // Swift 3まで
    // func shot(_ sender: AnyObject) {
    @objc func shot(_ sender: AnyObject) {
        // Swift 3まで
        // let connection = output.connection(withMediaType: AVMediaTypeVideo)
        // output.captureStillImageAsynchronously(from: connection) {(imageDataBuffer, error) -> Void in
        //     let imageData: Data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataBuffer)
        let connection = output.connection(with: .video)
        // この辺り若干適当なので思案中
        output.captureStillImageAsynchronously(from: connection!) {(imageDataBuffer, error) -> Void in
            let imageData: Data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataBuffer!)!
            let image = UIImage(data: imageData)!
            // 画像をカメラロールに保存
            UIImageWriteToSavedPhotosAlbum(image, self, nil, nil)
        }
    }

}

作成したアプリを実行すると、以下のような画面が表示される。


(2016/05/09)
() Swift 4.0、iOS 11対応。

新着情報
【iOS Objective-C, Swift Tips】アプリアイコンにバッジを表示(Swift)
【iOS Objective-C, Swift Tips】画像の向きを指定して保存する(Swift)
【iOS Objective-C, Swift Tips】UIImagePickerControllerの表示を日本語にする(Swift)

Copyright(C) 2004-2017 モバイル開発系(K) All rights reserved.
[Home]