Skip to content

Commit

Permalink
Merge pull request #20 from dokun1/pinchToZoom
Browse files Browse the repository at this point in the history
Pinch to zoom
  • Loading branch information
dokun1 authored Sep 27, 2017
2 parents 5cd51cf + 6f2efca commit 33a025e
Show file tree
Hide file tree
Showing 11 changed files with 332 additions and 29 deletions.
4 changes: 2 additions & 2 deletions Lumina.podspec
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
Pod::Spec.new do |s|
s.name = "Lumina"
s.version = "0.8.1"
s.version = "0.8.2"
s.summary = "Lumina gives you a camera for most photo processing needs, including streaming frames for CoreML live detection."
s.homepage = "https://github.com/dokun1/Lumina"
s.license = { :type => "MIT" }
s.authors = { "dokun1" => "[email protected]" }

s.requires_arc = true
s.ios.deployment_target = "10.0"
s.source = { :git => "https://github.com/dokun1/Lumina.git", :tag => "v0.8.1" }
s.source = { :git => "https://github.com/dokun1/Lumina.git", :tag => "v0.8.2" }
s.source_files = "Lumina/Lumina/*.swift"
end
2 changes: 1 addition & 1 deletion Lumina/Lumina/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.8.1</string>
<string>0.8.2</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
Expand Down
28 changes: 28 additions & 0 deletions Lumina/Lumina/LuminaCamera.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ final class LuminaCamera: NSObject {
}
}
}

var maxZoomScale: Float = MAXFLOAT

var currentZoomScale: Float = 1.0 {
didSet {
updateZoom()
}
}

fileprivate var recognizer: AnyObject?

private var _streamingModel: AnyObject?
Expand Down Expand Up @@ -231,6 +240,25 @@ final class LuminaCamera: NSObject {
}
}

// MARK: Zoom Handling

fileprivate extension LuminaCamera {
func updateZoom() {
guard let input = self.videoInput else {
return
}
let device = input.device
do {
try device.lockForConfiguration()
let newZoomScale = min(maxZoomScale, max(Float(1.0), min(currentZoomScale, Float(device.activeFormat.videoMaxZoomFactor))))
device.videoZoomFactor = CGFloat(newZoomScale)
device.unlockForConfiguration()
} catch {
device.unlockForConfiguration()
}
}
}

// MARK: Focus Handling

