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.
@@ -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, zoomFactor: String, disableAudio: Bool, completionHandler: @escaping (Error?) -> Void) {
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
- var session = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera,.builtInUltraWideCamera,.builtInTelephotoCamera], mediaType: AVMediaType.video, position: .unspecified)
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
- self.rearCamera = camera
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
- camera.focusMode = .continuousAutoFocus
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 rearCamera = self.rearCamera {
84
- self.rearCameraInput = try AVCaptureDeviceInput(device: rearCamera)
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 setZoom(lens: String) throws {
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
- // Stop the capture session
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
- guard let rearCameraInput = self.rearCameraInput, captureSession.inputs.contains(rearCameraInput) else {
303
- captureSession.startRunning() // Restart before throwing
304
- throw CameraControllerError.invalidOperation
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 session = AVCaptureDevice.DiscoverySession(
308
- deviceTypes: [.builtInWideAngleCamera, .builtInUltraWideCamera, .builtInTelephotoCamera],
309
- mediaType: AVMediaType.video,
310
- position: .unspecified
311
- )
312
-
313
- if lens == "ultra" {
314
- session = AVCaptureDevice.DiscoverySession(
315
- deviceTypes: [.builtInWideAngleCamera, .builtInUltraWideCamera],
316
- mediaType: AVMediaType.video,
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 cameras = session.devices.compactMap { $0 }
334
- guard !cameras.isEmpty else {
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
- for camera in cameras {
340
- if camera.position == .front {
341
- self.frontCamera = camera
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
- if camera.position == .back {
345
- self.rearCamera = camera
343
+ captureSession.commitConfiguration()
344
+ captureSession.startRunning()
346
345
 
347
- try camera.lockForConfiguration()
348
- if camera.isFocusModeSupported(.continuousAutoFocus) {
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
- captureSession.commitConfiguration()
349
+ }
361
350
 
362
- self.rearCameraInput = try AVCaptureDeviceInput(device: rearCamera!)
351
+ func setZoom(zoomFactor: CGFloat) throws {
352
+ guard let captureSession = self.captureSession, captureSession.isRunning else {
353
+ throw CameraControllerError.captureSessionIsMissing
354
+ }
363
355
 
364
- if captureSession.canAddInput(self.rearCameraInput!) {
365
- captureSession.addInput(self.rearCameraInput!)
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) {
@@ -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
- self.zoomFactor = call.getString("zoomFactor") ?? "wide"
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, zoomFactor: self.zoomFactor, disableAudio: self.disableAudio){error in
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? = call.getInt("quality", 85)
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!/100))
203
+ imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality/100))
197
204
  } else {
198
- imageData = image.jpegData(compressionQuality: CGFloat(quality!/100))
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? = call.getInt("quality", 85)
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!/100))
238
+ imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality/100))
232
239
  } else {
233
- imageData = image.jpegData(compressionQuality: CGFloat(quality!/100))
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
- self.zoomFactor = call.getString("zoomFactor") ?? "wide"
276
+ let zoom = call.getDouble("zoomFactor") ?? 1.0
270
277
  do {
271
- try self.cameraController.setZoom(lens: self.zoomFactor)
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-community-multilens-camerapreview",
3
- "version": "7.1.1",
3
+ "version": "7.1.3",
4
4
  "description": "fork of capacitor community camera preview with support for switchting lenses",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",