capacitor-camera-view 1.0.3 → 1.1.0

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/Package.swift CHANGED
@@ -25,4 +25,4 @@ let package = Package(
25
25
  dependencies: ["CameraViewPlugin"],
26
26
  path: "ios/Tests/CameraViewPluginTests")
27
27
  ]
28
- )
28
+ )
package/README.md CHANGED
@@ -272,16 +272,16 @@ Check if the camera view is currently running.
272
272
  ### capture(...)
273
273
 
274
274
  ```typescript
275
- capture(options: { quality: number; }) => Promise<CaptureResponse>
275
+ capture<T extends CaptureOptions>(options: T) => Promise<CaptureResponse<T>>
276
276
  ```
277
277
 
278
278
  Capture a photo using the current camera configuration.
279
279
 
280
- | Param | Type | Description |
281
- | ------------- | --------------------------------- | ------------------------------- |
282
- | **`options`** | <code>{ quality: number; }</code> | - Capture configuration options |
280
+ | Param | Type | Description |
281
+ | ------------- | -------------- | ------------------------------- |
282
+ | **`options`** | <code>T</code> | - Capture configuration options |
283
283
 
284
- **Returns:** <code>Promise&lt;<a href="#captureresponse">CaptureResponse</a>&gt;</code>
284
+ **Returns:** <code>Promise&lt;<a href="#captureresponse">CaptureResponse</a>&lt;T&gt;&gt;</code>
285
285
 
286
286
  **Since:** 1.0.0
287
287
 
@@ -291,7 +291,7 @@ Capture a photo using the current camera configuration.
291
291
  ### captureSample(...)
292
292
 
293
293
  ```typescript
294
- captureSample(options: { quality: number; }) => Promise<CaptureResponse>
294
+ captureSample<T extends CaptureOptions>(options: T) => Promise<CaptureResponse<T>>
295
295
  ```
296
296
 
297
297
  Captures a frame from the current camera preview without using the full camera capture pipeline.
