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

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

Lightroom

‎Adobe Lightroom CC
‎どこでも高品質な写真を撮影、編集、共有 Adobe Photoshop Lightroom CC mobile では、写真を撮影、編集、共有する強力で、しかも明快なソリューションをご利用いただけます。また、アップグレードすれば、モバイル、デスクトップ、ウェブなど、お使いのすべて機器からシームレスにアクセスしながら正確に制御できるプレミアム機能を利用できます。 写真撮影 • Lightroom CC のプロフェッショナル撮影モードを使用すれば、シャッターチャンスを逃さずに、スマートフォンのカメラを最大限に活用できます。 • DNG RAW 形式で写真撮影することにより、より思い通りの調整が行…

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の影響もあるので欲しい設定にするには微調整が必要そう。

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