extension LuminaCamera {
Expand Down
86 changes: 72 additions & 14 deletions Lumina/Lumina/LuminaViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,23 @@ public enum CameraPosition {
}

/// The resolution to set the camera to at any time - refer to AVCaptureSession.Preset definitions for matching, closest as of iOS 11
public enum CameraResolution {
case low352x288
case vga640x480
case medium1280x720
case high1920x1080
case ultra3840x2160
case iframe1280x720
case iframe960x540
case photo
case lowest
case medium
case highest
case inputPriority
public enum CameraResolution: String {
case low352x288 = "Low 352x288"
case vga640x480 = "VGA 640x480"
case medium1280x720 = "Medium 1280x720"
case high1920x1080 = "HD 1920x1080"
case ultra3840x2160 = "4K 3840x2160"
case iframe1280x720 = "iFrame 1280x720"
case iframe960x540 = "iFrame 960x540"
case photo = "Photo"
case lowest = "Lowest"
case medium = "Medium"
case highest = "Highest"
case inputPriority = "Input Priority"

public static func all() -> [CameraResolution] {
return [CameraResolution.low352x288, CameraResolution.vga640x480, CameraResolution.medium1280x720, CameraResolution.high1920x1080, CameraResolution.ultra3840x2160, CameraResolution.iframe1280x720, CameraResolution.iframe960x540, CameraResolution.photo, CameraResolution.lowest, CameraResolution.medium, CameraResolution.highest, CameraResolution.inputPriority]
}

func foundationPreset() -> AVCaptureSession.Preset {
switch self {
Expand Down Expand Up @@ -157,6 +161,20 @@ public final class LuminaViewController: UIViewController {
return layer
}

private var _zoomRecognizer: UIPinchGestureRecognizer?
var zoomRecognizer: UIPinchGestureRecognizer {
if let currentRecognizer = _zoomRecognizer {
return currentRecognizer
}
let recognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchGestureRecognizer(recognizer:)))
recognizer.delegate = self
self.view.addGestureRecognizer(recognizer)
_zoomRecognizer = recognizer
return recognizer
}



private var _cancelButton: LuminaButton?
var cancelButton: LuminaButton {
if let currentButton = _cancelButton {
Expand Down Expand Up @@ -295,7 +313,7 @@ public final class LuminaViewController: UIViewController {
///
/// - Warning: If this is set, streamFrames is over-ridden to true
@available(iOS 11.0, *)
public var streamingModel: MLModel? {
open var streamingModel: MLModel? {
get {
return _streamingModel as? MLModel
}
Expand All @@ -310,6 +328,27 @@ public final class LuminaViewController: UIViewController {
}
}

/// The maximum amout of zoom that Lumina can use
///
/// - Note: Default value will rely on whatever the active device can handle, if this is not explicitly set
open var maxZoomScale: Float = MAXFLOAT {
didSet {
if let camera = camera {
camera.maxZoomScale = maxZoomScale
}
}
}

fileprivate var currentZoomScale: Float = 1.0 {
didSet {
if let camera = self.camera {
camera.currentZoomScale = currentZoomScale
}
}
}

fileprivate var beginZoomScale: Float = 1.0

/// run this in order to create Lumina
public init() {
super.init(nibName: nil, bundle: nil)
Expand Down Expand Up @@ -399,13 +438,21 @@ public final class LuminaViewController: UIViewController {
// MARK: User Interface Creation

fileprivate extension LuminaViewController {
@objc func handlePinchGestureRecognizer(recognizer: UIPinchGestureRecognizer) {
guard self.position == .back else {
return
}
currentZoomScale = min(maxZoomScale, max(1.0, beginZoomScale * Float(recognizer.scale)))
}

func createUI() {
self.view.layer.addSublayer(self.previewLayer)
self.view.addSubview(self.cancelButton)
self.view.addSubview(self.shutterButton)
self.view.addSubview(self.switchButton)
self.view.addSubview(self.torchButton)
self.view.addSubview(self.textPromptView)
self.view.addGestureRecognizer(self.zoomRecognizer)
enableUI(valid: false)
}

Expand Down Expand Up @@ -526,6 +573,17 @@ fileprivate extension LuminaViewController {
}
}

// MARK: GestureRecognizer Delegate Methods

extension LuminaViewController: UIGestureRecognizerDelegate {
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer.isKind(of: UIPinchGestureRecognizer.self) {
beginZoomScale = currentZoomScale
}
return true
}
}

// MARK: Tap to Focus Methods

extension LuminaViewController {
Expand Down
2 changes: 1 addition & 1 deletion Lumina/LuminaTests/LuminaTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// LuminaTests.swift
// LuminaTests
//
// Created by David Okun IBM on 4/21/17.
// Created by David Okun on 4/21/17.
// Copyright © 2017 David Okun. All rights reserved.
//

Expand Down
4 changes: 4 additions & 0 deletions LuminaSample/LuminaSample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
534C1E9E1F7C3C59001127BC /* ResolutionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C1E9D1F7C3C59001127BC /* ResolutionViewController.swift */; };
5365BFD41F79829800B8F338 /* ImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5365BFD31F79829800B8F338 /* ImageViewController.swift */; };
5365BFDA1F79AAA800B8F338 /* MobileNet.mlmodel in Sources */ = {isa = PBXBuildFile; fileRef = 5365BFD91F79AA9B00B8F338 /* MobileNet.mlmodel */; };
53B828F71EAAA09000E3A624 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53B828F61EAAA09000E3A624 /* AppDelegate.swift */; };
Expand All @@ -33,6 +34,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
534C1E9D1F7C3C59001127BC /* ResolutionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResolutionViewController.swift; sourceTree = "<group>"; };
5365BFD31F79829800B8F338 /* ImageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewController.swift; sourceTree = "<group>"; };
5365BFD91F79AA9B00B8F338 /* MobileNet.mlmodel */ = {isa = PBXFileReference; lastKnownFileType = file.mlmodel; name = MobileNet.mlmodel; path = LuminaSample/MobileNet.mlmodel; sourceTree = "<group>"; };
53B828F31EAAA09000E3A624 /* LuminaSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LuminaSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -80,6 +82,7 @@
53B828F61EAAA09000E3A624 /* AppDelegate.swift */,
53B828F81EAAA09000E3A624 /* ViewController.swift */,
5365BFD31F79829800B8F338 /* ImageViewController.swift */,
534C1E9D1F7C3C59001127BC /* ResolutionViewController.swift */,
53B828FA1EAAA09000E3A624 /* Main.storyboard */,
53B828FD1EAAA09000E3A624 /* Assets.xcassets */,
53B828FF1EAAA09000E3A624 /* LaunchScreen.storyboard */,
Expand Down Expand Up @@ -171,6 +174,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
534C1E9E1F7C3C59001127BC /* ResolutionViewController.swift in Sources */,
5365BFDA1F79AAA800B8F338 /* MobileNet.mlmodel in Sources */,
53B828F91EAAA09000E3A624 /* ViewController.swift in Sources */,
5365BFD41F79829800B8F338 /* ImageViewController.swift in Sources */,
Expand Down
Loading

0 comments on commit 33a025e

Please sign in to comment.