スポンサーリンク

【Swift】カメラアプリの作り方ご紹介。

Swift
スポンサーリンク

今回の記事はSwiftでカメラアプリの作り方をご紹介する記事です。アプリ内でカメラを表示するところまでを初心者でも分かりやすいように記載します。是非、カメラアプリを作ってみようと考えている方は参考にして見てください。

スポンサーリンク

Swiftのカメラアプリ環境構築

まずはXcodeアプリを作成するのでXcodeをインストールして使用できるまで行いましょう。

通常のアプリを作成してで環境構築完了です。

カメラをアプリで使用する際の権限設定

「info.plist」を設定し、アプリにカメラ関連の権限を付与していきます。

「Privacy-Photo Library Additions Usage Description」「Privacy-Camera Usage Description」の設定を追加しましょう。

カメラを画面に表示する方法

実装は下記です。

import UIKit
import Foundation
import AVFoundation

class ViewController: UIViewController,AVCaptureVideoDataOutputSampleBufferDelegate,UIGestureRecognizerDelegate, AVCapturePhotoCaptureDelegate {

    //カメラ関連 セッション デバイス 出力
    var session: AVCaptureSession!
    var device: AVCaptureDevice!
    var output: AVCaptureVideoDataOutput!
    //保存用Image
    var saveimg:UIImage? = nil
    // カメラ表示用imageview
    @IBOutlet weak var CameraImageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // カメラの初期設定        
        if initCamera() {
            session.startRunning()
        }else{
            assert(false) //カメラが使えない
        }
        // Do any additional setup after loading the view.
    }
    
    // カメラの準備処理
    func initCamera() -> Bool {
        //解像度 フレームレート カメラ向き
        let preset = AVCaptureSession.Preset.hd4K3840x2160
        let frame = CMTimeMake(value: 1, timescale: 20) //
        let position = AVCaptureDevice.Position.back
        
        setImageViewLayout(preset: preset)//UIImageViewの大きさを調整
        // セッションの作成.
        session = AVCaptureSession()
        // 解像度の指定.
        session.sessionPreset = preset
        // デバイス取得.
        device = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera,for: AVMediaType.video,position: position)
        //AVCaptureDevice.default(AVCaptureDevice.DeviceType.
        // VideoInputを取得.
        var input: AVCaptureDeviceInput! = nil
        do {
            input = try
                AVCaptureDeviceInput(device: device) as AVCaptureDeviceInput
        } catch let error {
            print(error)
            return false
        }
        // セッションに追加.
        if session.canAddInput(input) {
            session.addInput(input)
        } else {
            return false
        }
        // 出力先を設定
        output = AVCaptureVideoDataOutput()
        //ピクセルフォーマットを設定
        output.videoSettings =
            [ kCVPixelBufferPixelFormatTypeKey as AnyHashable as! String : Int(kCVPixelFormatType_32BGRA) ]
        //サブスレッド用のシリアルキューを用意
    
        output.setSampleBufferDelegate(self, queue: DispatchQueue.main)
        // 遅れてきたフレームは無視する
        output.alwaysDiscardsLateVideoFrames = true
        // FPSを設定
        do {
            try device.lockForConfiguration()
            device.activeVideoMinFrameDuration = frame //フレームレート
            
            device.unlockForConfiguration()
        } catch {
            return false
        }
        // セッションに追加.
        if session.canAddOutput(output) {
            session.addOutput(output)
        } else {
            return false
        }
        // カメラの向きを合わせる
        for connection in output.connections {
            if connection.isVideoOrientationSupported {
                connection.videoOrientation = AVCaptureVideoOrientation.portrait
            }
        }
        return true
    }
    // 画像を出力
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        DispatchQueue.main.async{ [self] in //非同期処理として実行
            let img = self.captureImage(sampleBuffer) //UIImageへ変換
            var resultImg: UIImage //結果を格納する
            resultImg = img
            // 表示
            self.CameraImageView.image = resultImg
            
            saveimg = resultImg
        }
    }

    // 動画のbufferを画像に変換
    func captureImage(_ sampleBuffer:CMSampleBuffer) -> UIImage{
        let imageBuffer: CVImageBuffer! = CMSampleBufferGetImageBuffer(sampleBuffer)

        // ベースアドレスをロック
        CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
        // 画像データの情報を取得
        let baseAddress: UnsafeMutableRawPointer = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)!
        let bytesPerRow: Int = CVPixelBufferGetBytesPerRow(imageBuffer)
        let width: Int = CVPixelBufferGetWidth(imageBuffer)
        let height: Int = CVPixelBufferGetHeight(imageBuffer)
        // RGB色空間を作成
        let colorSpace: CGColorSpace! = CGColorSpaceCreateDeviceRGB()
        // Bitmap graphic contextを作成
        let bitsPerCompornent: Int = 8
        let bitmapInfo = CGBitmapInfo(rawValue: (CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue) as UInt32)
        let newContext: CGContext! = CGContext(data: baseAddress, width: width, height: height, bitsPerComponent: bitsPerCompornent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) as CGContext?
        // Quartz imageを作成
        let imageRef: CGImage! = newContext!.makeImage()
        // ベースアドレスをアンロック
        CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
        // UIImageを作成
        let resultImage: UIImage = UIImage(cgImage: imageRef)
        saveimg = resultImage

        return resultImage
    }
    // カメラの表示サイズ
    func setImageViewLayout(preset: AVCaptureSession.Preset){
        let width = self.view.frame.width
        var height:CGFloat
        switch preset {
        case .photo:
            height = width * 852 / 640
        case .high:
            height = width * 1280 / 720
        case .medium:
            height = width * 480 / 360
        case .low:
            height = width * 192 / 144
        case .cif352x288:
            height = width * 352 / 288
        case .hd1280x720:
            height = width * 1280 / 720
        default:
            height = self.view.frame.height
        }
        CameraImageView.frame = CGRect(x: 0, y: 0, width: width, height: height)
    }
}

