とこなつとこなつ

swift について勉強したことの忘備録とか

AVFoundation を使ってカメラアプリを作成

撮った写真を加工してごにょごにょするアプリを作ったのでメモ。
撮った写真を画面上に表示させるだけの簡単コード。
変数名が適当ですがあくまでメモなので。。

storyboard には撮影開始ボタンと imageView を配置。
ボタンは cameraStart と接続。
imageView は captureImage と接続。

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var session : AVCaptureSession!
    var device : AVCaptureDevice!
    var imageOutput : AVCaptureStillImageOutput!
    var videoLayer : AVCaptureVideoPreviewLayer!
    var button : UIButton!
    @IBOutlet weak var captureImage: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func viewDidDisappear(animated: Bool)
    {
        // カメラの停止とメモリ解放.
        self.session.stopRunning()
        for output in self.session.outputs
        {
            self.session.removeOutput(output as! AVCaptureOutput)
        }
        for input in self.session.inputs
        {
            self.session.removeInput(input as! AVCaptureInput)
        }
        self.session = nil
    }
    
    @IBAction func camerastart(sender: AnyObject) {
        // セッションの作成.
        session = AVCaptureSession()
        
        // デバイス一覧の取得.
        let devices = AVCaptureDevice.devices()
        
        // バックカメラをmyDeviceに格納.
        for device in devices{
            if(device.position == AVCaptureDevicePosition.Back){
                self.device = device as! AVCaptureDevice
            }
        }
        
        // バックカメラからVideoInputを取得.
        do {
            let captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
            let videoInput = try AVCaptureDeviceInput(device: captureDevice)
            // セッションに追加.
            session.addInput(videoInput)
        } catch {
            
        }
        
        // 出力先を生成.
        imageOutput = AVCaptureStillImageOutput()
        
        // セッションに追加.
        session.addOutput(imageOutput)
        
        // 画像を表示するレイヤーを生成.
        videoLayer = AVCaptureVideoPreviewLayer(session: session)
        videoLayer.frame = self.view.bounds
        videoLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
        self.view.layer.addSublayer(videoLayer)
        
        // セッション開始.
        session.startRunning()
        
        // UIボタンを作成.
        button = UIButton(frame: CGRectMake(0,0,120,50))
        button.backgroundColor = UIColor.redColor();
        button.layer.masksToBounds = true
        button.setTitle("capture", forState: .Normal)
        button.layer.cornerRadius = 20.0
        button.layer.position = CGPoint(x: self.view.bounds.width/2, y:self.view.bounds.height-50)
        button.addTarget(self, action: "capture:", forControlEvents: .TouchUpInside)
        
        self.view.addSubview(button);
    }
    
    func capture(sender: UIButton) {
        // ボタンを連続して押せないようにする
        self.button.enabled = false
        let videoConnection = imageOutput.connectionWithMediaType(AVMediaTypeVideo)
        self.videoLayer.removeFromSuperlayer()
        self.button.removeFromSuperview()
        
        // 接続から画像を取得.
        self.imageOutput.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: { (imageDataBuffer, error) -> Void in
            
            // 取得したImageのDataBufferをJpegに変換.
            let imageData : NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataBuffer)
            
            // JpegからUIIMageを作成.
            let image : UIImage = UIImage(data: imageData)!
            
            self.captureImage.image = image
            // カメラをストップ
            self.session.stopRunning()
        })
    }
}

カメラを起動して写真を撮るだけなのに結構なコード書かないとだめなんですね。。。

完成品

f:id:tokonatsutan:20160314211148j:plain