capacitor-camera-view 1.0.4 → 1.1.1

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,7 +123,11 @@ class CameraView(plugin: Plugin) {
119
123
  }
120
124
 
121
125
  /** Capture a photo with the current camera configuration */
122
- fun capturePhoto(quality: Int, callback: (String?, Exception?) -> Unit) {
126
+ fun capturePhoto(
127
+ quality: Int,
128
+ saveToFile: Boolean = false,
129
+ callback: (JSObject?, Exception?) -> Unit
130
+ ) {
123
131
  val startTime = System.currentTimeMillis()
124
132
  val controller =
125
133
  this.cameraController
@@ -146,23 +154,58 @@ class CameraView(plugin: Plugin) {
146
154
  )
147
155
 
148
156
  try {
149
- controller.takePicture(
150
- cameraExecutor,
151
- object : ImageCapture.OnImageCapturedCallback() {
152
- override fun onCaptureSuccess(image: ImageProxy) {
153
- Log.d(
154
- TAG,
155
- "Image captured successfully in ${System.currentTimeMillis() - startTime}ms"
156
- )
157
- 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
+ }
158
187
  }
159
-
160
- override fun onError(exception: ImageCaptureException) {
161
- Log.e(TAG, "Error capturing image", exception)
162
- 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
+ }
163
206
  }
164
- }
165
- )
207
+ )
208
+ }
166
209
  } catch (e: Exception) {
167
210
  Log.e(TAG, "Error setting up image capture", e)
168
211
  callback(null, e)
@@ -171,20 +214,22 @@ class CameraView(plugin: Plugin) {
171
214
  }
172
215
 
173
216
  /**
174
- * Handles the successful capture of an image, converting it to a Base64 string
217
+ * Handles the successful capture of an image for base64 conversion
175
218
  */
176
219
  fun handleCaptureSuccess(
177
220
  image: ImageProxy,
178
221
  quality: Int,
179
222
  rotationDegrees: Int,
180
- callback: (String?, Exception?) -> Unit
223
+ callback: (JSObject?, Exception?) -> Unit
181
224
  ) {
182
225
  val startTime = System.currentTimeMillis()
183
226
  try {
184
- // Turn the image into a Base64 encoded string and apply rotation if necessary
185
227
  val base64String = imageProxyToBase64(image, quality, rotationDegrees)
228
+ val result = JSObject().apply {
229
+ put("photo", base64String)
230
+ }
186
231
  Log.d(TAG, "Image processed to Base64 in ${System.currentTimeMillis() - startTime}ms")
187
- callback(base64String, null)
232
+ callback(result, null)
188
233
  } catch (e: Exception) {
189
234
  Log.e(TAG, "Error processing captured image", e)
190
235
  callback(null, e)
@@ -197,7 +242,11 @@ class CameraView(plugin: Plugin) {
197
242
  * Capture a frame directly from the preview without using the full photo pipeline which is
198
243
  * faster but has lower quality.
199
244
  */
200
- fun captureSampleFromPreview(quality: Int, callback: (String?, Exception?) -> Unit) {
245
+ fun captureSampleFromPreview(
246
+ quality: Int,
247
+ saveToFile: Boolean = false,
248
+ callback: (JSObject?, Exception?) -> Unit
249
+ ) {
201
250
  val previewView =
202
251
  this.previewView
203
252
  ?: run {
@@ -206,7 +255,6 @@ class CameraView(plugin: Plugin) {
206
255
  }
207
256
 
208
257
  mainHandler.post {
209
- val outputStream = ByteArrayOutputStream()
210
258
  try {
211
259
  val bitmap =
212
260
  previewView.bitmap
@@ -215,17 +263,38 @@ class CameraView(plugin: Plugin) {
215
263
  return@post
216
264
  }
217
265
 
218
- // Convert bitmap to Base64
219
- bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)
220
- val byteArray = outputStream.toByteArray()
221
- 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
+ }
222
293
 
223
- callback(base64String, null)
294
+ callback(result, null)
224
295
  } catch (e: Exception) {
225
296
  Log.e(TAG, "Error capturing preview frame", e)
226
297
  callback(null, e)
227
- } finally {
228
- outputStream.close()
229
298
  }
230
299
  }
231
300
  }
@@ -233,9 +302,9 @@ class CameraView(plugin: Plugin) {
233
302
  /** Flip between front and back cameras */
234
303
  fun flipCamera(callback: (Exception?) -> Unit) {
235
304
  currentCameraSelector = when (currentCameraSelector) {
236
- CameraSelector.DEFAULT_FRONT_CAMERA -> CameraSelector.DEFAULT_BACK_CAMERA
237
- else -> CameraSelector.DEFAULT_FRONT_CAMERA
238
- }
305
+ CameraSelector.DEFAULT_FRONT_CAMERA -> CameraSelector.DEFAULT_BACK_CAMERA
306
+ else -> CameraSelector.DEFAULT_FRONT_CAMERA
307
+ }
239
308
 
240
309
  val controller =
241
310
  this.cameraController
@@ -421,21 +490,21 @@ class CameraView(plugin: Plugin) {
421
490
  setupPreviewView(context)
422
491
 
423
492
  currentCameraSelector = if (config.position == "front") {
424
- CameraSelector.DEFAULT_FRONT_CAMERA
425
- } else {
426
- CameraSelector.DEFAULT_BACK_CAMERA
427
- }
493
+ CameraSelector.DEFAULT_FRONT_CAMERA
494
+ } else {
495
+ CameraSelector.DEFAULT_BACK_CAMERA
496
+ }
428
497
 
429
498
  if (config.deviceId != null) {
430
499
  // Prefer specific device id over position
431
500
  currentCameraSelector = CameraSelector.Builder()
432
- .addCameraFilter { cameraInfos ->
433
- cameraInfos.filter { info ->
434
- val cameraId = Camera2CameraInfo.from(info).cameraId
435
- cameraId == config.deviceId
436
- }
501
+ .addCameraFilter { cameraInfos ->
502
+ cameraInfos.filter { info ->
503
+ val cameraId = Camera2CameraInfo.from(info).cameraId
504
+ cameraId == config.deviceId
437
505
  }
438
- .build()
506
+ }
507
+ .build()
439
508
  }
440
509
 
441
510
  // Initialize camera controller
@@ -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
  *