2018-08-16 11:18:27 +02:00
|
|
|
//
|
|
|
|
// CameraController.swift
|
|
|
|
// CapFinder
|
|
|
|
//
|
|
|
|
// Created by User on 22.02.18.
|
|
|
|
// Copyright © 2018 User. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
|
|
|
|
protocol CameraControllerDelegate {
|
|
|
|
|
|
|
|
func didCapture(image: UIImage)
|
|
|
|
|
|
|
|
func didCancel()
|
|
|
|
}
|
|
|
|
|
|
|
|
class CameraController: UIViewController {
|
|
|
|
|
2019-03-15 13:19:19 +01:00
|
|
|
private let imageSize = 299 // New for XCode models, 227/229 for turicreate
|
2018-08-16 11:18:27 +02:00
|
|
|
|
|
|
|
// MARK: Outlets
|
|
|
|
|
|
|
|
@IBOutlet weak var imageButton: RoundedButton!
|
|
|
|
|
|
|
|
@IBOutlet weak var cropView: CropView!
|
|
|
|
|
|
|
|
@IBOutlet weak var cancelButton: RoundedButton!
|
|
|
|
|
|
|
|
@IBOutlet weak var cameraView: CameraView! {
|
|
|
|
didSet {
|
|
|
|
cameraView.configure()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var delegate: CameraControllerDelegate?
|
2019-03-15 13:19:19 +01:00
|
|
|
|
|
|
|
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
|
|
|
return .portrait
|
|
|
|
}
|
|
|
|
|
|
|
|
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
|
|
|
|
return .portrait
|
|
|
|
}
|
|
|
|
|
|
|
|
override var shouldAutorotate: Bool {
|
|
|
|
return false
|
|
|
|
}
|
2018-08-16 11:18:27 +02:00
|
|
|
|
|
|
|
// MARK: Actions
|
|
|
|
|
|
|
|
@IBAction func backButtonPressed() {
|
2019-03-15 13:19:19 +01:00
|
|
|
self.giveFeedback(.medium)
|
2018-08-16 11:18:27 +02:00
|
|
|
delegate?.didCancel()
|
|
|
|
self.dismiss(animated: true)
|
|
|
|
}
|
|
|
|
|
|
|
|
@IBAction func imageButtonPressed() {
|
2019-03-15 13:19:19 +01:00
|
|
|
self.giveFeedback(.medium)
|
2018-08-16 11:18:27 +02:00
|
|
|
imageButton.isEnabled = false
|
|
|
|
cameraView.capture()
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Life cycle
|
|
|
|
|
|
|
|
override func viewWillAppear(_ animated: Bool) {
|
|
|
|
super.viewWillAppear(animated)
|
|
|
|
|
|
|
|
cameraView.delegate = self
|
|
|
|
imageButton.imageView?.image = UIImage.templateImage(named: "camera")
|
|
|
|
setTintColor()
|
|
|
|
|
|
|
|
cameraView.launch { success, error in
|
|
|
|
guard let err = error else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
switch err {
|
|
|
|
case "No camera access": self.showNoCameraAccessAlert()
|
|
|
|
case "Camera error": self.showAlert("Unable to capture media")
|
|
|
|
default: self.showAlert("Error in camera setup")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.imageButton.isEnabled = true
|
|
|
|
}
|
|
|
|
|
|
|
|
override func viewWillDisappear(_ animated: Bool) {
|
|
|
|
super.viewWillDisappear(animated)
|
|
|
|
cameraView.complete()
|
|
|
|
}
|
|
|
|
|
|
|
|
private func setTintColor() {
|
|
|
|
let tint = AppDelegate.tintColor
|
|
|
|
cropView.lineColor = tint
|
|
|
|
imageButton.borderColor = tint
|
|
|
|
imageButton.imageView?.tintColor = tint
|
|
|
|
cancelButton.borderColor = tint
|
|
|
|
cancelButton.set(template: "cancel", with: tint)
|
|
|
|
}
|
2019-03-15 13:19:19 +01:00
|
|
|
|
|
|
|
private func giveFeedback(_ style: UIImpactFeedbackGenerator.FeedbackStyle) {
|
|
|
|
let generator = UIImpactFeedbackGenerator(style: style)
|
|
|
|
generator.impactOccurred()
|
|
|
|
}
|
2018-08-16 11:18:27 +02:00
|
|
|
|
|
|
|
// MARK: Alerts
|
|
|
|
|
|
|
|
private func showNoCameraAccessAlert() {
|
|
|
|
let alert = UIAlertController(title: "Unable to access the Camera",
|
|
|
|
message: "To enable access, go to Settings > Privacy > Camera and turn on Camera access for this app.",
|
|
|
|
preferredStyle: .alert,
|
|
|
|
blurStyle: .dark)
|
|
|
|
|
|
|
|
let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
|
|
|
|
alert.addAction(okAction)
|
|
|
|
|
|
|
|
let settingsAction = UIAlertAction(title: "Settings", style: .default, handler: { _ in
|
|
|
|
// Take the user to Settings app to possibly change permission.
|
|
|
|
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else { return }
|
|
|
|
if UIApplication.shared.canOpenURL(settingsUrl) {
|
|
|
|
UIApplication.shared.open(settingsUrl, completionHandler: nil)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
alert.addAction(settingsAction)
|
|
|
|
self.present(alert, animated: true, completion: nil)
|
|
|
|
}
|
2019-03-15 13:19:19 +01:00
|
|
|
|
|
|
|
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
|
|
cameraView.didReceiveTouch(touches.first!)
|
|
|
|
}
|
2018-08-16 11:18:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extension CameraController: PhotoCaptureHandlerDelegate {
|
|
|
|
|
|
|
|
func didCapture(_ image: UIImage?) {
|
|
|
|
event("Image captured")
|
|
|
|
let factor = CGFloat(cropView.relativeSize)
|
|
|
|
self.dismiss(animated: true)
|
|
|
|
let size = CGSize(width: imageSize, height: imageSize)
|
|
|
|
guard let img = image else {
|
|
|
|
self.error("No image captured")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
guard delegate != nil else {
|
|
|
|
self.error("No delegate")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
guard let masked = img.crop(factor: factor).circleMasked else {
|
|
|
|
self.error("Could not mask image")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only use 227 x 227 image
|
|
|
|
let scaled = masked.resize(to: size)
|
|
|
|
|
|
|
|
delegate!.didCapture(image: scaled)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension CameraController: Logger {
|
|
|
|
|
|
|
|
static var logToken = "[Camera]"
|
|
|
|
}
|