capacitor-community-multilens-camerapreview 7.1.1 → 7.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ios/Plugin/CameraController.swift +75 -85
- package/ios/Plugin/Plugin.swift +19 -14
- package/package.json +1 -1
|
@@ -23,6 +23,10 @@ class CameraController: NSObject {
|
|
|
23
23
|
var rearCamera: AVCaptureDevice?
|
|
24
24
|
var rearCameraInput: AVCaptureDeviceInput?
|
|
25
25
|
|
|
26
|
+
var ultraWideCamera: AVCaptureDevice?
|
|
27
|
+
var wideAngleCamera: AVCaptureDevice?
|
|
28
|
+
var telephotoCamera: AVCaptureDevice?
|
|
29
|
+
|
|
26
30
|
var previewLayer: AVCaptureVideoPreviewLayer?
|
|
27
31
|
|
|
28
32
|
var flashMode = AVCaptureDevice.FlashMode.off
|
|
@@ -38,21 +42,14 @@ class CameraController: NSObject {
|
|
|
38
42
|
var zoomFactor: CGFloat = 1.0
|
|
39
43
|
}
|
|
40
44
|
extension CameraController {
|
|
41
|
-
func prepare(cameraPosition: String,
|
|
45
|
+
func prepare(cameraPosition: String, disableAudio: Bool, completionHandler: @escaping (Error?) -> Void) {
|
|
42
46
|
|
|
43
47
|
func createCaptureSession() {
|
|
44
48
|
self.captureSession = AVCaptureSession()
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
func configureCaptureDevices() throws {
|
|
48
|
-
|
|
49
|
-
if(zoomFactor == "ultra"){
|
|
50
|
-
session = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera,.builtInUltraWideCamera], mediaType: AVMediaType.video, position: .unspecified)
|
|
51
|
-
} else if(zoomFactor == "wide"){
|
|
52
|
-
session = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .unspecified)
|
|
53
|
-
} else if(zoomFactor == "tele"){
|
|
54
|
-
session = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera,.builtInTelephotoCamera], mediaType: AVMediaType.video, position: .unspecified)
|
|
55
|
-
}
|
|
52
|
+
let session = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera, .builtInUltraWideCamera, .builtInTelephotoCamera], mediaType: AVMediaType.video, position: .unspecified)
|
|
56
53
|
let cameras = session.devices.compactMap { $0 }
|
|
57
54
|
guard !cameras.isEmpty else { throw CameraControllerError.noCamerasAvailable }
|
|
58
55
|
|
|
@@ -62,11 +59,21 @@ extension CameraController {
|
|
|
62
59
|
}
|
|
63
60
|
|
|
64
61
|
if camera.position == .back {
|
|
65
|
-
|
|
62
|
+
switch camera.deviceType {
|
|
63
|
+
case .builtInWideAngleCamera:
|
|
64
|
+
self.wideAngleCamera = camera
|
|
65
|
+
case .builtInUltraWideCamera:
|
|
66
|
+
self.ultraWideCamera = camera
|
|
67
|
+
case .builtInTelephotoCamera:
|
|
68
|
+
self.telephotoCamera = camera
|
|
69
|
+
default:
|
|
70
|
+
break
|
|
71
|
+
}
|
|
72
|
+
self.rearCamera = camera // Keep a general rear camera reference
|
|
66
73
|
|
|
67
74
|
try camera.lockForConfiguration()
|
|
68
75
|
if camera.isFocusModeSupported(.continuousAutoFocus){
|
|
69
|
-
|
|
76
|
+
camera.focusMode = .continuousAutoFocus
|
|
70
77
|
}
|
|
71
78
|
camera.unlockForConfiguration()
|
|
72
79
|
}
|
|
@@ -80,8 +87,8 @@ extension CameraController {
|
|
|
80
87
|
guard let captureSession = self.captureSession else { throw CameraControllerError.captureSessionIsMissing }
|
|
81
88
|
|
|
82
89
|
if cameraPosition == "rear" {
|
|
83
|
-
if let
|
|
84
|
-
self.rearCameraInput = try AVCaptureDeviceInput(device:
|
|
90
|
+
if let wideAngleCamera = self.wideAngleCamera {
|
|
91
|
+
self.rearCameraInput = try AVCaptureDeviceInput(device: wideAngleCamera)
|
|
85
92
|
|
|
86
93
|
if captureSession.canAddInput(self.rearCameraInput!) { captureSession.addInput(self.rearCameraInput!) }
|
|
87
94
|
|
|
@@ -145,7 +152,6 @@ extension CameraController {
|
|
|
145
152
|
try configureDeviceInputs()
|
|
146
153
|
try configurePhotoOutput()
|
|
147
154
|
try configureDataOutput()
|
|
148
|
-
// try configureVideoOutput()
|
|
149
155
|
} catch {
|
|
150
156
|
DispatchQueue.main.async {
|
|
151
157
|
completionHandler(error)
|
|
@@ -285,105 +291,89 @@ extension CameraController {
|
|
|
285
291
|
|
|
286
292
|
captureSession.commitConfiguration()
|
|
287
293
|
|
|
288
|
-
// Restart the capture session
|
|
289
294
|
captureSession.startRunning()
|
|
295
|
+
|
|
296
|
+
DispatchQueue.main.async {
|
|
297
|
+
self.updateVideoOrientation()
|
|
298
|
+
}
|
|
290
299
|
}
|
|
291
|
-
func
|
|
292
|
-
print(lens)
|
|
300
|
+
func setCameraLens(lens: String) throws {
|
|
293
301
|
guard let captureSession = self.captureSession, captureSession.isRunning else {
|
|
294
302
|
throw CameraControllerError.captureSessionIsMissing
|
|
295
303
|
}
|
|
296
|
-
|
|
297
|
-
|
|
304
|
+
|
|
305
|
+
guard self.currentCameraPosition == .rear else {
|
|
306
|
+
throw CameraControllerError.invalidOperation // Only allow lens switching for rear camera
|
|
307
|
+
}
|
|
308
|
+
|
|
298
309
|
captureSession.stopRunning()
|
|
299
|
-
|
|
300
310
|
captureSession.beginConfiguration()
|
|
301
311
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
312
|
+
// Remove existing rear camera input
|
|
313
|
+
if let currentRearInput = self.rearCameraInput {
|
|
314
|
+
captureSession.removeInput(currentRearInput)
|
|
315
|
+
self.rearCameraInput = nil
|
|
305
316
|
}
|
|
306
317
|
|
|
307
|
-
var
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
position: .unspecified
|
|
318
|
-
)
|
|
319
|
-
} else if lens == "wide" {
|
|
320
|
-
session = AVCaptureDevice.DiscoverySession(
|
|
321
|
-
deviceTypes: [.builtInWideAngleCamera],
|
|
322
|
-
mediaType: AVMediaType.video,
|
|
323
|
-
position: .unspecified
|
|
324
|
-
)
|
|
325
|
-
} else if lens == "tele" {
|
|
326
|
-
session = AVCaptureDevice.DiscoverySession(
|
|
327
|
-
deviceTypes: [.builtInWideAngleCamera, .builtInTelephotoCamera],
|
|
328
|
-
mediaType: AVMediaType.video,
|
|
329
|
-
position: .unspecified
|
|
330
|
-
)
|
|
318
|
+
var newRearCamera: AVCaptureDevice?
|
|
319
|
+
switch lens {
|
|
320
|
+
case "ultra":
|
|
321
|
+
newRearCamera = self.ultraWideCamera
|
|
322
|
+
case "wide":
|
|
323
|
+
newRearCamera = self.wideAngleCamera
|
|
324
|
+
case "tele":
|
|
325
|
+
newRearCamera = self.telephotoCamera
|
|
326
|
+
default:
|
|
327
|
+
newRearCamera = self.wideAngleCamera // Default to wide if unknown lens
|
|
331
328
|
}
|
|
332
|
-
|
|
333
|
-
let
|
|
334
|
-
|
|
335
|
-
captureSession.startRunning() // Restart before throwing
|
|
329
|
+
|
|
330
|
+
guard let camera = newRearCamera else {
|
|
331
|
+
captureSession.startRunning()
|
|
336
332
|
throw CameraControllerError.noCamerasAvailable
|
|
337
333
|
}
|
|
338
334
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
335
|
+
self.rearCameraInput = try AVCaptureDeviceInput(device: camera)
|
|
336
|
+
if captureSession.canAddInput(self.rearCameraInput!) {
|
|
337
|
+
captureSession.addInput(self.rearCameraInput!)
|
|
338
|
+
} else {
|
|
339
|
+
captureSession.startRunning()
|
|
340
|
+
throw CameraControllerError.inputsAreInvalid
|
|
341
|
+
}
|
|
343
342
|
|
|
344
|
-
|
|
345
|
-
|
|
343
|
+
captureSession.commitConfiguration()
|
|
344
|
+
captureSession.startRunning()
|
|
346
345
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
camera.focusMode = .continuousAutoFocus
|
|
350
|
-
}
|
|
351
|
-
camera.unlockForConfiguration()
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
if let inputs = captureSession.inputs as? [AVCaptureDeviceInput] {
|
|
356
|
-
for input in inputs {
|
|
357
|
-
captureSession.removeInput(input)
|
|
358
|
-
}
|
|
346
|
+
DispatchQueue.main.async {
|
|
347
|
+
self.updateVideoOrientation()
|
|
359
348
|
}
|
|
360
|
-
|
|
349
|
+
}
|
|
361
350
|
|
|
362
|
-
|
|
351
|
+
func setZoom(zoomFactor: CGFloat) throws {
|
|
352
|
+
guard let captureSession = self.captureSession, captureSession.isRunning else {
|
|
353
|
+
throw CameraControllerError.captureSessionIsMissing
|
|
354
|
+
}
|
|
363
355
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
self.currentCameraPosition = .rear
|
|
356
|
+
guard let device = self.currentCameraPosition == .rear ? rearCameraInput?.device : frontCameraInput?.device else {
|
|
357
|
+
throw CameraControllerError.noCamerasAvailable
|
|
367
358
|
}
|
|
368
359
|
|
|
369
360
|
do {
|
|
370
|
-
guard let device = self.currentCameraPosition == .rear ? rearCamera : frontCamera else {
|
|
371
|
-
captureSession.startRunning() // Restart before returning
|
|
372
|
-
return
|
|
373
|
-
}
|
|
374
|
-
|
|
375
361
|
try device.lockForConfiguration()
|
|
376
362
|
defer { device.unlockForConfiguration() }
|
|
377
|
-
|
|
378
|
-
device.videoZoomFactor = 1.0
|
|
379
|
-
zoomFactor = device.videoZoomFactor
|
|
380
363
|
|
|
364
|
+
let minZoomFactor: CGFloat = 1.0
|
|
365
|
+
let maxZoomFactor = device.activeFormat.videoMaxZoomFactor
|
|
366
|
+
|
|
367
|
+
device.videoZoomFactor = max(minZoomFactor, min(zoomFactor, maxZoomFactor))
|
|
368
|
+
self.zoomFactor = device.videoZoomFactor
|
|
381
369
|
} catch {
|
|
382
370
|
debugPrint(error)
|
|
371
|
+
throw CameraControllerError.invalidOperation
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
DispatchQueue.main.async {
|
|
375
|
+
self.updateVideoOrientation()
|
|
383
376
|
}
|
|
384
|
-
|
|
385
|
-
// Restart the capture session
|
|
386
|
-
captureSession.startRunning()
|
|
387
377
|
}
|
|
388
378
|
|
|
389
379
|
func captureImage(completion: @escaping (UIImage?, Error?) -> Void) {
|
package/ios/Plugin/Plugin.swift
CHANGED
|
@@ -22,7 +22,6 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
22
22
|
var enableZoom: Bool?
|
|
23
23
|
var highResolutionOutput: Bool = false
|
|
24
24
|
var disableAudio: Bool = false
|
|
25
|
-
var zoomFactor = String()
|
|
26
25
|
|
|
27
26
|
private func currentInterfaceOrientation() -> UIInterfaceOrientation? {
|
|
28
27
|
if let window = self.webView?.window ?? self.bridge?.viewController?.view.window {
|
|
@@ -69,7 +68,7 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
69
68
|
|
|
70
69
|
@objc func start(_ call: CAPPluginCall) {
|
|
71
70
|
self.cameraPosition = call.getString("position") ?? "rear"
|
|
72
|
-
|
|
71
|
+
let zoomFactor = call.getString("zoomFactor") ?? "wide"
|
|
73
72
|
self.highResolutionOutput = call.getBool("enableHighResolution") ?? false
|
|
74
73
|
self.cameraController.highResolutionOutput = self.highResolutionOutput
|
|
75
74
|
|
|
@@ -105,13 +104,21 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
105
104
|
if self.cameraController.captureSession?.isRunning ?? false {
|
|
106
105
|
call.reject("camera already started")
|
|
107
106
|
} else {
|
|
108
|
-
self.cameraController.prepare(cameraPosition: self.cameraPosition,
|
|
107
|
+
self.cameraController.prepare(cameraPosition: self.cameraPosition, disableAudio: self.disableAudio, completionHandler: {error in
|
|
109
108
|
if let error = error {
|
|
110
109
|
print(error)
|
|
111
110
|
call.reject(error.localizedDescription)
|
|
112
111
|
return
|
|
113
112
|
}
|
|
114
113
|
let height = self.paddingBottom != nil ? self.height! - self.paddingBottom!: self.height!
|
|
114
|
+
|
|
115
|
+
// Set lens after camera is prepared
|
|
116
|
+
do {
|
|
117
|
+
try self.cameraController.setCameraLens(lens: zoomFactor)
|
|
118
|
+
} catch {
|
|
119
|
+
print("Failed to set initial lens: \(error)")
|
|
120
|
+
}
|
|
121
|
+
|
|
115
122
|
self.previewView = UIView(frame: CGRect(x: self.x ?? 0, y: self.y ?? 0, width: self.width!, height: height))
|
|
116
123
|
self.webView?.isOpaque = false
|
|
117
124
|
self.webView?.backgroundColor = UIColor.clear
|
|
@@ -135,7 +142,7 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
135
142
|
|
|
136
143
|
call.resolve()
|
|
137
144
|
|
|
138
|
-
}
|
|
145
|
+
})
|
|
139
146
|
}
|
|
140
147
|
}
|
|
141
148
|
})
|
|
@@ -177,7 +184,7 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
177
184
|
@objc func capture(_ call: CAPPluginCall) {
|
|
178
185
|
DispatchQueue.main.async {
|
|
179
186
|
|
|
180
|
-
let quality: Int
|
|
187
|
+
let quality: Int = call.getInt("quality") ?? 85
|
|
181
188
|
|
|
182
189
|
self.cameraController.captureImage { (image, error) in
|
|
183
190
|
|
|
@@ -193,9 +200,9 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
193
200
|
let imageData: Data?
|
|
194
201
|
if self.cameraController.currentCameraPosition == .front {
|
|
195
202
|
let flippedImage = image.withHorizontallyFlippedOrientation()
|
|
196
|
-
imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality
|
|
203
|
+
imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality/100))
|
|
197
204
|
} else {
|
|
198
|
-
imageData = image.jpegData(compressionQuality: CGFloat(quality
|
|
205
|
+
imageData = image.jpegData(compressionQuality: CGFloat(quality/100))
|
|
199
206
|
}
|
|
200
207
|
|
|
201
208
|
if self.storeToFile == false {
|
|
@@ -216,7 +223,7 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
216
223
|
|
|
217
224
|
@objc func captureSample(_ call: CAPPluginCall) {
|
|
218
225
|
DispatchQueue.main.async {
|
|
219
|
-
let quality: Int
|
|
226
|
+
let quality: Int = call.getInt("quality") ?? 85
|
|
220
227
|
|
|
221
228
|
self.cameraController.captureSample { image, error in
|
|
222
229
|
guard let image = image else {
|
|
@@ -228,9 +235,9 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
228
235
|
let imageData: Data?
|
|
229
236
|
if self.cameraController.currentCameraPosition == .front {
|
|
230
237
|
let flippedImage = image.withHorizontallyFlippedOrientation()
|
|
231
|
-
imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality
|
|
238
|
+
imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality/100))
|
|
232
239
|
} else {
|
|
233
|
-
imageData = image.jpegData(compressionQuality: CGFloat(quality
|
|
240
|
+
imageData = image.jpegData(compressionQuality: CGFloat(quality/100))
|
|
234
241
|
}
|
|
235
242
|
|
|
236
243
|
if self.storeToFile == false {
|
|
@@ -266,9 +273,9 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
266
273
|
}
|
|
267
274
|
}
|
|
268
275
|
@objc func setZoom(_ call: CAPPluginCall) {
|
|
269
|
-
|
|
276
|
+
let zoom = call.getDouble("zoomFactor") ?? 1.0
|
|
270
277
|
do {
|
|
271
|
-
try self.cameraController.setZoom(
|
|
278
|
+
try self.cameraController.setZoom(zoomFactor: CGFloat(zoom))
|
|
272
279
|
call.resolve()
|
|
273
280
|
} catch {
|
|
274
281
|
call.reject("failed to set zoom")
|
|
@@ -307,8 +314,6 @@ public class CameraPreviewMultiLens: CAPPlugin {
|
|
|
307
314
|
@objc func startRecordVideo(_ call: CAPPluginCall) {
|
|
308
315
|
DispatchQueue.main.async {
|
|
309
316
|
|
|
310
|
-
let _ = call.getInt("quality", 85)
|
|
311
|
-
|
|
312
317
|
self.cameraController.captureVideo { (image, error) in
|
|
313
318
|
|
|
314
319
|
guard let image = image else {
|
package/package.json
CHANGED