PIYO - Tech & Life -

iOSのカメラでLightroomのように撮影条件を変更する

iOS Swift

iOSのカメラというかAVFoundationにはAdobeのLightroomアプリのようにホワイトバランスやシャッタースピードなどをカスタマイズするAPIがあります。

ドキュメントを読んでみて難しい部分があったので整理しておこうと思います。

Lightroom

‎「Adobe Lightroom:写真加工・編集・高画質カメラ」をApp Storeで
‎「Adobe Lightroom:写真加工・編集・高画質カメラ」のレビューをチェック、カスタマー評価を比較、スクリーンショットと詳細情報を確認することができます。「Adobe Lightroom:写真加工・編集・高画質カメラ」をダウンロードしてiPhone、iPad、iPod touchでお楽しみください。

LightroomのiPhone版では撮影時に微調整しながら撮影できます。

↑の矢印部分をタップしてプロに切り替える(元々はAuto)と、シャッタースピードやISO感度、ホワイトバランスを調整するコントロールが現れます。ここで色々いじると設定を変えられるわけですね。

iOSでの実装

ベース部分

AVFoundationAVCapturePhotoOutputを使います。よくあるコードなので特に解説しませんが、こんな感じになりますよね。

deviceの設定をするconfigureDeviceというfunctionが最後にあります。今はオートフォーカスを有効にすることしかしていませんが、ここで色々設定を変更していきます。

import UIKit
import AVFoundation

class CameraViewController: AppViewController {

    let captureSession = AVCaptureSession()
    var photoOutput : AVCapturePhotoOutput!

    override func viewDidLoad() {
        super.viewDidLoad()
        configure()
    }

    override func viewWillAppear(_ animated: Bool) {
        captureSession.startRunning()
        super.viewWillAppear(animated)
    }

    override func viewWillDisappear(_ animated: Bool) {
        captureSession.stopRunning()
        super.viewWillDisappear(animated)
    }

    private func getDevice() -> AVCaptureDevice? {
        let discoverSession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInTelephotoCamera, .builtInWideAngleCamera], mediaType: .video, position: .back)
        return discoverSession.devices.first
    }

    private func configure() {
        if let device = getDevice() {
            do {
                try device.lockForConfiguration()
                self.configureDevice(device: device)
                device.unlockForConfiguration()
            } catch { print("error") }

            do {
                let input = try AVCaptureDeviceInput(device: device)
                captureSession.addInput(input)
            } catch { print("error") }


            photoOutput = AVCapturePhotoOutput()
            if captureSession.canAddOutput(photoOutput) {
                captureSession.addOutput(photoOutput)

                let captureVideoLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.init(session: captureSession)
                captureVideoLayer.frame = self.imageView.bounds
                captureVideoLayer.videoGravity = .resizeAspectFill
                self.imageView.layer.addSublayer(captureVideoLayer)
            }
        }
    }

    func configureDevice(device: AVCaptureDevice) {
        if device.isFocusModeSupported(.continuousAutoFocus) {
            device.focusMode = .continuousAutoFocus
        }

        // その他設定
    }
}

シャッタースピードとISO

AVCaptureDevicesetExposureModeCustomを使います。

先程のconfigureDeviceに追記するとして、たとえばシャッタースピードを1/400、ISOを800にするのであれば↓のように設定できます。

let shutterSpeed = CMTimeMake(1, 400)
device.setExposureModeCustom(duration: shutterSpeed, iso: 800, completionHandler: nil)

ホワイトバランス

ホワイトバランスのほうは少々厄介でして、iOS側のAPIはWhiteBlanceGainsというstructを使用します。

Lightroomのアプリにおけるホワイトバランスの設定は「蛍光灯」や「昼光」など、色温度ベースとなっています。そこで色温度などからWhiteBalanceGainsに変換する必要があります。

let k = 6000 // 色温度
let tint = -5 // -150.0〜+ 150.0の範囲のホワイトバランスの色合い値
let values = AVCaptureDevice.WhiteBalanceTemperatureAndTintValues(temperature: k, tint: tint)
let gains = device.deviceWhiteBalanceGains(for: values)
device.setWhiteBalanceModeLocked(with: gains, completionHandler: nil)

まず、AVCaptureDevice.WhiteBalanceTemperatureAndTintValuesを色温度と色合いの値を使って初期化し、それを元にWhiteBalanceGainsにします。次にsetWhiteBalanceModeLockedによりホワイトバランスを設定します。

こちらは色温度だけでなくtintValueの影響もあるので欲しい設定にするには微調整が必要そう。

ともかくこれでよくやりそうな設定は変更できました。