ImageScannerController.swift 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //
  2. // ImageScannerController.swift
  3. // WeScan
  4. //
  5. // Created by Boris Emorine on 2/12/18.
  6. // Copyright © 2018 WeTransfer. All rights reserved.
  7. //
  8. import UIKit
  9. import AVFoundation
  10. @available(iOS 10, *)
  11. /// A set of methods that your delegate object must implement to interact with the image scanner interface.
  12. public protocol ImageScannerControllerDelegate: NSObjectProtocol {
  13. /// Tells the delegate that the user scanned a document.
  14. ///
  15. /// - Parameters:
  16. /// - scanner: The scanner controller object managing the scanning interface.
  17. /// - results: The results of the user scanning with the camera.
  18. /// - Discussion: Your delegate's implementation of this method should dismiss the image scanner controller.
  19. func imageScannerController(_ scanner: ImageScannerController, didFinishScanningWithResults results: ImageScannerResults)
  20. /// Tells the delegate that the user cancelled the scan operation.
  21. ///
  22. /// - Parameters:
  23. /// - scanner: The scanner controller object managing the scanning interface.
  24. /// - Discussion: Your delegate's implementation of this method should dismiss the image scanner controller.
  25. func imageScannerControllerDidCancel(_ scanner: ImageScannerController)
  26. /// Tells the delegate that an error occured during the user's scanning experience.
  27. ///
  28. /// - Parameters:
  29. /// - scanner: The scanner controller object managing the scanning interface.
  30. /// - error: The error that occured.
  31. func imageScannerController(_ scanner: ImageScannerController, didFailWithError error: Error)
  32. }
  33. @available(iOS 10, *)
  34. /// A view controller that manages the full flow for scanning documents.
  35. /// The `ImageScannerController` class is meant to be presented. It consists of a series of 3 different screens which guide the user:
  36. /// 1. Uses the camera to capture an image with a rectangle that has been detected.
  37. /// 2. Edit the detected rectangle.
  38. /// 3. Review the cropped down version of the rectangle.
  39. public final class ImageScannerController: UINavigationController {
  40. /// The object that acts as the delegate of the `ImageScannerController`.
  41. weak public var imageScannerDelegate: ImageScannerControllerDelegate?
  42. // MARK: - Life Cycle
  43. /// A black UIView, used to quickly display a black screen when the shutter button is presseed.
  44. internal let blackFlashView: UIView = {
  45. let view = UIView()
  46. view.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
  47. view.isHidden = true
  48. view.translatesAutoresizingMaskIntoConstraints = false
  49. return view
  50. }()
  51. public required init() {
  52. let scannerViewController = ScannerViewController()
  53. super.init(rootViewController: scannerViewController)
  54. navigationBar.tintColor = NCBrandColor.sharedInstance.brandText
  55. navigationBar.isTranslucent = false
  56. self.view.addSubview(blackFlashView)
  57. setupConstraints()
  58. }
  59. public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
  60. super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
  61. }
  62. required public init?(coder aDecoder: NSCoder) {
  63. fatalError("init(coder:) has not been implemented")
  64. }
  65. private func setupConstraints() {
  66. let blackFlashViewConstraints = [
  67. blackFlashView.topAnchor.constraint(equalTo: view.topAnchor),
  68. blackFlashView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
  69. view.bottomAnchor.constraint(equalTo: blackFlashView.bottomAnchor),
  70. view.trailingAnchor.constraint(equalTo: blackFlashView.trailingAnchor)
  71. ]
  72. NSLayoutConstraint.activate(blackFlashViewConstraints)
  73. }
  74. override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
  75. return .portrait
  76. }
  77. internal func flashToBlack() {
  78. view.bringSubviewToFront(blackFlashView)
  79. blackFlashView.isHidden = false
  80. let flashDuration = DispatchTime.now() + 0.05
  81. DispatchQueue.main.asyncAfter(deadline: flashDuration) {
  82. self.blackFlashView.isHidden = true
  83. }
  84. }
  85. }
  86. /// Data structure containing information about a scan.
  87. public struct ImageScannerResults {
  88. /// The original image taken by the user.
  89. public var originalImage: UIImage
  90. /// The deskewed and cropped orignal image using the detected rectangle.
  91. public var scannedImage: UIImage
  92. /// The detected rectangle which was used to generate the `scannedImage`.
  93. public var detectedRectangle: Quadrilateral
  94. }