@capgo/camera-preview 7.6.1 → 7.7.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/README.md +143 -0
- package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +97 -0
- package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraXView.java +126 -0
- package/dist/docs.json +131 -0
- package/dist/esm/definitions.d.ts +47 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +21 -1
- package/dist/esm/web.js +19 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +19 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +19 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCameraPreviewPlugin/CameraController.swift +185 -8
- package/ios/Sources/CapgoCameraPreviewPlugin/Plugin.swift +115 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,6 +95,53 @@ await CameraPreview.deleteFile({ path: filePath })
|
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
|
|
98
|
+
## Exposure controls (iOS & Android)
|
|
99
|
+
|
|
100
|
+
This plugin exposes camera exposure controls on iOS and Android:
|
|
101
|
+
|
|
102
|
+
- Exposure modes: `"AUTO" | "LOCK" | "CONTINUOUS" | "CUSTOM"`
|
|
103
|
+
- Exposure compensation (EV bias): get range `{ min, max, step }`, read current value, and set new value
|
|
104
|
+
|
|
105
|
+
Platform notes:
|
|
106
|
+
|
|
107
|
+
- iOS: The camera starts in `CONTINUOUS` by default. Switching to `AUTO` or `CONTINUOUS` resets EV to 0. The `step` value is approximated to 0.1 since iOS does not expose the bias step.
|
|
108
|
+
- Android: AE lock/unlock and mode are handled via CameraX + Camera2 interop. The `step` value comes from CameraX `ExposureState` and may vary per device.
|
|
109
|
+
|
|
110
|
+
Example (TypeScript):
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { CameraPreview } from '@capgo/camera-preview';
|
|
114
|
+
|
|
115
|
+
// Query supported modes
|
|
116
|
+
const { modes } = await CameraPreview.getExposureModes();
|
|
117
|
+
console.log('Supported exposure modes:', modes);
|
|
118
|
+
|
|
119
|
+
// Get current mode
|
|
120
|
+
const { mode } = await CameraPreview.getExposureMode();
|
|
121
|
+
console.log('Current exposure mode:', mode);
|
|
122
|
+
|
|
123
|
+
// Set mode (AUTO | LOCK | CONTINUOUS | CUSTOM)
|
|
124
|
+
await CameraPreview.setExposureMode({ mode: 'CONTINUOUS' });
|
|
125
|
+
|
|
126
|
+
// Get EV range (with step)
|
|
127
|
+
const { min, max, step } = await CameraPreview.getExposureCompensationRange();
|
|
128
|
+
console.log('EV range:', { min, max, step });
|
|
129
|
+
|
|
130
|
+
// Read current EV
|
|
131
|
+
const { value: currentEV } = await CameraPreview.getExposureCompensation();
|
|
132
|
+
console.log('Current EV:', currentEV);
|
|
133
|
+
|
|
134
|
+
// Increment EV by one step and clamp to range
|
|
135
|
+
const nextEV = Math.max(min, Math.min(max, currentEV + step));
|
|
136
|
+
await CameraPreview.setExposureCompensation({ value: nextEV });
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Example app (Ionic):
|
|
140
|
+
|
|
141
|
+
- Exposure mode toggle (sun icon) cycles through modes.
|
|
142
|
+
- EV controls (+/−) are placed in a top‑right floating action bar, outside the preview area.
|
|
143
|
+
|
|
144
|
+
|
|
98
145
|
# Installation
|
|
99
146
|
|
|
100
147
|
```
|
|
@@ -267,6 +314,12 @@ Documentation for the [uploader](https://github.com/Cap-go/capacitor-uploader)
|
|
|
267
314
|
* [`deleteFile(...)`](#deletefile)
|
|
268
315
|
* [`getSafeAreaInsets()`](#getsafeareainsets)
|
|
269
316
|
* [`getOrientation()`](#getorientation)
|
|
317
|
+
* [`getExposureModes()`](#getexposuremodes)
|
|
318
|
+
* [`getExposureMode()`](#getexposuremode)
|
|
319
|
+
* [`setExposureMode(...)`](#setexposuremode)
|
|
320
|
+
* [`getExposureCompensationRange()`](#getexposurecompensationrange)
|
|
321
|
+
* [`getExposureCompensation()`](#getexposurecompensation)
|
|
322
|
+
* [`setExposureCompensation(...)`](#setexposurecompensation)
|
|
270
323
|
* [Interfaces](#interfaces)
|
|
271
324
|
* [Type Aliases](#type-aliases)
|
|
272
325
|
* [Enums](#enums)
|
|
@@ -828,6 +881,89 @@ Gets the current device orientation in a cross-platform format.
|
|
|
828
881
|
--------------------
|
|
829
882
|
|
|
830
883
|
|
|
884
|
+
### getExposureModes()
|
|
885
|
+
|
|
886
|
+
```typescript
|
|
887
|
+
getExposureModes() => Promise<{ modes: ExposureMode[]; }>
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
Returns the exposure modes supported by the active camera.
|
|
891
|
+
Modes can include: 'locked', 'auto', 'continuous', 'custom'.
|
|
892
|
+
|
|
893
|
+
**Returns:** <code>Promise<{ modes: ExposureMode[]; }></code>
|
|
894
|
+
|
|
895
|
+
--------------------
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
### getExposureMode()
|
|
899
|
+
|
|
900
|
+
```typescript
|
|
901
|
+
getExposureMode() => Promise<{ mode: ExposureMode; }>
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
Returns the current exposure mode.
|
|
905
|
+
|
|
906
|
+
**Returns:** <code>Promise<{ mode: <a href="#exposuremode">ExposureMode</a>; }></code>
|
|
907
|
+
|
|
908
|
+
--------------------
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
### setExposureMode(...)
|
|
912
|
+
|
|
913
|
+
```typescript
|
|
914
|
+
setExposureMode(options: { mode: ExposureMode; }) => Promise<void>
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
Sets the exposure mode.
|
|
918
|
+
|
|
919
|
+
| Param | Type |
|
|
920
|
+
| ------------- | ---------------------------------------------------------------- |
|
|
921
|
+
| **`options`** | <code>{ mode: <a href="#exposuremode">ExposureMode</a>; }</code> |
|
|
922
|
+
|
|
923
|
+
--------------------
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
### getExposureCompensationRange()
|
|
927
|
+
|
|
928
|
+
```typescript
|
|
929
|
+
getExposureCompensationRange() => Promise<{ min: number; max: number; step: number; }>
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
Returns the exposure compensation (EV bias) supported range.
|
|
933
|
+
|
|
934
|
+
**Returns:** <code>Promise<{ min: number; max: number; step: number; }></code>
|
|
935
|
+
|
|
936
|
+
--------------------
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
### getExposureCompensation()
|
|
940
|
+
|
|
941
|
+
```typescript
|
|
942
|
+
getExposureCompensation() => Promise<{ value: number; }>
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
Returns the current exposure compensation (EV bias).
|
|
946
|
+
|
|
947
|
+
**Returns:** <code>Promise<{ value: number; }></code>
|
|
948
|
+
|
|
949
|
+
--------------------
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
### setExposureCompensation(...)
|
|
953
|
+
|
|
954
|
+
```typescript
|
|
955
|
+
setExposureCompensation(options: { value: number; }) => Promise<void>
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
Sets the exposure compensation (EV bias). Value will be clamped to range.
|
|
959
|
+
|
|
960
|
+
| Param | Type |
|
|
961
|
+
| ------------- | ------------------------------- |
|
|
962
|
+
| **`options`** | <code>{ value: number; }</code> |
|
|
963
|
+
|
|
964
|
+
--------------------
|
|
965
|
+
|
|
966
|
+
|
|
831
967
|
### Interfaces
|
|
832
968
|
|
|
833
969
|
|
|
@@ -1023,6 +1159,13 @@ Canonical device orientation values across platforms.
|
|
|
1023
1159
|
<code>"portrait" | "landscape" | "landscape-left" | "landscape-right" | "portrait-upside-down" | "unknown"</code>
|
|
1024
1160
|
|
|
1025
1161
|
|
|
1162
|
+
#### ExposureMode
|
|
1163
|
+
|
|
1164
|
+
Reusable exposure mode type for cross-platform support.
|
|
1165
|
+
|
|
1166
|
+
<code>"AUTO" | "LOCK" | "CONTINUOUS" | "CUSTOM"</code>
|
|
1167
|
+
|
|
1168
|
+
|
|
1026
1169
|
### Enums
|
|
1027
1170
|
|
|
1028
1171
|
|
|
@@ -82,6 +82,103 @@ public class CameraPreview
|
|
|
82
82
|
private int lastOrientation = Configuration.ORIENTATION_UNDEFINED;
|
|
83
83
|
|
|
84
84
|
@PluginMethod
|
|
85
|
+
public void getExposureModes(PluginCall call) {
|
|
86
|
+
if (cameraXView == null || !cameraXView.isRunning()) {
|
|
87
|
+
call.reject("Camera is not running");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
JSArray arr = new JSArray();
|
|
91
|
+
for (String m : cameraXView.getExposureModes()) arr.put(m);
|
|
92
|
+
JSObject ret = new JSObject();
|
|
93
|
+
ret.put("modes", arr);
|
|
94
|
+
call.resolve(ret);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@PluginMethod
|
|
98
|
+
public void getExposureMode(PluginCall call) {
|
|
99
|
+
if (cameraXView == null || !cameraXView.isRunning()) {
|
|
100
|
+
call.reject("Camera is not running");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
JSObject ret = new JSObject();
|
|
104
|
+
ret.put("mode", cameraXView.getExposureMode());
|
|
105
|
+
call.resolve(ret);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@PluginMethod
|
|
109
|
+
public void setExposureMode(PluginCall call) {
|
|
110
|
+
if (cameraXView == null || !cameraXView.isRunning()) {
|
|
111
|
+
call.reject("Camera is not running");
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
String mode = call.getString("mode");
|
|
115
|
+
if (mode == null || mode.isEmpty()) {
|
|
116
|
+
call.reject("mode parameter is required");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
cameraXView.setExposureMode(mode);
|
|
121
|
+
call.resolve();
|
|
122
|
+
} catch (Exception e) {
|
|
123
|
+
call.reject("Failed to set exposure mode: " + e.getMessage());
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@PluginMethod
|
|
128
|
+
public void getExposureCompensationRange(PluginCall call) {
|
|
129
|
+
if (cameraXView == null || !cameraXView.isRunning()) {
|
|
130
|
+
call.reject("Camera is not running");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
float[] range = cameraXView.getExposureCompensationRange();
|
|
135
|
+
JSObject ret = new JSObject();
|
|
136
|
+
ret.put("min", range[0]);
|
|
137
|
+
ret.put("max", range[1]);
|
|
138
|
+
ret.put("step", range.length > 2 ? range[2] : 0.1);
|
|
139
|
+
call.resolve(ret);
|
|
140
|
+
} catch (Exception e) {
|
|
141
|
+
call.reject(
|
|
142
|
+
"Failed to get exposure compensation range: " + e.getMessage()
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@PluginMethod
|
|
148
|
+
public void getExposureCompensation(PluginCall call) {
|
|
149
|
+
if (cameraXView == null || !cameraXView.isRunning()) {
|
|
150
|
+
call.reject("Camera is not running");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
float value = cameraXView.getExposureCompensation();
|
|
155
|
+
JSObject ret = new JSObject();
|
|
156
|
+
ret.put("value", value);
|
|
157
|
+
call.resolve(ret);
|
|
158
|
+
} catch (Exception e) {
|
|
159
|
+
call.reject("Failed to get exposure compensation: " + e.getMessage());
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@PluginMethod
|
|
164
|
+
public void setExposureCompensation(PluginCall call) {
|
|
165
|
+
if (cameraXView == null || !cameraXView.isRunning()) {
|
|
166
|
+
call.reject("Camera is not running");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
Float value = call.getFloat("value");
|
|
170
|
+
if (value == null) {
|
|
171
|
+
call.reject("value parameter is required");
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
cameraXView.setExposureCompensation(value);
|
|
176
|
+
call.resolve();
|
|
177
|
+
} catch (Exception e) {
|
|
178
|
+
call.reject("Failed to set exposure compensation: " + e.getMessage());
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
85
182
|
public void getOrientation(PluginCall call) {
|
|
86
183
|
int orientation = getContext()
|
|
87
184
|
.getResources()
|
|
@@ -12,6 +12,7 @@ import android.graphics.drawable.GradientDrawable;
|
|
|
12
12
|
import android.hardware.camera2.CameraAccessException;
|
|
13
13
|
import android.hardware.camera2.CameraCharacteristics;
|
|
14
14
|
import android.hardware.camera2.CameraManager;
|
|
15
|
+
import android.hardware.camera2.CaptureRequest;
|
|
15
16
|
import android.location.Location;
|
|
16
17
|
import android.media.MediaScannerConnection;
|
|
17
18
|
import android.os.Build;
|
|
@@ -19,6 +20,8 @@ import android.os.Environment;
|
|
|
19
20
|
import android.util.Base64;
|
|
20
21
|
import android.util.DisplayMetrics;
|
|
21
22
|
import android.util.Log;
|
|
23
|
+
import android.util.Range;
|
|
24
|
+
import android.util.Rational;
|
|
22
25
|
import android.util.Size;
|
|
23
26
|
import android.view.MotionEvent;
|
|
24
27
|
import android.view.View;
|
|
@@ -30,12 +33,15 @@ import android.widget.FrameLayout;
|
|
|
30
33
|
import androidx.annotation.NonNull;
|
|
31
34
|
import androidx.annotation.OptIn;
|
|
32
35
|
import androidx.annotation.RequiresApi;
|
|
36
|
+
import androidx.camera.camera2.interop.Camera2CameraControl;
|
|
33
37
|
import androidx.camera.camera2.interop.Camera2CameraInfo;
|
|
38
|
+
import androidx.camera.camera2.interop.CaptureRequestOptions;
|
|
34
39
|
import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
|
|
35
40
|
import androidx.camera.core.AspectRatio;
|
|
36
41
|
import androidx.camera.core.Camera;
|
|
37
42
|
import androidx.camera.core.CameraInfo;
|
|
38
43
|
import androidx.camera.core.CameraSelector;
|
|
44
|
+
import androidx.camera.core.ExposureState;
|
|
39
45
|
import androidx.camera.core.FocusMeteringAction;
|
|
40
46
|
import androidx.camera.core.FocusMeteringResult;
|
|
41
47
|
import androidx.camera.core.ImageCapture;
|
|
@@ -69,6 +75,7 @@ import java.nio.ByteBuffer;
|
|
|
69
75
|
import java.text.SimpleDateFormat;
|
|
70
76
|
import java.util.ArrayList;
|
|
71
77
|
import java.util.Arrays;
|
|
78
|
+
import java.util.Arrays;
|
|
72
79
|
import java.util.Collections;
|
|
73
80
|
import java.util.List;
|
|
74
81
|
import java.util.Locale;
|
|
@@ -115,6 +122,7 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
|
|
|
115
122
|
private boolean isRunning = false;
|
|
116
123
|
private Size currentPreviewResolution = null;
|
|
117
124
|
private ListenableFuture<FocusMeteringResult> currentFocusFuture = null; // Track current focus operation
|
|
125
|
+
private String currentExposureMode = "CONTINUOUS"; // Default behavior
|
|
118
126
|
|
|
119
127
|
public CameraXView(Context context, WebView webView) {
|
|
120
128
|
this.context = context;
|
|
@@ -1807,6 +1815,22 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
|
|
|
1807
1815
|
currentFocusFuture.cancel(true);
|
|
1808
1816
|
}
|
|
1809
1817
|
|
|
1818
|
+
// Reset exposure compensation to 0 on tap-to-focus
|
|
1819
|
+
try {
|
|
1820
|
+
ExposureState state = camera.getCameraInfo().getExposureState();
|
|
1821
|
+
Range<Integer> range = state.getExposureCompensationRange();
|
|
1822
|
+
int zeroIdx = 0;
|
|
1823
|
+
if (range != null && !range.contains(0)) {
|
|
1824
|
+
// Choose the closest index to 0 if 0 is not available
|
|
1825
|
+
zeroIdx = Math.abs(range.getLower()) < Math.abs(range.getUpper())
|
|
1826
|
+
? range.getLower()
|
|
1827
|
+
: range.getUpper();
|
|
1828
|
+
}
|
|
1829
|
+
camera.getCameraControl().setExposureCompensationIndex(zeroIdx);
|
|
1830
|
+
} catch (Exception e) {
|
|
1831
|
+
Log.w(TAG, "setFocus: Failed to reset exposure compensation to 0", e);
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1810
1834
|
int viewWidth = previewView.getWidth();
|
|
1811
1835
|
int viewHeight = previewView.getHeight();
|
|
1812
1836
|
|
|
@@ -1878,6 +1902,108 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
|
|
|
1878
1902
|
}
|
|
1879
1903
|
}
|
|
1880
1904
|
|
|
1905
|
+
// ===================== Exposure APIs =====================
|
|
1906
|
+
public java.util.List<String> getExposureModes() {
|
|
1907
|
+
return Arrays.asList("LOCK", "CONTINUOUS");
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
public String getExposureMode() {
|
|
1911
|
+
return currentExposureMode;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
@OptIn(markerClass = ExperimentalCamera2Interop.class)
|
|
1915
|
+
public void setExposureMode(String mode) throws Exception {
|
|
1916
|
+
if (camera == null) {
|
|
1917
|
+
throw new Exception("Camera not initialized");
|
|
1918
|
+
}
|
|
1919
|
+
if (mode == null) {
|
|
1920
|
+
throw new Exception("mode is required");
|
|
1921
|
+
}
|
|
1922
|
+
String normalized = mode.toUpperCase(Locale.US);
|
|
1923
|
+
|
|
1924
|
+
try {
|
|
1925
|
+
Camera2CameraControl c2 = Camera2CameraControl.from(
|
|
1926
|
+
camera.getCameraControl()
|
|
1927
|
+
);
|
|
1928
|
+
switch (normalized) {
|
|
1929
|
+
case "LOCK": {
|
|
1930
|
+
CaptureRequestOptions opts = new CaptureRequestOptions.Builder()
|
|
1931
|
+
.setCaptureRequestOption(CaptureRequest.CONTROL_AE_LOCK, true)
|
|
1932
|
+
.setCaptureRequestOption(
|
|
1933
|
+
CaptureRequest.CONTROL_AE_MODE,
|
|
1934
|
+
CaptureRequest.CONTROL_AE_MODE_ON
|
|
1935
|
+
)
|
|
1936
|
+
.build();
|
|
1937
|
+
mainExecutor.execute(() -> c2.setCaptureRequestOptions(opts));
|
|
1938
|
+
currentExposureMode = "LOCK";
|
|
1939
|
+
break;
|
|
1940
|
+
}
|
|
1941
|
+
case "CONTINUOUS": {
|
|
1942
|
+
CaptureRequestOptions opts = new CaptureRequestOptions.Builder()
|
|
1943
|
+
.setCaptureRequestOption(CaptureRequest.CONTROL_AE_LOCK, false)
|
|
1944
|
+
.setCaptureRequestOption(
|
|
1945
|
+
CaptureRequest.CONTROL_AE_MODE,
|
|
1946
|
+
CaptureRequest.CONTROL_AE_MODE_ON
|
|
1947
|
+
)
|
|
1948
|
+
.build();
|
|
1949
|
+
mainExecutor.execute(() -> c2.setCaptureRequestOptions(opts));
|
|
1950
|
+
currentExposureMode = "CONTINUOUS";
|
|
1951
|
+
break;
|
|
1952
|
+
}
|
|
1953
|
+
default:
|
|
1954
|
+
throw new Exception("Unsupported exposure mode: " + mode);
|
|
1955
|
+
}
|
|
1956
|
+
} catch (Exception e) {
|
|
1957
|
+
throw e;
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
public float[] getExposureCompensationRange() throws Exception {
|
|
1962
|
+
if (camera == null) {
|
|
1963
|
+
throw new Exception("Camera not initialized");
|
|
1964
|
+
}
|
|
1965
|
+
ExposureState state = camera.getCameraInfo().getExposureState();
|
|
1966
|
+
Range<Integer> idxRange = state.getExposureCompensationRange();
|
|
1967
|
+
Rational step = state.getExposureCompensationStep();
|
|
1968
|
+
float evStep = step != null
|
|
1969
|
+
? (float) step.getNumerator() / (float) step.getDenominator()
|
|
1970
|
+
: 1.0f;
|
|
1971
|
+
float min = idxRange.getLower() * evStep;
|
|
1972
|
+
float max = idxRange.getUpper() * evStep;
|
|
1973
|
+
return new float[] { min, max, evStep };
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
public float getExposureCompensation() throws Exception {
|
|
1977
|
+
if (camera == null) {
|
|
1978
|
+
throw new Exception("Camera not initialized");
|
|
1979
|
+
}
|
|
1980
|
+
ExposureState state = camera.getCameraInfo().getExposureState();
|
|
1981
|
+
int idx = state.getExposureCompensationIndex();
|
|
1982
|
+
Rational step = state.getExposureCompensationStep();
|
|
1983
|
+
float evStep = step != null
|
|
1984
|
+
? (float) step.getNumerator() / (float) step.getDenominator()
|
|
1985
|
+
: 1.0f;
|
|
1986
|
+
return idx * evStep;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
public void setExposureCompensation(float ev) throws Exception {
|
|
1990
|
+
if (camera == null) {
|
|
1991
|
+
throw new Exception("Camera not initialized");
|
|
1992
|
+
}
|
|
1993
|
+
ExposureState state = camera.getCameraInfo().getExposureState();
|
|
1994
|
+
Range<Integer> idxRange = state.getExposureCompensationRange();
|
|
1995
|
+
Rational step = state.getExposureCompensationStep();
|
|
1996
|
+
float evStep = step != null
|
|
1997
|
+
? (float) step.getNumerator() / (float) step.getDenominator()
|
|
1998
|
+
: 1.0f;
|
|
1999
|
+
if (evStep <= 0f) evStep = 1.0f;
|
|
2000
|
+
int idx = Math.round(ev / evStep);
|
|
2001
|
+
// clamp
|
|
2002
|
+
if (idx < idxRange.getLower()) idx = idxRange.getLower();
|
|
2003
|
+
if (idx > idxRange.getUpper()) idx = idxRange.getUpper();
|
|
2004
|
+
camera.getCameraControl().setExposureCompensationIndex(idx);
|
|
2005
|
+
}
|
|
2006
|
+
|
|
1881
2007
|
private void showFocusIndicator(float x, float y) {
|
|
1882
2008
|
if (disableFocusIndicator || sessionConfig.getDisableFocusIndicator()) {
|
|
1883
2009
|
return;
|
package/dist/docs.json
CHANGED
|
@@ -882,6 +882,114 @@
|
|
|
882
882
|
"DeviceOrientation"
|
|
883
883
|
],
|
|
884
884
|
"slug": "getorientation"
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
"name": "getExposureModes",
|
|
888
|
+
"signature": "() => Promise<{ modes: ExposureMode[]; }>",
|
|
889
|
+
"parameters": [],
|
|
890
|
+
"returns": "Promise<{ modes: ExposureMode[]; }>",
|
|
891
|
+
"tags": [
|
|
892
|
+
{
|
|
893
|
+
"name": "platform",
|
|
894
|
+
"text": "android, ios"
|
|
895
|
+
}
|
|
896
|
+
],
|
|
897
|
+
"docs": "Returns the exposure modes supported by the active camera.\nModes can include: 'locked', 'auto', 'continuous', 'custom'.",
|
|
898
|
+
"complexTypes": [
|
|
899
|
+
"ExposureMode"
|
|
900
|
+
],
|
|
901
|
+
"slug": "getexposuremodes"
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
"name": "getExposureMode",
|
|
905
|
+
"signature": "() => Promise<{ mode: ExposureMode; }>",
|
|
906
|
+
"parameters": [],
|
|
907
|
+
"returns": "Promise<{ mode: ExposureMode; }>",
|
|
908
|
+
"tags": [
|
|
909
|
+
{
|
|
910
|
+
"name": "platform",
|
|
911
|
+
"text": "android, ios"
|
|
912
|
+
}
|
|
913
|
+
],
|
|
914
|
+
"docs": "Returns the current exposure mode.",
|
|
915
|
+
"complexTypes": [
|
|
916
|
+
"ExposureMode"
|
|
917
|
+
],
|
|
918
|
+
"slug": "getexposuremode"
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
"name": "setExposureMode",
|
|
922
|
+
"signature": "(options: { mode: ExposureMode; }) => Promise<void>",
|
|
923
|
+
"parameters": [
|
|
924
|
+
{
|
|
925
|
+
"name": "options",
|
|
926
|
+
"docs": "",
|
|
927
|
+
"type": "{ mode: ExposureMode; }"
|
|
928
|
+
}
|
|
929
|
+
],
|
|
930
|
+
"returns": "Promise<void>",
|
|
931
|
+
"tags": [
|
|
932
|
+
{
|
|
933
|
+
"name": "platform",
|
|
934
|
+
"text": "android, ios"
|
|
935
|
+
}
|
|
936
|
+
],
|
|
937
|
+
"docs": "Sets the exposure mode.",
|
|
938
|
+
"complexTypes": [
|
|
939
|
+
"ExposureMode"
|
|
940
|
+
],
|
|
941
|
+
"slug": "setexposuremode"
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
"name": "getExposureCompensationRange",
|
|
945
|
+
"signature": "() => Promise<{ min: number; max: number; step: number; }>",
|
|
946
|
+
"parameters": [],
|
|
947
|
+
"returns": "Promise<{ min: number; max: number; step: number; }>",
|
|
948
|
+
"tags": [
|
|
949
|
+
{
|
|
950
|
+
"name": "platform",
|
|
951
|
+
"text": "ios"
|
|
952
|
+
}
|
|
953
|
+
],
|
|
954
|
+
"docs": "Returns the exposure compensation (EV bias) supported range.",
|
|
955
|
+
"complexTypes": [],
|
|
956
|
+
"slug": "getexposurecompensationrange"
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
"name": "getExposureCompensation",
|
|
960
|
+
"signature": "() => Promise<{ value: number; }>",
|
|
961
|
+
"parameters": [],
|
|
962
|
+
"returns": "Promise<{ value: number; }>",
|
|
963
|
+
"tags": [
|
|
964
|
+
{
|
|
965
|
+
"name": "platform",
|
|
966
|
+
"text": "ios"
|
|
967
|
+
}
|
|
968
|
+
],
|
|
969
|
+
"docs": "Returns the current exposure compensation (EV bias).",
|
|
970
|
+
"complexTypes": [],
|
|
971
|
+
"slug": "getexposurecompensation"
|
|
972
|
+
},
|
|
973
|
+
{
|
|
974
|
+
"name": "setExposureCompensation",
|
|
975
|
+
"signature": "(options: { value: number; }) => Promise<void>",
|
|
976
|
+
"parameters": [
|
|
977
|
+
{
|
|
978
|
+
"name": "options",
|
|
979
|
+
"docs": "",
|
|
980
|
+
"type": "{ value: number; }"
|
|
981
|
+
}
|
|
982
|
+
],
|
|
983
|
+
"returns": "Promise<void>",
|
|
984
|
+
"tags": [
|
|
985
|
+
{
|
|
986
|
+
"name": "platform",
|
|
987
|
+
"text": "ios"
|
|
988
|
+
}
|
|
989
|
+
],
|
|
990
|
+
"docs": "Sets the exposure compensation (EV bias). Value will be clamped to range.",
|
|
991
|
+
"complexTypes": [],
|
|
992
|
+
"slug": "setexposurecompensation"
|
|
885
993
|
}
|
|
886
994
|
],
|
|
887
995
|
"properties": []
|
|
@@ -1804,6 +1912,29 @@
|
|
|
1804
1912
|
"complexTypes": []
|
|
1805
1913
|
}
|
|
1806
1914
|
]
|
|
1915
|
+
},
|
|
1916
|
+
{
|
|
1917
|
+
"name": "ExposureMode",
|
|
1918
|
+
"slug": "exposuremode",
|
|
1919
|
+
"docs": "Reusable exposure mode type for cross-platform support.",
|
|
1920
|
+
"types": [
|
|
1921
|
+
{
|
|
1922
|
+
"text": "\"AUTO\"",
|
|
1923
|
+
"complexTypes": []
|
|
1924
|
+
},
|
|
1925
|
+
{
|
|
1926
|
+
"text": "\"LOCK\"",
|
|
1927
|
+
"complexTypes": []
|
|
1928
|
+
},
|
|
1929
|
+
{
|
|
1930
|
+
"text": "\"CONTINUOUS\"",
|
|
1931
|
+
"complexTypes": []
|
|
1932
|
+
},
|
|
1933
|
+
{
|
|
1934
|
+
"text": "\"CUSTOM\"",
|
|
1935
|
+
"complexTypes": []
|
|
1936
|
+
}
|
|
1937
|
+
]
|
|
1807
1938
|
}
|
|
1808
1939
|
],
|
|
1809
1940
|
"pluginConfigs": []
|
|
@@ -278,6 +278,8 @@ export interface CameraSampleOptions {
|
|
|
278
278
|
* 'torch' is a continuous light mode.
|
|
279
279
|
*/
|
|
280
280
|
export type CameraPreviewFlashMode = "off" | "on" | "auto" | "torch";
|
|
281
|
+
/** Reusable exposure mode type for cross-platform support. */
|
|
282
|
+
export type ExposureMode = "AUTO" | "LOCK" | "CONTINUOUS" | "CUSTOM";
|
|
281
283
|
/**
|
|
282
284
|
* Defines the options for setting the camera preview's opacity.
|
|
283
285
|
*/
|
|
@@ -678,4 +680,49 @@ export interface CameraPreviewPlugin {
|
|
|
678
680
|
getOrientation(): Promise<{
|
|
679
681
|
orientation: DeviceOrientation;
|
|
680
682
|
}>;
|
|
683
|
+
/**
|
|
684
|
+
* Returns the exposure modes supported by the active camera.
|
|
685
|
+
* Modes can include: 'locked', 'auto', 'continuous', 'custom'.
|
|
686
|
+
* @platform android, ios
|
|
687
|
+
*/
|
|
688
|
+
getExposureModes(): Promise<{
|
|
689
|
+
modes: ExposureMode[];
|
|
690
|
+
}>;
|
|
691
|
+
/**
|
|
692
|
+
* Returns the current exposure mode.
|
|
693
|
+
* @platform android, ios
|
|
694
|
+
*/
|
|
695
|
+
getExposureMode(): Promise<{
|
|
696
|
+
mode: ExposureMode;
|
|
697
|
+
}>;
|
|
698
|
+
/**
|
|
699
|
+
* Sets the exposure mode.
|
|
700
|
+
* @platform android, ios
|
|
701
|
+
*/
|
|
702
|
+
setExposureMode(options: {
|
|
703
|
+
mode: ExposureMode;
|
|
704
|
+
}): Promise<void>;
|
|
705
|
+
/**
|
|
706
|
+
* Returns the exposure compensation (EV bias) supported range.
|
|
707
|
+
* @platform ios
|
|
708
|
+
*/
|
|
709
|
+
getExposureCompensationRange(): Promise<{
|
|
710
|
+
min: number;
|
|
711
|
+
max: number;
|
|
712
|
+
step: number;
|
|
713
|
+
}>;
|
|
714
|
+
/**
|
|
715
|
+
* Returns the current exposure compensation (EV bias).
|
|
716
|
+
* @platform ios
|
|
717
|
+
*/
|
|
718
|
+
getExposureCompensation(): Promise<{
|
|
719
|
+
value: number;
|
|
720
|
+
}>;
|
|
721
|
+
/**
|
|
722
|
+
* Sets the exposure compensation (EV bias). Value will be clamped to range.
|
|
723
|
+
* @platform ios
|
|
724
|
+
*/
|
|
725
|
+
setExposureCompensation(options: {
|
|
726
|
+
value: number;
|
|
727
|
+
}): Promise<void>;
|
|
681
728
|
}
|