forked from WeTransfer/WeScan
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add MockCaptureDevice and tests for focus and flash states
- Loading branch information
1 parent
1723f90
commit 9831cbe
Showing
6 changed files
with
229 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,12 +52,15 @@ | |
A1F22EA5202DB3AA001723AD /* CGPoint+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F22EA4202DB3AA001723AD /* CGPoint+Utils.swift */; }; | ||
A1F22ECE2031937E001723AD /* EditScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F22ECD2031937E001723AD /* EditScanViewController.swift */; }; | ||
B9274D3A219B951000F9FCD1 /* CIImage+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9274D39219B951000F9FCD1 /* CIImage+Utils.swift */; }; | ||
B92A2C8321578D28002874E5 /* CaptureSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B92A2C8221578D28002874E5 /* CaptureSession.swift */; }; | ||
B940E38A21A77192003B3C0B /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = B940E38721A77192003B3C0B /* [email protected] */; }; | ||
B940E38B21A77192003B3C0B /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = B940E38821A77192003B3C0B /* [email protected] */; }; | ||
B940E38C21A77192003B3C0B /* enhance.png in Resources */ = {isa = PBXBuildFile; fileRef = B940E38921A77192003B3C0B /* enhance.png */; }; | ||
B940E3B821A95C44003B3C0B /* FocusRectangleViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B940E3B721A95C44003B3C0B /* FocusRectangleViewTests.swift */; }; | ||
B940E3AD21A829EE003B3C0B /* CaptureSession+Orientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B940E3AC21A829ED003B3C0B /* CaptureSession+Orientation.swift */; }; | ||
B940E3B821A95C44003B3C0B /* FocusRectangleViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B940E3B721A95C44003B3C0B /* FocusRectangleViewTests.swift */; }; | ||
B940E3D821AE0B42003B3C0B /* CaptureDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = B940E3D721AE0B42003B3C0B /* CaptureDevice.swift */; }; | ||
B940E3DA21AE2919003B3C0B /* CaptureSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B940E3D921AE2919003B3C0B /* CaptureSession.swift */; }; | ||
B940E3DC21AE2A64003B3C0B /* CaptureSession+Flash.swift in Sources */ = {isa = PBXBuildFile; fileRef = B940E3DB21AE2A64003B3C0B /* CaptureSession+Flash.swift */; }; | ||
B940E3DE21AE2A79003B3C0B /* CaptureSession+Focus.swift in Sources */ = {isa = PBXBuildFile; fileRef = B940E3DD21AE2A79003B3C0B /* CaptureSession+Focus.swift */; }; | ||
B94FBBAD2178652B001ED1B4 /* flash.png in Resources */ = {isa = PBXBuildFile; fileRef = B94FBBAA2178652B001ED1B4 /* flash.png */; }; | ||
B94FBBAE2178652B001ED1B4 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = B94FBBAB2178652B001ED1B4 /* [email protected] */; }; | ||
B94FBBAF2178652B001ED1B4 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = B94FBBAC2178652B001ED1B4 /* [email protected] */; }; | ||
|
@@ -223,16 +226,19 @@ | |
A1F22EA4202DB3AA001723AD /* CGPoint+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGPoint+Utils.swift"; sourceTree = "<group>"; }; | ||
A1F22ECD2031937E001723AD /* EditScanViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditScanViewController.swift; sourceTree = "<group>"; }; | ||
B9274D39219B951000F9FCD1 /* CIImage+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CIImage+Utils.swift"; sourceTree = "<group>"; }; | ||
B92A2C8221578D28002874E5 /* CaptureSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaptureSession.swift; sourceTree = "<group>"; }; | ||
B940E38721A77192003B3C0B /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; }; | ||
B940E38821A77192003B3C0B /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; }; | ||
B940E38921A77192003B3C0B /* enhance.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = enhance.png; sourceTree = "<group>"; }; | ||
B940E3AC21A829ED003B3C0B /* CaptureSession+Orientation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CaptureSession+Orientation.swift"; sourceTree = "<group>"; }; | ||
B940E3B721A95C44003B3C0B /* FocusRectangleViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FocusRectangleViewTests.swift; sourceTree = "<group>"; }; | ||
B940E3BD21AC2553003B3C0B /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = "<group>"; }; | ||
B940E3C521AC2560003B3C0B /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; }; | ||
B940E3C621AC2568003B3C0B /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; }; | ||
B940E3C721AC256E003B3C0B /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; }; | ||
B940E3AC21A829ED003B3C0B /* CaptureSession+Orientation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CaptureSession+Orientation.swift"; sourceTree = "<group>"; }; | ||
B940E3D721AE0B42003B3C0B /* CaptureDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaptureDevice.swift; sourceTree = "<group>"; }; | ||
B940E3D921AE2919003B3C0B /* CaptureSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaptureSession.swift; sourceTree = "<group>"; }; | ||
B940E3DB21AE2A64003B3C0B /* CaptureSession+Flash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CaptureSession+Flash.swift"; sourceTree = "<group>"; }; | ||
B940E3DD21AE2A79003B3C0B /* CaptureSession+Focus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CaptureSession+Focus.swift"; sourceTree = "<group>"; }; | ||
B94FBBAA2178652B001ED1B4 /* flash.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flash.png; sourceTree = "<group>"; }; | ||
B94FBBAB2178652B001ED1B4 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; }; | ||
B94FBBAC2178652B001ED1B4 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; }; | ||
|
@@ -422,14 +428,14 @@ | |
isa = PBXGroup; | ||
children = ( | ||
A1DF90E320358CB000841A11 /* Transformable.swift */, | ||
B940E3D721AE0B42003B3C0B /* CaptureDevice.swift */, | ||
); | ||
path = Protocols; | ||
sourceTree = "<group>"; | ||
}; | ||
A1DF90F720371A0800841A11 /* Common */ = { | ||
isa = PBXGroup; | ||
children = ( | ||
B92A2C8221578D28002874E5 /* CaptureSession.swift */, | ||
A1DF90A320331A0B00841A11 /* CIRectangleDetector.swift */, | ||
B992E830210C36A400C33A21 /* VisionRectangleDetector.swift */, | ||
A1F22E9E202C8D70001723AD /* Quadrilateral.swift */, | ||
|
@@ -484,7 +490,9 @@ | |
B940E3A021A82931003B3C0B /* Session */ = { | ||
isa = PBXGroup; | ||
children = ( | ||
B92A2C8221578D28002874E5 /* CaptureSession.swift */, | ||
B940E3D921AE2919003B3C0B /* CaptureSession.swift */, | ||
B940E3DB21AE2A64003B3C0B /* CaptureSession+Flash.swift */, | ||
B940E3DD21AE2A79003B3C0B /* CaptureSession+Focus.swift */, | ||
B940E3AC21A829ED003B3C0B /* CaptureSession+Orientation.swift */, | ||
); | ||
path = Session; | ||
|
@@ -767,12 +775,14 @@ | |
A1DF90E420358CB100841A11 /* Transformable.swift in Sources */, | ||
A1D4BD0C202C504F00FCDDEC /* ScannerViewController.swift in Sources */, | ||
A11C5B9C2046A20C005075FE /* Error.swift in Sources */, | ||
B940E3DE21AE2A79003B3C0B /* CaptureSession+Focus.swift in Sources */, | ||
B940E3DC21AE2A64003B3C0B /* CaptureSession+Flash.swift in Sources */, | ||
A1D4BD15202C6CC000FCDDEC /* Array+Utils.swift in Sources */, | ||
B92A2C8321578D28002874E5 /* CaptureSession.swift in Sources */, | ||
C3E2EB8E20B8970800A42E58 /* UIImage+Utils.swift in Sources */, | ||
A165F67E2044741B002D5ED6 /* ShutterButton.swift in Sources */, | ||
B940E3AD21A829EE003B3C0B /* CaptureSession+Orientation.swift in Sources */, | ||
B992E831210C36A400C33A21 /* VisionRectangleDetector.swift in Sources */, | ||
B940E3D821AE0B42003B3C0B /* CaptureDevice.swift in Sources */, | ||
A1F22EA5202DB3AA001723AD /* CGPoint+Utils.swift in Sources */, | ||
A14089BA204D92EA0009530F /* EditScanCornerView.swift in Sources */, | ||
A1DF90A02031D89D00841A11 /* ImageScannerController.swift in Sources */, | ||
|
@@ -783,6 +793,7 @@ | |
A1DF90F62037187500841A11 /* UIImage+Orientation.swift in Sources */, | ||
A1F22E99202C7B66001723AD /* QuadrilateralView.swift in Sources */, | ||
A194E97220431DD7003493E2 /* ReviewViewController.swift in Sources */, | ||
B940E3DA21AE2919003B3C0B /* CaptureSession.swift in Sources */, | ||
); | ||
runOnlyForDeploymentPostprocessing = 0; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// | ||
// CaptureDevice.swift | ||
// WeScan | ||
// | ||
// Created by Julian Schiavo on 28/11/2018. | ||
// Copyright © 2018 WeTransfer. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import AVFoundation | ||
|
||
protocol CaptureDevice: class { | ||
func unlockForConfiguration() | ||
func lockForConfiguration() throws | ||
|
||
var torchMode: AVCaptureDevice.TorchMode { get set } | ||
var isTorchAvailable: Bool { get } | ||
|
||
var focusMode: AVCaptureDevice.FocusMode { get set } | ||
var focusPointOfInterest: CGPoint { get set } | ||
var isFocusPointOfInterestSupported: Bool { get } | ||
func isFocusModeSupported(_ focusMode: AVCaptureDevice.FocusMode) -> Bool | ||
|
||
var exposureMode: AVCaptureDevice.ExposureMode { get set } | ||
var exposurePointOfInterest: CGPoint { get set } | ||
var isExposurePointOfInterestSupported: Bool { get } | ||
func isExposureModeSupported(_ exposureMode: AVCaptureDevice.ExposureMode) -> Bool | ||
|
||
var isSubjectAreaChangeMonitoringEnabled: Bool { get set } | ||
} | ||
|
||
extension AVCaptureDevice: CaptureDevice { } | ||
|
||
class MockCaptureDevice: CaptureDevice { | ||
func unlockForConfiguration() { | ||
return | ||
} | ||
|
||
func lockForConfiguration() throws { | ||
return | ||
} | ||
|
||
var torchMode: AVCaptureDevice.TorchMode = .off | ||
var isTorchAvailable: Bool = true | ||
|
||
var focusMode: AVCaptureDevice.FocusMode = .continuousAutoFocus | ||
var focusPointOfInterest: CGPoint = .zero | ||
var isFocusPointOfInterestSupported: Bool = true | ||
|
||
var exposureMode: AVCaptureDevice.ExposureMode = .continuousAutoExposure | ||
var exposurePointOfInterest: CGPoint = .zero | ||
var isExposurePointOfInterestSupported: Bool = true | ||
|
||
func isFocusModeSupported(_ focusMode: AVCaptureDevice.FocusMode) -> Bool { | ||
return true | ||
} | ||
|
||
func isExposureModeSupported(_ exposureMode: AVCaptureDevice.ExposureMode) -> Bool { | ||
return true | ||
} | ||
|
||
var isSubjectAreaChangeMonitoringEnabled: Bool = false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// | ||
// CaptureSession+Flash.swift | ||
// WeScan | ||
// | ||
// Created by Julian Schiavo on 28/11/2018. | ||
// Copyright © 2018 WeTransfer. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Extension to CaptureSession to manage the device flashlight | ||
extension CaptureSession { | ||
/// The possible states that the current device's flashlight can be in | ||
enum FlashState { | ||
case on | ||
case off | ||
case unavailable | ||
case unknown | ||
} | ||
|
||
/// Toggles the current device's flashlight on or off. | ||
func toggleFlash() -> FlashState { | ||
guard let device = device, device.isTorchAvailable else { return .unavailable } | ||
|
||
do { | ||
try device.lockForConfiguration() | ||
} catch { | ||
return .unknown | ||
} | ||
|
||
defer { | ||
device.unlockForConfiguration() | ||
} | ||
|
||
if device.torchMode == .on { | ||
device.torchMode = .off | ||
return .off | ||
} else if device.torchMode == .off { | ||
device.torchMode = .on | ||
return .on | ||
} | ||
|
||
return .unknown | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// | ||
// CaptureSession+Focus.swift | ||
// WeScan | ||
// | ||
// Created by Julian Schiavo on 28/11/2018. | ||
// Copyright © 2018 WeTransfer. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Extension to CaptureSession that controls auto focus | ||
extension CaptureSession { | ||
/// Sets the camera's exposure and focus point to the given point | ||
func setFocusPointToTapPoint(_ tapPoint: CGPoint) throws { | ||
guard let device = device else { | ||
let error = ImageScannerControllerError.inputDevice | ||
throw error | ||
} | ||
|
||
try device.lockForConfiguration() | ||
|
||
defer { | ||
device.unlockForConfiguration() | ||
} | ||
|
||
if device.isFocusPointOfInterestSupported && device.isFocusModeSupported(.autoFocus) { | ||
device.focusPointOfInterest = tapPoint | ||
device.focusMode = .autoFocus | ||
} | ||
|
||
if device.isExposurePointOfInterestSupported, device.isExposureModeSupported(.continuousAutoExposure) { | ||
device.exposurePointOfInterest = tapPoint | ||
device.exposureMode = .continuousAutoExposure | ||
} | ||
} | ||
|
||
/// Resets the camera's exposure and focus point to automatic | ||
func resetFocusToAuto() throws { | ||
guard let device = device else { | ||
let error = ImageScannerControllerError.inputDevice | ||
throw error | ||
} | ||
|
||
try device.lockForConfiguration() | ||
|
||
defer { | ||
device.unlockForConfiguration() | ||
} | ||
|
||
if device.isFocusPointOfInterestSupported && device.isFocusModeSupported(.continuousAutoFocus) { | ||
device.focusMode = .continuousAutoFocus | ||
} | ||
|
||
if device.isExposurePointOfInterestSupported, device.isExposureModeSupported(.continuousAutoExposure) { | ||
device.exposureMode = .continuousAutoExposure | ||
} | ||
} | ||
|
||
/// Removes an existing focus rectangle if one exists, optionally animating the exit | ||
func removeFocusRectangleIfNeeded(_ focusRectangle: FocusRectangleView?, animated: Bool) { | ||
guard let focusRectangle = focusRectangle else { return } | ||
if animated { | ||
UIView.animate(withDuration: 0.3, delay: 1.0, animations: { | ||
focusRectangle.alpha = 0.0 | ||
}, completion: { (_) in | ||
focusRectangle.removeFromSuperview() | ||
}) | ||
} else { | ||
focusRectangle.removeFromSuperview() | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.