2021-02-19 08:28:05 -07:00
|
|
|
//
|
|
|
|
// CameraView+TakePhoto.swift
|
2021-06-21 14:42:46 -06:00
|
|
|
// mrousavy
|
2021-02-19 08:28:05 -07:00
|
|
|
//
|
|
|
|
// Created by Marc Rousavy on 16.12.20.
|
2021-06-01 05:07:57 -06:00
|
|
|
// Copyright © 2020 mrousavy. All rights reserved.
|
2021-02-19 08:28:05 -07:00
|
|
|
//
|
|
|
|
|
|
|
|
import AVFoundation
|
|
|
|
|
|
|
|
extension CameraView {
|
|
|
|
func takePhoto(options: NSDictionary, promise: Promise) {
|
2023-07-20 07:30:04 -06:00
|
|
|
CameraQueues.cameraQueue.async {
|
2021-06-07 05:08:40 -06:00
|
|
|
guard let photoOutput = self.photoOutput,
|
|
|
|
let videoDeviceInput = self.videoDeviceInput else {
|
|
|
|
if self.photo?.boolValue == true {
|
2021-06-09 03:14:49 -06:00
|
|
|
promise.reject(error: .session(.cameraNotReady))
|
|
|
|
return
|
2021-06-07 05:08:40 -06:00
|
|
|
} else {
|
2021-06-09 03:14:49 -06:00
|
|
|
promise.reject(error: .capture(.photoNotEnabled))
|
|
|
|
return
|
2021-06-07 05:08:40 -06:00
|
|
|
}
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
|
2021-06-10 05:49:34 -06:00
|
|
|
ReactLogger.log(level: .info, message: "Capturing photo...")
|
|
|
|
|
|
|
|
var format: [String: Any]?
|
|
|
|
// photo codec
|
2021-02-19 08:28:05 -07:00
|
|
|
if let photoCodecString = options["photoCodec"] as? String {
|
|
|
|
guard let photoCodec = AVVideoCodecType(withString: photoCodecString) else {
|
2021-06-10 05:49:34 -06:00
|
|
|
promise.reject(error: .parameter(.invalid(unionName: "PhotoCodec", receivedValue: photoCodecString)))
|
2021-06-09 03:14:49 -06:00
|
|
|
return
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
if photoOutput.availablePhotoCodecTypes.contains(photoCodec) {
|
2021-06-10 05:49:34 -06:00
|
|
|
format = [AVVideoCodecKey: photoCodec]
|
2021-02-19 08:28:05 -07:00
|
|
|
} else {
|
2021-06-10 05:49:34 -06:00
|
|
|
promise.reject(error: .capture(.invalidPhotoCodec))
|
2021-06-09 03:14:49 -06:00
|
|
|
return
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
}
|
2021-06-10 05:49:34 -06:00
|
|
|
|
|
|
|
// Create photo settings
|
|
|
|
let photoSettings = AVCapturePhotoSettings(format: format)
|
|
|
|
|
|
|
|
// default, overridable settings if high quality capture was enabled
|
|
|
|
if self.enableHighQualityPhotos?.boolValue == true {
|
|
|
|
photoSettings.isHighResolutionPhotoEnabled = true
|
|
|
|
if #available(iOS 13.0, *) {
|
|
|
|
photoSettings.photoQualityPrioritization = .quality
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// flash
|
2021-02-19 08:28:05 -07:00
|
|
|
if videoDeviceInput.device.isFlashAvailable, let flash = options["flash"] as? String {
|
|
|
|
guard let flashMode = AVCaptureDevice.FlashMode(withString: flash) else {
|
2021-06-09 03:14:49 -06:00
|
|
|
promise.reject(error: .parameter(.invalid(unionName: "FlashMode", receivedValue: flash)))
|
|
|
|
return
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
photoSettings.flashMode = flashMode
|
|
|
|
}
|
2021-06-10 05:49:34 -06:00
|
|
|
|
|
|
|
// depth data
|
2021-02-19 08:28:05 -07:00
|
|
|
photoSettings.isDepthDataDeliveryEnabled = photoOutput.isDepthDataDeliveryEnabled
|
|
|
|
if #available(iOS 12.0, *) {
|
|
|
|
photoSettings.isPortraitEffectsMatteDeliveryEnabled = photoOutput.isPortraitEffectsMatteDeliveryEnabled
|
|
|
|
}
|
2021-06-10 05:49:34 -06:00
|
|
|
|
|
|
|
// quality prioritization
|
2021-02-19 08:28:05 -07:00
|
|
|
if #available(iOS 13.0, *), let qualityPrioritization = options["qualityPrioritization"] as? String {
|
|
|
|
guard let photoQualityPrioritization = AVCapturePhotoOutput.QualityPrioritization(withString: qualityPrioritization) else {
|
2021-06-09 03:14:49 -06:00
|
|
|
promise.reject(error: .parameter(.invalid(unionName: "QualityPrioritization", receivedValue: qualityPrioritization)))
|
|
|
|
return
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
photoSettings.photoQualityPrioritization = photoQualityPrioritization
|
|
|
|
}
|
2021-06-10 05:49:34 -06:00
|
|
|
|
|
|
|
// red-eye reduction
|
2021-02-19 08:28:05 -07:00
|
|
|
if #available(iOS 12.0, *), let autoRedEyeReduction = options["enableAutoRedEyeReduction"] as? Bool {
|
|
|
|
photoSettings.isAutoRedEyeReductionEnabled = autoRedEyeReduction
|
|
|
|
}
|
2021-06-10 05:49:34 -06:00
|
|
|
|
|
|
|
// stabilization
|
2021-02-19 08:28:05 -07:00
|
|
|
if let enableAutoStabilization = options["enableAutoStabilization"] as? Bool {
|
|
|
|
photoSettings.isAutoStillImageStabilizationEnabled = enableAutoStabilization
|
|
|
|
}
|
2021-06-10 05:49:34 -06:00
|
|
|
|
|
|
|
// distortion correction
|
2021-02-19 08:28:05 -07:00
|
|
|
if #available(iOS 14.1, *), let enableAutoDistortionCorrection = options["enableAutoDistortionCorrection"] as? Bool {
|
|
|
|
photoSettings.isAutoContentAwareDistortionCorrectionEnabled = enableAutoDistortionCorrection
|
|
|
|
}
|
|
|
|
|
|
|
|
photoOutput.capturePhoto(with: photoSettings, delegate: PhotoCaptureDelegate(promise: promise))
|
2021-06-10 05:49:34 -06:00
|
|
|
|
|
|
|
// Assume that `takePhoto` is always called with the same parameters, so prepare the next call too.
|
|
|
|
photoOutput.setPreparedPhotoSettingsArray([photoSettings], completionHandler: nil)
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|