上記コードの解説を行なっていきます。まずはdelegateに下記を追加します。

,AVCaptureVideoDataOutputSampleBufferDelegate,UIGestureRecognizerDelegate, AVCapturePhotoCaptureDelegate

セッション等必要な情報を定義します。

//カメラ関連 セッション デバイス 出力
var session: AVCaptureSession!
var device: AVCaptureDevice!
var output: AVCaptureVideoDataOutput!
//保存用Image
var saveimg:UIImage? = nil

カメラを設定するためには「initCamera()」「captureOutput()」「captureOutput()」「setImageViewLayout()」の4つの関数だけで実装できます。

カメラアプリの機能追加

カメラアプリで例えば画像を撮影し、カメラロールに画像を保存したり画面サイズを変更したりなどの機能もあります。詳しい内容は下記リンクより記載しているので興味ある方は是非見て見てください。

  • カメラアプリで画像を撮影する方法
  • カメラアプリのカメラサイズを変更
  • 背面カメラと前面カメラを設定する方法

随時追加していきます。

今回の記事は以上です。他にもSwift関連の記事を記載しているので興味ある方は是非サイト内見ていってください。

本記事を読んでいただき感謝です。サイトを訪れていただいた方はプログラミング勉強中かと思いますのでプログラミング勉強のコツを合わせてご紹介。

スポンサーリンク
スポンサーリンク
スポンサーリンク

ブログに関しては500円程度かかりますが、それ以外は無料です。知識の吸収と並行してアウトプットは非常に効率が良いです。テックアカデミーに関しては講座レベルが高いにも関わらず、無料体験や人気口座も大幅値下げがあるので、重点的に学びたいものを無料体験してみてください。

転職時にも、エンジニアからテックアカデミー・Paizaは認知度が高いので、未経験入社採用を行う際履歴書で目に留まります。特にPaizaのスキルレベルA・SなどはIT業界でも評価されます。

テックアカデミー・Paizaの無料登録ができる期間中にぜひご利用してみてください。私も活用経験ありです。

Swift
スポンサーリンク
スポンサーリンク

コメント

タイトルとURLをコピーしました