2021-02-19 08:28:05 -07:00
|
|
|
//
|
|
|
|
// PhotoCaptureDelegate.swift
|
2021-06-21 14:42:46 -06:00
|
|
|
// mrousavy
|
2021-02-19 08:28:05 -07:00
|
|
|
//
|
|
|
|
// Created by Marc Rousavy on 15.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
|
|
|
|
|
|
|
|
private var delegatesReferences: [NSObject] = []
|
|
|
|
|
2021-03-09 02:53:29 -07:00
|
|
|
// MARK: - PhotoCaptureDelegate
|
|
|
|
|
2021-02-19 08:28:05 -07:00
|
|
|
class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate {
|
2021-06-09 03:14:49 -06:00
|
|
|
private let promise: Promise
|
2023-08-21 07:27:42 -06:00
|
|
|
private let enableShutterSound: Bool
|
2021-06-09 03:14:49 -06:00
|
|
|
|
2023-08-21 07:27:42 -06:00
|
|
|
required init(promise: Promise, enableShutterSound: Bool) {
|
2021-02-19 08:28:05 -07:00
|
|
|
self.promise = promise
|
2023-08-21 07:27:42 -06:00
|
|
|
self.enableShutterSound = enableShutterSound
|
2021-02-19 08:28:05 -07:00
|
|
|
super.init()
|
|
|
|
delegatesReferences.append(self)
|
|
|
|
}
|
|
|
|
|
2023-08-21 07:27:42 -06:00
|
|
|
func photoOutput(_: AVCapturePhotoOutput, willCapturePhotoFor _: AVCaptureResolvedPhotoSettings) {
|
|
|
|
if !enableShutterSound {
|
|
|
|
// disable system shutter sound (see https://stackoverflow.com/a/55235949/5281431)
|
|
|
|
AudioServicesDisposeSystemSoundID(1108)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-19 08:28:05 -07:00
|
|
|
func photoOutput(_: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
|
|
|
|
defer {
|
|
|
|
delegatesReferences.removeAll(where: { $0 == self })
|
|
|
|
}
|
2021-03-26 09:20:57 -06:00
|
|
|
if let error = error as NSError? {
|
2021-06-09 03:14:49 -06:00
|
|
|
promise.reject(error: .capture(.unknown(message: error.description)), cause: error)
|
|
|
|
return
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let error = ErrorPointer(nilLiteral: ())
|
|
|
|
guard let tempFilePath = RCTTempFilePath("jpeg", error)
|
|
|
|
else {
|
2021-06-09 03:14:49 -06:00
|
|
|
promise.reject(error: .capture(.createTempFileError), cause: error?.pointee)
|
|
|
|
return
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
let url = URL(string: "file://\(tempFilePath)")!
|
|
|
|
|
2021-06-09 03:14:49 -06:00
|
|
|
guard let data = photo.fileDataRepresentation() else {
|
|
|
|
promise.reject(error: .capture(.fileError))
|
|
|
|
return
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
try data.write(to: url)
|
|
|
|
let exif = photo.metadata["{Exif}"] as? [String: Any]
|
|
|
|
let width = exif?["PixelXDimension"]
|
|
|
|
let height = exif?["PixelYDimension"]
|
2023-08-21 04:50:14 -06:00
|
|
|
let exifOrientation = photo.metadata[kCGImagePropertyOrientation as String] as? Int ?? 0
|
|
|
|
let orientation = getOrientation(forExifOrientation: exifOrientation)
|
|
|
|
let isMirrored = getIsMirrored(forExifOrientation: exifOrientation)
|
2021-02-19 08:28:05 -07:00
|
|
|
|
2021-06-09 03:14:49 -06:00
|
|
|
promise.resolve([
|
2021-02-19 08:28:05 -07:00
|
|
|
"path": tempFilePath,
|
|
|
|
"width": width as Any,
|
|
|
|
"height": height as Any,
|
2023-08-21 04:50:14 -06:00
|
|
|
"orientation": orientation,
|
|
|
|
"isMirrored": isMirrored,
|
2021-02-19 08:28:05 -07:00
|
|
|
"isRawPhoto": photo.isRawPhoto,
|
|
|
|
"metadata": photo.metadata,
|
|
|
|
"thumbnail": photo.embeddedThumbnailPhotoFormat as Any,
|
|
|
|
])
|
|
|
|
} catch {
|
2021-06-09 03:14:49 -06:00
|
|
|
promise.reject(error: .capture(.fileError), cause: error as NSError)
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func photoOutput(_: AVCapturePhotoOutput, didFinishCaptureFor _: AVCaptureResolvedPhotoSettings, error: Error?) {
|
|
|
|
defer {
|
|
|
|
delegatesReferences.removeAll(where: { $0 == self })
|
|
|
|
}
|
2021-03-26 09:20:57 -06:00
|
|
|
if let error = error as NSError? {
|
2021-06-09 03:14:49 -06:00
|
|
|
promise.reject(error: .capture(.unknown(message: error.description)), cause: error)
|
|
|
|
return
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|
|
|
|
}
|
2023-08-21 04:50:14 -06:00
|
|
|
|
|
|
|
private func getOrientation(forExifOrientation exifOrientation: Int) -> String {
|
|
|
|
switch exifOrientation {
|
|
|
|
case 1, 2:
|
|
|
|
return "portrait"
|
|
|
|
case 3, 4:
|
|
|
|
return "portrait-upside-down"
|
|
|
|
case 5, 6:
|
|
|
|
return "landscape-left"
|
|
|
|
case 7, 8:
|
|
|
|
return "landscape-right"
|
|
|
|
default:
|
|
|
|
return "portrait"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private func getIsMirrored(forExifOrientation exifOrientation: Int) -> Bool {
|
|
|
|
switch exifOrientation {
|
|
|
|
case 2, 4, 5, 7:
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2021-02-19 08:28:05 -07:00
|
|
|
}
|