capacitor-community-multilens-camerapreview 7.1.1 → 7.1.2

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)
@@ -287,103 +293,82 @@ extension CameraController {
287
293
 
288
294
  // Restart the capture session
289
295
  captureSession.startRunning()
296
+
297
+ updateVideoOrientation()
290
298
  }
291
- func setZoom(lens: String) throws {
292
- print(lens)
299
+ func setCameraLens(lens: String) throws {
293
300
  guard let captureSession = self.captureSession, captureSession.isRunning else {
294
301
  throw CameraControllerError.captureSessionIsMissing
295
302
  }
296
-
297
- // Stop the capture session
303
+
304
+ guard self.currentCameraPosition == .rear else {
305
+ throw CameraControllerError.invalidOperation // Only allow lens switching for rear camera
306
+ }
307
+
298
308
  captureSession.stopRunning()
299
-
300
309
  captureSession.beginConfiguration()
301
310
 
302
- guard let rearCameraInput = self.rearCameraInput, captureSession.inputs.contains(rearCameraInput) else {
303
- captureSession.startRunning() // Restart before throwing
304
- throw CameraControllerError.invalidOperation
311
+ // Remove existing rear camera input
312
+ if let currentRearInput = self.rearCameraInput {
313
+ captureSession.removeInput(currentRearInput)
314
+ self.rearCameraInput = nil
305
315
  }
306
316
 
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
- )
317
+ var newRearCamera: AVCaptureDevice?
318
+ switch lens {
319
+ case "ultra":
320
+ newRearCamera = self.ultraWideCamera
321
+ case "wide":
322
+ newRearCamera = self.wideAngleCamera
323
+ case "tele":
324
+ newRearCamera = self.telephotoCamera
325
+ default:
326
+ newRearCamera = self.wideAngleCamera // Default to wide if unknown lens
331
327
  }
332
-
333
- let cameras = session.devices.compactMap { $0 }
334
- guard !cameras.isEmpty else {
335
- captureSession.startRunning() // Restart before throwing
328
+
329
+ guard let camera = newRearCamera else {
330
+ captureSession.startRunning()
336
331
  throw CameraControllerError.noCamerasAvailable
337
332
  }
338
333
 
339
- for camera in cameras {
340
- if camera.position == .front {
341
- self.frontCamera = camera
342
- }
343
-
344
- if camera.position == .back {
345
- self.rearCamera = camera
346
-
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
- }
334
+ self.rearCameraInput = try AVCaptureDeviceInput(device: camera)
335
+ if captureSession.canAddInput(self.rearCameraInput!) {
336
+ captureSession.addInput(self.rearCameraInput!)
337
+ } else {
338
+ captureSession.startRunning()
339
+ throw CameraControllerError.inputsAreInvalid
359
340
  }
341
+
360
342
  captureSession.commitConfiguration()
343
+ captureSession.startRunning()
361
344
 
362
- self.rearCameraInput = try AVCaptureDeviceInput(device: rearCamera!)
345
+ updateVideoOrientation()
346
+ }
363
347
 
364
- if captureSession.canAddInput(self.rearCameraInput!) {
365
- captureSession.addInput(self.rearCameraInput!)
366
- self.currentCameraPosition = .rear
348
+ func setZoom(zoomFactor: CGFloat) throws {
349
+ guard let captureSession = self.captureSession, captureSession.isRunning else {
350
+ throw CameraControllerError.captureSessionIsMissing
367
351
  }
368
352
 
369
- do {
370
- guard let device = self.currentCameraPosition == .rear ? rearCamera : frontCamera else {
371
- captureSession.startRunning() // Restart before returning
372
- return
373
- }
353
+ guard let device = self.currentCameraPosition == .rear ? rearCameraInput?.device : frontCameraInput?.device else {
354
+ throw CameraControllerError.noCamerasAvailable
355
+ }
374
356
 
357
+ do {
375
358
  try device.lockForConfiguration()
376
359
  defer { device.unlockForConfiguration() }
377
-
378
- device.videoZoomFactor = 1.0
379
- zoomFactor = device.videoZoomFactor
380
360
 
361
+ let minZoomFactor: CGFloat = 1.0
362
+ let maxZoomFactor = device.activeFormat.videoMaxZoomFactor
363
+
364
+ device.videoZoomFactor = max(minZoomFactor, min(zoomFactor, maxZoomFactor))
365
+ self.zoomFactor = device.videoZoomFactor
381
366
  } catch {
382
367
  debugPrint(error)
368
+ throw CameraControllerError.invalidOperation
383
369
  }
384
-
385
- // Restart the capture session
386
- captureSession.startRunning()
370
+
371
+ updateVideoOrientation()
387
372
  }
388
373
 
389
374
  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.2",
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",