@@ -304,11 +304,11 @@ On web this method does exactly the same as `capture()` as it only captures a fr
304
304
  because unfortunately [ImageCapture API](https://developer.mozilla.org/en-US/docs/Web/API/ImageCapture) is
305
305
  not yet well supported on the web.
306
306
 
307
- | Param | Type | Description |
308
- | ------------- | --------------------------------- | ------------------------------- |
309
- | **`options`** | <code>{ quality: number; }</code> | - Capture configuration options |
307
+ | Param | Type | Description |
308
+ | ------------- | -------------- | ------------------------------- |
309
+ | **`options`** | <code>T</code> | - Capture configuration options |
310
310
 
311
- **Returns:** <code>Promise&lt;<a href="#captureresponse">CaptureResponse</a>&gt;</code>
311
+ **Returns:** <code>Promise&lt;<a href="#captureresponse">CaptureResponse</a>&lt;T&gt;&gt;</code>
312
312
 
313
313
  **Since:** 1.0.0
314
314
 
@@ -517,13 +517,14 @@ Response for checking if the camera view is running.
517
517
  | **`isRunning`** | <code>boolean</code> | Indicates if the camera view is currently active and running |
518
518
 
519
519
 
520
- #### CaptureResponse
520
+ #### CaptureOptions
521
521
 
522
- Response for capturing a photo.
522
+ Configuration options for capturing photos and samples.
523
523
 
524
- | Prop | Type | Description |
525
- | ----------- | ------------------- | ----------------------------------------------- |
526
- | **`photo`** | <code>string</code> | The base64 encoded string of the captured photo |
524
+ | Prop | Type | Description | Default | Since |
525
+ | ---------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
526
+ | **`quality`** | <code>number</code> | The JPEG quality of the captured photo/sample on a scale of 0-100 | | 1.1.0 |
527
+ | **`saveToFile`** | <code>boolean</code> | If true, saves to a temporary file and returns the web path instead of base64. The web path can be used to set the src attribute of an image for efficient loading and rendering. This reduces the data that needs to be transferred over the bridge, which can improve performance especially for high-resolution images. | <code>false</code> | 1.1.0 |
527
528
 
528
529
 
529
530
  #### GetAvailableDevicesResponse
@@ -637,6 +638,15 @@ Maps to AVCaptureDevice DeviceTypes in iOS.
637
638
  <code>'wideAngle' | 'ultraWide' | 'telephoto' | 'dual' | 'dualWide' | 'triple' | 'trueDepth'</code>
638
639
 
639
640
 
641
+ #### CaptureResponse
642
+
643
+ Response for capturing a photo
644
+ This will contain either a base64 encoded string or a web path to the captured photo,
645
+ depending on the `saveToFile` option in the <a href="#captureoptions">CaptureOptions</a>.
646
+
647
+ <code>T['saveToFile'] extends true ? { /** The web path to the captured photo that can be used to set the src attribute of an image for efficient loading and rendering (when saveToFile is true) */ webPath: string; } : { /** The base64 encoded string of the captured photo (when saveToFile is false or undefined) */ photo: string; }</code>
648
+
649
+
640
650
  #### FlashMode
641
651
 
642
652
  Flash mode options for the camera.
@@ -5,6 +5,7 @@ import android.content.Context.CAMERA_SERVICE
5
5
  import android.graphics.Bitmap
6
6
  import android.hardware.camera2.CameraCharacteristics
7
7
  import android.hardware.camera2.CameraManager
8
+ import android.net.Uri
8
9
  import android.util.Base64
9
10
  import android.util.Log
10
11
  import android.view.Surface
@@ -14,7 +15,6 @@ import androidx.annotation.OptIn
14
15
  import androidx.camera.camera2.interop.Camera2CameraInfo
15
16
  import androidx.camera.camera2.interop.ExperimentalCamera2Interop
16
17
  import androidx.camera.core.CameraSelector
17
- import androidx.camera.core.ExperimentalZeroShutterLag
18
18
  import androidx.camera.core.ImageAnalysis
19
19
  import androidx.camera.core.ImageCapture
20
20
  import androidx.camera.core.ImageCaptureException
@@ -26,6 +26,8 @@ import androidx.camera.view.LifecycleCameraController
26
26
  import androidx.camera.view.PreviewView
27
27
  import androidx.core.content.ContextCompat
28
28
  import androidx.lifecycle.LifecycleOwner
29
+ import com.getcapacitor.FileUtils
30
+ import com.getcapacitor.JSObject
29
31
  import com.getcapacitor.Plugin
30
32
  import com.google.mlkit.vision.barcode.BarcodeScanner
31
33
  import com.google.mlkit.vision.barcode.BarcodeScannerOptions
@@ -36,6 +38,8 @@ import com.michaelwolz.capacitorcameraview.model.CameraDevice
36
38
  import com.michaelwolz.capacitorcameraview.model.CameraSessionConfiguration
37
39
  import com.michaelwolz.capacitorcameraview.model.ZoomFactors
38
40
  import java.io.ByteArrayOutputStream
41
+ import java.io.File
42
+ import java.io.FileOutputStream
39
43
  import java.util.concurrent.ExecutorService
40
44
  import java.util.concurrent.Executors
41
45
 
@@ -119,8 +123,11 @@ class CameraView(plugin: Plugin) {
119
123
  }
120
124
 
121
125
  /** Capture a photo with the current camera configuration */
122
- @OptIn(ExperimentalZeroShutterLag::class)
123
- fun capturePhoto(quality: Int, callback: (String?, Exception?) -> Unit) {
126
+ fun capturePhoto(
127
+ quality: Int,
128
+ saveToFile: Boolean = false,
129
+ callback: (JSObject?, Exception?) -> Unit
130
+ ) {
124
131
  val startTime = System.currentTimeMillis()
125
132
  val controller =
126
133
  this.cameraController
@@ -147,23 +154,58 @@ class CameraView(plugin: Plugin) {
147
154
  )
148
155
 
149
156
  try {
150
- controller.takePicture(
151
- cameraExecutor,
152
- object : ImageCapture.OnImageCapturedCallback() {
153
- override fun onCaptureSuccess(image: ImageProxy) {
154
- Log.d(
155
- TAG,
156
- "Image captured successfully in ${System.currentTimeMillis() - startTime}ms"
157
- )
158
- handleCaptureSuccess(image, quality, imageRotationDegrees, callback)
157
+ if (saveToFile) {
158
+ // Direct file capture - much more efficient!
159
+ val tempFile =
160
+ File.createTempFile("camera_capture_photo", ".jpg", context.cacheDir)
161
+ val outputFileOptions = ImageCapture.OutputFileOptions.Builder(tempFile).build()
162
+
163
+ controller.takePicture(
164
+ outputFileOptions,
165
+ cameraExecutor,
166
+ object : ImageCapture.OnImageSavedCallback {
167
+ override fun onImageSaved(output: ImageCapture.OutputFileResults) {
168
+ val processingTime = System.currentTimeMillis() - startTime
169
+ Log.d(TAG, "Image saved directly to file in ${processingTime}ms")
170
+
171
+ val result = JSObject().apply {
172
+ val capacitorFilePath = FileUtils.getPortablePath(
173
+ context,
174
+ pluginDelegate.bridge.localUrl,
175
+ Uri.fromFile(tempFile)
176
+ )
177
+
178
+ put("webPath", capacitorFilePath)
179
+ }
180
+ callback(result, null)
181
+ }
182
+
183
+ override fun onError(exception: ImageCaptureException) {
184
+ Log.e(TAG, "Error saving image to file", exception)
185
+ callback(null, exception)
186
+ }
159
187
  }
160
-
161
- override fun onError(exception: ImageCaptureException) {
162
- Log.e(TAG, "Error capturing image", exception)
163
- callback(null, exception)
188
+ )
189
+ } else {
190
+ // Base64 capture using ImageProxy
191
+ controller.takePicture(
192
+ cameraExecutor,
193
+ object : ImageCapture.OnImageCapturedCallback() {
194
+ override fun onCaptureSuccess(image: ImageProxy) {
195
+ Log.d(
196
+ TAG,
197
+ "Image captured successfully in ${System.currentTimeMillis() - startTime}ms"
198
+ )
199
+ handleCaptureSuccess(image, quality, imageRotationDegrees, callback)
200
+ }
201
+
202
+ override fun onError(exception: ImageCaptureException) {
203
+ Log.e(TAG, "Error capturing image", exception)
204
+ callback(null, exception)
205
+ }
164
206
  }
165
- }
166
- )
207
+ )
208
+ }
167
209
  } catch (e: Exception) {
168
210
  Log.e(TAG, "Error setting up image capture", e)
169
211
  callback(null, e)
@@ -172,20 +214,22 @@ class CameraView(plugin: Plugin) {
172
214
  }
173
215
 
174
216
  /**
175
- * Handles the successful capture of an image, converting it to a Base64 string
217
+ * Handles the successful capture of an image for base64 conversion
176
218
  */
177
219
  fun handleCaptureSuccess(
178
220
  image: ImageProxy,
179
221
  quality: Int,
180
222
  rotationDegrees: Int,
181
- callback: (String?, Exception?) -> Unit
223
+ callback: (JSObject?, Exception?) -> Unit
182
224
  ) {
183
225
  val startTime = System.currentTimeMillis()
184
226
  try {
185
- // Turn the image into a Base64 encoded string and apply rotation if necessary
186
227
  val base64String = imageProxyToBase64(image, quality, rotationDegrees)
228
+ val result = JSObject().apply {
229
+ put("photo", base64String)
230
+ }
187
231
  Log.d(TAG, "Image processed to Base64 in ${System.currentTimeMillis() - startTime}ms")
188
- callback(base64String, null)
232
+ callback(result, null)
189
233
  } catch (e: Exception) {
190
234
  Log.e(TAG, "Error processing captured image", e)
191
235
  callback(null, e)
@@ -198,7 +242,11 @@ class CameraView(plugin: Plugin) {
198
242
  * Capture a frame directly from the preview without using the full photo pipeline which is
199
243
  * faster but has lower quality.
200
244
  */
201
- fun captureSampleFromPreview(quality: Int, callback: (String?, Exception?) -> Unit) {
245
+ fun captureSampleFromPreview(
246
+ quality: Int,
247
+ saveToFile: Boolean = false,
248
+ callback: (JSObject?, Exception?) -> Unit
249
+ ) {
202
250
  val previewView =
203
251
  this.previewView
204
252
  ?: run {
@@ -207,7 +255,6 @@ class CameraView(plugin: Plugin) {
207
255
  }
208
256
 
209
257
  mainHandler.post {
210
- val outputStream = ByteArrayOutputStream()
211
258
  try {
212
259
  val bitmap =
213
260
  previewView.bitmap
@@ -216,17 +263,38 @@ class CameraView(plugin: Plugin) {
216
263
  return@post
217
264
  }
218
265
 
219
- // Convert bitmap to Base64
220
- bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)
221
- val byteArray = outputStream.toByteArray()
222
- val base64String = Base64.encodeToString(byteArray, Base64.NO_WRAP)
266
+ val result = JSObject()
267
+
268
+ if (saveToFile) {
269
+ val tempFile =
270
+ File.createTempFile("camera_capture_sample", ".jpg", context.cacheDir)
271
+
272
+ FileOutputStream(tempFile).use { outputStream ->
273
+ bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)
274
+ }
275
+
276
+ val capacitorFilePath = FileUtils.getPortablePath(
277
+ context,
278
+ pluginDelegate.bridge.localUrl,
279
+ Uri.fromFile(tempFile)
280
+ )
281
+
282
+ result.put("webPath", capacitorFilePath)
283
+ } else {
284
+ // Convert bitmap to Base64
285
+ val outputStream = ByteArrayOutputStream()
286
+ outputStream.use { stream ->
287
+ bitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream)
288
+ val byteArray = stream.toByteArray()
289
+ val base64String = Base64.encodeToString(byteArray, Base64.NO_WRAP)
290
+ result.put("photo", base64String)
291
+ }
292
+ }
223
293
 
224
- callback(base64String, null)
294
+ callback(result, null)
225
295
  } catch (e: Exception) {
226
296
  Log.e(TAG, "Error capturing preview frame", e)
227
297
  callback(null, e)
228
- } finally {
229
- outputStream.close()
230
298
  }
231
299
  }
232
300
  }
@@ -234,9 +302,9 @@ class CameraView(plugin: Plugin) {
234
302
  /** Flip between front and back cameras */
235
303
  fun flipCamera(callback: (Exception?) -> Unit) {
236
304
  currentCameraSelector = when (currentCameraSelector) {
237
- CameraSelector.DEFAULT_FRONT_CAMERA -> CameraSelector.DEFAULT_BACK_CAMERA
238
- else -> CameraSelector.DEFAULT_FRONT_CAMERA
239
- }
305
+ CameraSelector.DEFAULT_FRONT_CAMERA -> CameraSelector.DEFAULT_BACK_CAMERA
306
+ else -> CameraSelector.DEFAULT_FRONT_CAMERA
307
+ }
240
308
 
241
309
  val controller =
242
310
  this.cameraController
@@ -412,7 +480,7 @@ class CameraView(plugin: Plugin) {
412
480
  (webView.parent as? ViewGroup)?.addView(previewView, 0)
413
481
  }
414
482
 
415
- @OptIn(ExperimentalCamera2Interop::class, ExperimentalZeroShutterLag::class)
483
+ @OptIn(ExperimentalCamera2Interop::class)
416
484
  private fun initializeCamera(
417
485
  context: Context,
418
486
  lifecycleOwner: LifecycleOwner,
@@ -422,28 +490,28 @@ class CameraView(plugin: Plugin) {
422
490
  setupPreviewView(context)
423
491
 
424
492
  currentCameraSelector = if (config.position == "front") {
425
- CameraSelector.DEFAULT_FRONT_CAMERA
426
- } else {
427
- CameraSelector.DEFAULT_BACK_CAMERA
428
- }
493
+ CameraSelector.DEFAULT_FRONT_CAMERA
494
+ } else {
495
+ CameraSelector.DEFAULT_BACK_CAMERA
496
+ }
429
497
 
430
498
  if (config.deviceId != null) {
431
499
  // Prefer specific device id over position
432
500
  currentCameraSelector = CameraSelector.Builder()
433
- .addCameraFilter { cameraInfos ->
434
- cameraInfos.filter { info ->
435
- val cameraId = Camera2CameraInfo.from(info).cameraId
436
- cameraId == config.deviceId
437
- }
501
+ .addCameraFilter { cameraInfos ->
502
+ cameraInfos.filter { info ->
503
+ val cameraId = Camera2CameraInfo.from(info).cameraId
504
+ cameraId == config.deviceId
438
505
  }
439
- .build()
506
+ }
507
+ .build()
440
508
  }
441
509
 
442
510
  // Initialize camera controller
443
511
  val controller =
444
512
  LifecycleCameraController(context).apply {
445
513
  cameraSelector = currentCameraSelector
446
- imageCaptureMode = ImageCapture.CAPTURE_MODE_ZERO_SHUTTER_LAG
514
+ imageCaptureMode = ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY
447
515
  imageCaptureResolutionSelector =
448
516
  ResolutionSelector.Builder()
449
517
  .setAspectRatioStrategy(
@@ -76,17 +76,18 @@ class CameraViewPlugin : Plugin() {
76
76
  fun capture(call: PluginCall) {
77
77
  val timeStart = System.currentTimeMillis();
78
78
  val quality = call.getInt("quality") ?: 90
79
+ val saveToFile = call.getBoolean("saveToFile") ?: false
79
80
 
80
81
  if (quality !in 0..100) {
81
82
  call.reject("Quality must be between 0 and 100")
82
83
  return
83
84
  }
84
85
 
85
- implementation.capturePhoto(quality) { photo, error ->
86
+ implementation.capturePhoto(quality, saveToFile) { result, error ->
86
87
  when {
87
88
  error != null -> call.reject("Failed to capture image: ${error.message}", error)
88
- photo == null -> call.reject("No image data")
89
- else -> call.resolve(JSObject().apply { put("photo", photo) })
89
+ result == null -> call.reject("No image data")
90
+ else -> call.resolve(result)
90
91
  }
91
92
  Log.d(TAG, "capture took ${System.currentTimeMillis() - timeStart}ms")
92
93
  }
@@ -96,17 +97,18 @@ class CameraViewPlugin : Plugin() {
96
97
  fun captureSample(call: PluginCall) {
97
98
  val timeStart = System.currentTimeMillis();
98
99
  val quality = call.getInt("quality") ?: 90
100
+ val saveToFile = call.getBoolean("saveToFile") ?: false
99
101
 
100
102
  if (quality !in 0..100) {
101
103
  call.reject("Quality must be between 0 and 100")
102
104
  return
103
105
  }
104
106
 
105
- implementation.captureSampleFromPreview(quality) { photo, error ->
107
+ implementation.captureSampleFromPreview(quality, saveToFile) { result, error ->
106
108
  when {
107
109
  error != null -> call.reject("Failed to capture frame: ${error.message}", error)
108
- photo == null -> call.reject("No frame data")
109
- else -> call.resolve(JSObject().apply { put("photo", photo) })
110
+ result == null -> call.reject("No frame data")
111
+ else -> call.resolve(result)
110
112
  }
111
113
  Log.d(TAG, "captureSample took ${System.currentTimeMillis() - timeStart}ms")
112
114
  }
package/dist/docs.json CHANGED
@@ -83,27 +83,23 @@
83
83
  },
84
84
  {
85
85
  "name": "capture",
86
- "signature": "(options: { quality: number; }) => Promise<CaptureResponse>",
86
+ "signature": "<T extends CaptureOptions>(options: T) => Promise<CaptureResponse<T>>",
87
87
  "parameters": [
88
88
  {
89
89
  "name": "options",
90
90
  "docs": "- Capture configuration options",
91
- "type": "{ quality: number; }"
91
+ "type": "T"
92
92
  }
93
93
  ],
94
- "returns": "Promise<CaptureResponse>",
94
+ "returns": "Promise<CaptureResponse<T>>",
95
95
  "tags": [
96
96
  {
97
97
  "name": "param",
98
98
  "text": "options - Capture configuration options"
99
99
  },
100
- {
101
- "name": "param",
102
- "text": "options.quality - The JPEG quality of the captured photo on a scale of 0-100"
103
- },
104
100
  {
105
101
  "name": "returns",
106
- "text": "A promise that resolves with an object containing a base64 encoded string of the captured photo"
102
+ "text": "A promise that resolves with an object containing either a base64 encoded string or file path of the captured photo"
107
103
  },
108
104
  {
109
105
  "name": "since",
@@ -112,33 +108,31 @@
112
108
  ],
113
109
  "docs": "Capture a photo using the current camera configuration.",
114
110
  "complexTypes": [
115
- "CaptureResponse"
111
+ "CaptureResponse",
112
+ "T",
113
+ "CaptureOptions"
116
114
  ],
117
115
  "slug": "capture"
118
116
  },
119
117
  {
120
118
  "name": "captureSample",
121
- "signature": "(options: { quality: number; }) => Promise<CaptureResponse>",
119
+ "signature": "<T extends CaptureOptions>(options: T) => Promise<CaptureResponse<T>>",
122
120
  "parameters": [
123
121
  {
124
122
  "name": "options",
125
123
  "docs": "- Capture configuration options",
126
- "type": "{ quality: number; }"
124
+ "type": "T"
127
125
  }
128
126
  ],
129
- "returns": "Promise<CaptureResponse>",
127
+ "returns": "Promise<CaptureResponse<T>>",
130
128
  "tags": [
131
129
  {
132
130
  "name": "param",
133
131
  "text": "options - Capture configuration options"
134
132
  },
135
- {
136
- "name": "param",
137
- "text": "options.quality - The JPEG quality of the captured sample on a scale of 0-100"
138
- },
139
133
  {
140
134
  "name": "returns",
141
- "text": "A promise that resolves with an object containing a base64 encoded string of the captured sample"
135
+ "text": "A promise that resolves with an object containing either a base64 encoded string or file path of the captured sample"
142
136
  },
143
137
  {
144
138
  "name": "since",
@@ -147,7 +141,9 @@
147
141
  ],
148
142
  "docs": "Captures a frame from the current camera preview without using the full camera capture pipeline.\n\nUnlike `capture()` which may trigger hardware-level photo capture on native platforms,\nthis method quickly samples the current video stream. This is suitable computer vision or\nsimple snapshots where high fidelity is not required.\n\nOn web this method does exactly the same as `capture()` as it only captures a frame from the video stream\nbecause unfortunately [ImageCapture API](https://developer.mozilla.org/en-US/docs/Web/API/ImageCapture) is\nnot yet well supported on the web.",
149
143
  "complexTypes": [
150
- "CaptureResponse"
144
+ "CaptureResponse",
145
+ "T",
146
+ "CaptureOptions"
151
147
  ],
152
148
  "slug": "capturesample"
153
149
  },
@@ -573,23 +569,44 @@
573
569
  ]
574
570
  },
575
571
  {
576
- "name": "CaptureResponse",
577
- "slug": "captureresponse",
578
- "docs": "Response for capturing a photo.",
572
+ "name": "CaptureOptions",
573
+ "slug": "captureoptions",
574
+ "docs": "Configuration options for capturing photos and samples.",
579
575
  "tags": [
580
576
  {
581
- "text": "1.0.0",
577
+ "text": "1.1.0",
582
578
  "name": "since"
583
579
  }
584
580
  ],
585
581
  "methods": [],
586
582
  "properties": [
587
583
  {
588
- "name": "photo",
589
- "tags": [],
590
- "docs": "The base64 encoded string of the captured photo",
584
+ "name": "quality",
585
+ "tags": [
586
+ {
587
+ "text": "1.1.0",
588
+ "name": "since"
589
+ }
590
+ ],
591
+ "docs": "The JPEG quality of the captured photo/sample on a scale of 0-100",
591
592
  "complexTypes": [],
592
- "type": "string"
593
+ "type": "number"
594
+ },
595
+ {
596
+ "name": "saveToFile",
597
+ "tags": [
598
+ {
599
+ "text": "false",
600
+ "name": "default"
601
+ },
602
+ {
603
+ "text": "1.1.0",
604
+ "name": "since"
605
+ }
606
+ ],
607
+ "docs": "If true, saves to a temporary file and returns the web path instead of base64.\nThe web path can be used to set the src attribute of an image for efficient loading and rendering.\nThis reduces the data that needs to be transferred over the bridge, which can improve performance\nespecially for high-resolution images.",
608
+ "complexTypes": [],
609
+ "type": "boolean | undefined"
593
610
  }
594
611
  ]
595
612
  },
@@ -921,6 +938,19 @@
921
938
  }
922
939
  ]
923
940
  },
941
+ {
942
+ "name": "CaptureResponse",
943
+ "slug": "captureresponse",
944
+ "docs": "Response for capturing a photo\nThis will contain either a base64 encoded string or a web path to the captured photo,\ndepending on the `saveToFile` option in the CaptureOptions.",
945
+ "types": [
946
+ {
947
+ "text": "T['saveToFile'] extends true\n ? {\n /** The web path to the captured photo that can be used to set the src attribute of an image for efficient loading and rendering (when saveToFile is true) */\n webPath: string;\n }\n : {\n /** The base64 encoded string of the captured photo (when saveToFile is false or undefined) */\n photo: string;\n }",
948
+ "complexTypes": [
949
+ "T"
950
+ ]
951
+ }
952
+ ]
953
+ },
924
954
  {
925
955
  "name": "FlashMode",
926
956
  "slug": "flashmode",
@@ -34,14 +34,11 @@ export interface CameraViewPlugin {
34
34
  * Capture a photo using the current camera configuration.
35
35
  *
36
36
  * @param options - Capture configuration options
37
- * @param options.quality - The JPEG quality of the captured photo on a scale of 0-100
38
- * @returns A promise that resolves with an object containing a base64 encoded string of the captured photo
37
+ * @returns A promise that resolves with an object containing either a base64 encoded string or file path of the captured photo
39
38
  *
40
39
  * @since 1.0.0
41
40
  */
42
- capture(options: {
43
- quality: number;
44
- }): Promise<CaptureResponse>;
41
+ capture<T extends CaptureOptions>(options: T): Promise<CaptureResponse<T>>;
45
42
  /**
46
43
  * Captures a frame from the current camera preview without using the full camera capture pipeline.
47
44
  *
@@ -54,14 +51,11 @@ export interface CameraViewPlugin {
54
51
  * not yet well supported on the web.
55
52
  *
56
53
  * @param options - Capture configuration options
57
- * @param options.quality - The JPEG quality of the captured sample on a scale of 0-100
58
- * @returns A promise that resolves with an object containing a base64 encoded string of the captured sample
54
+ * @returns A promise that resolves with an object containing either a base64 encoded string or file path of the captured sample
59
55
  *
60
56
  * @since 1.0.0
61
57
  */
62
- captureSample(options: {
63
- quality: number;
64
- }): Promise<CaptureResponse>;
58
+ captureSample<T extends CaptureOptions>(options: T): Promise<CaptureResponse<T>>;
65
59
  /**
66
60
  * Switch between front and back camera.
67
61
  *
@@ -278,6 +272,27 @@ export interface CameraSessionConfiguration {
278
272
  */
279
273
  containerElementId?: string;
280
274
  }
275
+ /**
276
+ * Configuration options for capturing photos and samples.
277
+ *
278
+ * @since 1.1.0
279
+ */
280
+ export interface CaptureOptions {
281
+ /**
282
+ * The JPEG quality of the captured photo/sample on a scale of 0-100
283
+ * @since 1.1.0
284
+ */
285
+ quality: number;
286
+ /**
287
+ * If true, saves to a temporary file and returns the web path instead of base64.
288
+ * The web path can be used to set the src attribute of an image for efficient loading and rendering.
289
+ * This reduces the data that needs to be transferred over the bridge, which can improve performance
290
+ * especially for high-resolution images.
291
+ * @default false
292
+ * @since 1.1.0
293
+ */
294
+ saveToFile?: boolean;
295
+ }
281
296
  /**
282
297
  * Response for checking if the camera view is running.
283
298
  *
@@ -288,14 +303,18 @@ export interface IsRunningResponse {
288
303
  isRunning: boolean;
289
304
  }
290
305
  /**
291
- * Response for capturing a photo.
292
- *
306
+ * Response for capturing a photo
307
+ * This will contain either a base64 encoded string or a web path to the captured photo,
308
+ * depending on the `saveToFile` option in the CaptureOptions.
293
309
  * @since 1.0.0
294
310
  */
295
- export interface CaptureResponse {
296
- /** The base64 encoded string of the captured photo */
311
+ export declare type CaptureResponse<T extends CaptureOptions = CaptureOptions> = T['saveToFile'] extends true ? {
312
+ /** The web path to the captured photo that can be used to set the src attribute of an image for efficient loading and rendering (when saveToFile is true) */
313
+ webPath: string;
314
+ } : {
315
+ /** The base64 encoded string of the captured photo (when saveToFile is false or undefined) */
297
316
  photo: string;
298
- }
317
+ };
299
318
  /**
300
319
  * Response for getting available camera devices.
301
320
  *