expo-camera 12.0.2 → 12.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +23 -2
  2. package/README.md +1 -1
  3. package/android/build.gradle +22 -19
  4. package/android/src/main/java/expo/modules/camera/CameraModule.kt +217 -0
  5. package/android/src/main/java/expo/modules/camera/CameraPackage.kt +10 -0
  6. package/android/src/main/java/expo/modules/camera/CameraViewHelper.kt +139 -0
  7. package/android/src/main/java/expo/modules/camera/CameraViewManager.kt +116 -0
  8. package/android/src/main/java/expo/modules/camera/Constants.kt +184 -0
  9. package/android/src/main/java/expo/modules/camera/ExpoCameraView.kt +329 -0
  10. package/android/src/main/java/expo/modules/camera/events/BarCodeScannedEvent.kt +50 -0
  11. package/android/src/main/java/expo/modules/camera/events/CameraMountErrorEvent.kt +33 -0
  12. package/android/src/main/java/expo/modules/camera/events/CameraReadyEvent.kt +23 -0
  13. package/android/src/main/java/expo/modules/camera/events/FaceDetectionErrorEvent.kt +39 -0
  14. package/android/src/main/java/expo/modules/camera/events/FacesDetectedEvent.kt +46 -0
  15. package/android/src/main/java/expo/modules/camera/events/PictureSavedEvent.kt +41 -0
  16. package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTask.kt +26 -0
  17. package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTaskDelegate.kt +8 -0
  18. package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorAsyncTaskDelegate.kt +10 -0
  19. package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorTask.kt +34 -0
  20. package/android/src/main/java/expo/modules/camera/tasks/PictureSavedDelegate.kt +7 -0
  21. package/android/src/main/java/expo/modules/camera/tasks/ResolveTakenPictureAsyncTask.kt +231 -0
  22. package/android/src/main/java/expo/modules/camera/utils/FileSystemUtils.kt +23 -0
  23. package/android/src/main/java/expo/modules/camera/utils/ImageDimensions.kt +14 -0
  24. package/build/ExponentCameraManager.web.js +3 -1
  25. package/build/ExponentCameraManager.web.js.map +1 -1
  26. package/ios/EXCamera.xcframework/ios-arm64/EXCamera.framework/EXCamera +0 -0
  27. package/ios/EXCamera.xcframework/ios-arm64/EXCamera.framework/Info.plist +0 -0
  28. package/ios/EXCamera.xcframework/ios-arm64_x86_64-simulator/EXCamera.framework/EXCamera +0 -0
  29. package/ios/EXCamera.xcframework/ios-arm64_x86_64-simulator/EXCamera.framework/Info.plist +0 -0
  30. package/package.json +7 -5
  31. package/plugin/build/withCamera.d.ts +2 -1
  32. package/plugin/build/withCamera.js +50 -30
  33. package/plugin/src/withCamera.ts +66 -27
  34. package/src/ExponentCameraManager.web.ts +3 -2
  35. package/src/{types → ts-declarations}/image-capture.d.ts +0 -0
  36. package/src/ts-declarations/lib.dom.d.ts +34 -0
  37. package/android/src/main/java/expo/modules/camera/CameraModule.java +0 -359
  38. package/android/src/main/java/expo/modules/camera/CameraPackage.java +0 -23
  39. package/android/src/main/java/expo/modules/camera/CameraViewHelper.java +0 -294
  40. package/android/src/main/java/expo/modules/camera/CameraViewManager.java +0 -142
  41. package/android/src/main/java/expo/modules/camera/ExpoCameraView.java +0 -376
  42. package/android/src/main/java/expo/modules/camera/events/BarCodeScannedEvent.java +0 -59
  43. package/android/src/main/java/expo/modules/camera/events/CameraMountErrorEvent.java +0 -38
  44. package/android/src/main/java/expo/modules/camera/events/CameraReadyEvent.java +0 -30
  45. package/android/src/main/java/expo/modules/camera/events/FaceDetectionErrorEvent.java +0 -50
  46. package/android/src/main/java/expo/modules/camera/events/FacesDetectedEvent.java +0 -63
  47. package/android/src/main/java/expo/modules/camera/events/PictureSavedEvent.java +0 -53
  48. package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTask.java +0 -47
  49. package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTaskDelegate.java +0 -8
  50. package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorAsyncTaskDelegate.java +0 -13
  51. package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorTask.java +0 -53
  52. package/android/src/main/java/expo/modules/camera/tasks/PictureSavedDelegate.java +0 -7
  53. package/android/src/main/java/expo/modules/camera/tasks/ResolveTakenPictureAsyncTask.java +0 -288
  54. package/android/src/main/java/expo/modules/camera/utils/FileSystemUtils.java +0 -21
  55. package/android/src/main/java/expo/modules/camera/utils/ImageDimensions.java +0 -64
@@ -1,47 +0,0 @@
1
- package expo.modules.camera.tasks;
2
-
3
- import expo.modules.interfaces.barcodescanner.BarCodeScannerInterface;
4
- import expo.modules.interfaces.barcodescanner.BarCodeScannerResult;
5
-
6
- public class BarCodeScannerAsyncTask extends android.os.AsyncTask<Void, Void, BarCodeScannerResult> {
7
- private final BarCodeScannerInterface mBarCodeScanner;
8
- private byte[] mImageData;
9
- private int mWidth;
10
- private int mHeight;
11
- private int mRotation;
12
- private BarCodeScannerAsyncTaskDelegate mDelegate;
13
-
14
- public BarCodeScannerAsyncTask(
15
- BarCodeScannerAsyncTaskDelegate delegate,
16
- BarCodeScannerInterface barCodeScanner,
17
- byte[] imageData,
18
- int width,
19
- int height,
20
- int rotation
21
- ) {
22
- mImageData = imageData;
23
- mWidth = width;
24
- mHeight = height;
25
- mDelegate = delegate;
26
- mBarCodeScanner = barCodeScanner;
27
- mRotation = rotation;
28
- }
29
-
30
- @Override
31
- protected BarCodeScannerResult doInBackground(Void... ignored) {
32
- if (isCancelled() || mDelegate == null) {
33
- return null;
34
- }
35
-
36
- return mBarCodeScanner.scan(mImageData, mWidth, mHeight, mRotation);
37
- }
38
-
39
- @Override
40
- protected void onPostExecute(BarCodeScannerResult result) {
41
- super.onPostExecute(result);
42
- if (result != null) {
43
- mDelegate.onBarCodeScanned(result);
44
- }
45
- mDelegate.onBarCodeScanningTaskCompleted();
46
- }
47
- }
@@ -1,8 +0,0 @@
1
- package expo.modules.camera.tasks;
2
-
3
- import expo.modules.interfaces.barcodescanner.BarCodeScannerResult;
4
-
5
- public interface BarCodeScannerAsyncTaskDelegate {
6
- void onBarCodeScanned(BarCodeScannerResult barCode);
7
- void onBarCodeScanningTaskCompleted();
8
- }
@@ -1,13 +0,0 @@
1
- package expo.modules.camera.tasks;
2
-
3
- import android.os.Bundle;
4
-
5
- import java.util.List;
6
-
7
- import expo.modules.interfaces.facedetector.FaceDetectorInterface;
8
-
9
- public interface FaceDetectorAsyncTaskDelegate {
10
- void onFacesDetected(List<Bundle> faces);
11
- void onFaceDetectionError(FaceDetectorInterface faceDetector);
12
- void onFaceDetectingTaskCompleted();
13
- }
@@ -1,53 +0,0 @@
1
- package expo.modules.camera.tasks;
2
-
3
- import expo.modules.interfaces.facedetector.FaceDetectorInterface;
4
-
5
- public class FaceDetectorTask {
6
-
7
- private byte[] mImageData;
8
- private int mWidth;
9
- private int mHeight;
10
- private int mRotation;
11
- private boolean mMirrored;
12
- private double mScaleX;
13
- private double mScaleY;
14
- private FaceDetectorInterface mFaceDetector;
15
- private FaceDetectorAsyncTaskDelegate mDelegate;
16
-
17
- public FaceDetectorTask(
18
- FaceDetectorAsyncTaskDelegate delegate,
19
- FaceDetectorInterface faceDetector,
20
- byte[] imageData,
21
- int width,
22
- int height,
23
- int rotation,
24
- boolean mirrored,
25
- double scaleX,
26
- double scaleY
27
- ) {
28
- mImageData = imageData;
29
- mWidth = width;
30
- mHeight = height;
31
- mMirrored = mirrored;
32
- mScaleX = scaleX;
33
- mScaleY = scaleY;
34
- mRotation = rotation;
35
- mDelegate = delegate;
36
- mFaceDetector = faceDetector;
37
- }
38
-
39
- public void execute() {
40
- mFaceDetector.detectFaces(mImageData, mWidth, mHeight, mRotation, mMirrored, mScaleX, mScaleY, result -> {
41
- if (result != null) {
42
- mDelegate.onFacesDetected(result);
43
- } else {
44
- mDelegate.onFaceDetectionError(mFaceDetector);
45
- }
46
- mDelegate.onFaceDetectingTaskCompleted();
47
- }, error -> {
48
- mDelegate.onFaceDetectionError(mFaceDetector);
49
- mDelegate.onFaceDetectingTaskCompleted();
50
- }, skippedReason -> mDelegate.onFaceDetectingTaskCompleted());
51
- }
52
-
53
- }
@@ -1,7 +0,0 @@
1
- package expo.modules.camera.tasks;
2
-
3
- import android.os.Bundle;
4
-
5
- public interface PictureSavedDelegate {
6
- void onPictureSaved(Bundle response);
7
- }
@@ -1,288 +0,0 @@
1
- package expo.modules.camera.tasks;
2
-
3
- import android.content.res.Resources;
4
- import android.graphics.Bitmap;
5
- import android.graphics.BitmapFactory;
6
- import android.graphics.Matrix;
7
- import android.os.Bundle;
8
-
9
- import androidx.exifinterface.media.ExifInterface;
10
-
11
- import android.net.Uri;
12
- import android.os.AsyncTask;
13
- import android.util.Base64;
14
-
15
- import java.io.ByteArrayInputStream;
16
- import java.io.ByteArrayOutputStream;
17
- import java.io.File;
18
- import java.io.FileOutputStream;
19
- import java.io.IOException;
20
- import java.util.Map;
21
-
22
- import expo.modules.core.Promise;
23
-
24
- import expo.modules.camera.CameraViewHelper;
25
- import expo.modules.camera.utils.FileSystemUtils;
26
-
27
- public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, Bundle> {
28
- private static final String DIRECTORY_NOT_FOUND_MSG = "Documents directory of the app could not be found.";
29
- private static final String UNKNOWN_IO_EXCEPTION_MSG = "An unknown I/O exception has occurred.";
30
- private static final String UNKNOWN_EXCEPTION_MSG = "An unknown exception has occurred.";
31
-
32
- private static final String ERROR_TAG = "E_TAKING_PICTURE_FAILED";
33
-
34
- private static final String DIRECTORY_NAME = "Camera";
35
- private static final String EXTENSION = ".jpg";
36
-
37
- private static final String SKIP_PROCESSING_KEY = "skipProcessing";
38
- private static final String FAST_MODE_KEY = "fastMode";
39
- private static final String QUALITY_KEY = "quality";
40
- private static final String BASE64_KEY = "base64";
41
- private static final String HEIGHT_KEY = "height";
42
- private static final String WIDTH_KEY = "width";
43
- private static final String EXIF_KEY = "exif";
44
- private static final String DATA_KEY = "data";
45
- private static final String URI_KEY = "uri";
46
- private static final String ID_KEY = "id";
47
-
48
- private static final int DEFAULT_QUALITY = 1;
49
-
50
- private Promise mPromise;
51
- private byte[] mImageData;
52
- private Bitmap mBitmap;
53
- private Map<String, Object> mOptions;
54
- private File mDirectory;
55
- private PictureSavedDelegate mPictureSavedDelegate;
56
-
57
- public ResolveTakenPictureAsyncTask(byte[] imageData, Promise promise, Map<String, Object> options, File directory, PictureSavedDelegate delegate) {
58
- mPromise = promise;
59
- mOptions = options;
60
- mImageData = imageData;
61
- mDirectory = directory;
62
- mPictureSavedDelegate = delegate;
63
- }
64
-
65
- public ResolveTakenPictureAsyncTask(Bitmap bitmap, Promise promise, Map<String, Object> options, File directory, PictureSavedDelegate delegate) {
66
- mPromise = promise;
67
- mBitmap = bitmap;
68
- mOptions = options;
69
- mDirectory = directory;
70
- mPictureSavedDelegate = delegate;
71
- }
72
-
73
- private int getQuality() {
74
- if (mOptions.get(QUALITY_KEY) instanceof Number) {
75
- double requestedQuality = ((Number) mOptions.get(QUALITY_KEY)).doubleValue();
76
- return (int) (requestedQuality * 100);
77
- }
78
-
79
- return DEFAULT_QUALITY * 100;
80
- }
81
-
82
- @Override
83
- protected Bundle doInBackground(Void... voids) {
84
- // handle SkipProcessing
85
- if (mImageData != null && isOptionEnabled(SKIP_PROCESSING_KEY)) {
86
- return handleSkipProcessing();
87
- }
88
-
89
- Bundle response = new Bundle();
90
-
91
- if (mBitmap == null) {
92
- mBitmap = BitmapFactory.decodeByteArray(mImageData, 0, mImageData.length);
93
- }
94
-
95
- ByteArrayInputStream inputStream = new ByteArrayInputStream(mImageData);
96
-
97
- try {
98
- ExifInterface exifInterface = new ExifInterface(inputStream);
99
- // Get orientation of the image from mImageData via inputStream
100
- int orientation = exifInterface.getAttributeInt(
101
- ExifInterface.TAG_ORIENTATION,
102
- ExifInterface.ORIENTATION_UNDEFINED
103
- );
104
-
105
- // Rotate the bitmap to the proper orientation if needed
106
- if (orientation != ExifInterface.ORIENTATION_UNDEFINED) {
107
- mBitmap = rotateBitmap(mBitmap, getImageRotation(orientation));
108
- }
109
-
110
- // Write Exif data to the response if requested
111
- if (isOptionEnabled(EXIF_KEY)) {
112
- Bundle exifData = CameraViewHelper.getExifData(exifInterface);
113
- response.putBundle(EXIF_KEY, exifData);
114
- }
115
-
116
- // Upon rotating, write the image's dimensions to the response
117
- response.putInt(WIDTH_KEY, mBitmap.getWidth());
118
- response.putInt(HEIGHT_KEY, mBitmap.getHeight());
119
-
120
- // Cache compressed image in imageStream
121
- ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
122
- mBitmap.compress(Bitmap.CompressFormat.JPEG, getQuality(), imageStream);
123
- // Write compressed image to file in cache directory
124
- String filePath = writeStreamToFile(imageStream);
125
-
126
- // Save Exif data to the image if requested
127
- if (isOptionEnabled(EXIF_KEY)) {
128
- ExifInterface exifFromFile = new ExifInterface(filePath);
129
- CameraViewHelper.addExifData(exifFromFile, exifInterface);
130
- }
131
-
132
- File imageFile = new File(filePath);
133
- String fileUri = Uri.fromFile(imageFile).toString();
134
- response.putString(URI_KEY, fileUri);
135
-
136
- // Write base64-encoded image to the response if requested
137
- if (isOptionEnabled(BASE64_KEY)) {
138
- response.putString(BASE64_KEY, Base64.encodeToString(imageStream.toByteArray(), Base64.NO_WRAP));
139
- }
140
-
141
- // Cleanup
142
- imageStream.close();
143
- inputStream.close();
144
- inputStream = null;
145
-
146
- return response;
147
- } catch (Resources.NotFoundException e) {
148
- mPromise.reject(ERROR_TAG, DIRECTORY_NOT_FOUND_MSG, e);
149
- e.printStackTrace();
150
- } catch (IOException e) {
151
- mPromise.reject(ERROR_TAG, UNKNOWN_IO_EXCEPTION_MSG, e);
152
- e.printStackTrace();
153
- } catch (Exception e) {
154
- mPromise.reject(ERROR_TAG, UNKNOWN_EXCEPTION_MSG, e);
155
- e.printStackTrace();
156
- } finally {
157
- try {
158
- if (inputStream != null) {
159
- inputStream.close();
160
- }
161
- } catch (IOException e) {
162
- e.printStackTrace();
163
- }
164
- }
165
-
166
- // An exception had to occur, promise has already been rejected. Do not try to resolve it again.
167
- return null;
168
- }
169
-
170
- private Bundle handleSkipProcessing() {
171
- Bundle response = new Bundle();
172
- try {
173
- // save byte array (it's already a JPEG)
174
- ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
175
- imageStream.write(mImageData);
176
-
177
- // write compressed image to file in cache directory
178
- String filePath = writeStreamToFile(imageStream);
179
- File imageFile = new File(filePath);
180
-
181
- // handle image uri
182
- String fileUri = Uri.fromFile(imageFile).toString();
183
- response.putString(URI_KEY, fileUri);
184
-
185
- // read exif information
186
- ExifInterface exifInterface = new ExifInterface(filePath);
187
-
188
- // handle image dimensions
189
- response.putInt(WIDTH_KEY, exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, -1));
190
- response.putInt(HEIGHT_KEY, exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, -1));
191
-
192
- // handle exif request
193
- if (isOptionEnabled(EXIF_KEY)) {
194
- Bundle exifData = CameraViewHelper.getExifData(exifInterface);
195
- response.putBundle(EXIF_KEY, exifData);
196
- }
197
-
198
- // handle base64
199
- if (isOptionEnabled(BASE64_KEY)) {
200
- response.putString(BASE64_KEY, Base64.encodeToString(mImageData, Base64.NO_WRAP));
201
- }
202
-
203
- return response;
204
- } catch (IOException e) {
205
- mPromise.reject(ERROR_TAG, UNKNOWN_IO_EXCEPTION_MSG, e);
206
- e.printStackTrace();
207
- } catch (Exception e) {
208
- mPromise.reject(ERROR_TAG, UNKNOWN_EXCEPTION_MSG, e);
209
- e.printStackTrace();
210
- }
211
- // error occurred
212
- return null;
213
- }
214
-
215
- @Override
216
- protected void onPostExecute(Bundle response) {
217
- super.onPostExecute(response);
218
-
219
- // If the response is not null everything went well and we can resolve the promise.
220
- if (response != null) {
221
- if (isOptionEnabled(FAST_MODE_KEY)) {
222
- Bundle wrapper = new Bundle();
223
- wrapper.putInt(ID_KEY, ((Double) mOptions.get(ID_KEY)).intValue());
224
- wrapper.putBundle(DATA_KEY, response);
225
- mPictureSavedDelegate.onPictureSaved(wrapper);
226
- } else {
227
- mPromise.resolve(response);
228
- }
229
- }
230
- }
231
-
232
- // Write stream to file in cache directory
233
- private String writeStreamToFile(ByteArrayOutputStream inputStream) throws Exception {
234
- String outputPath = null;
235
- Exception exception = null;
236
- FileOutputStream outputStream = null;
237
-
238
- try {
239
- outputPath = FileSystemUtils.generateOutputPath(mDirectory, DIRECTORY_NAME, EXTENSION);
240
- outputStream = new FileOutputStream(outputPath);
241
- inputStream.writeTo(outputStream);
242
- } catch (IOException e) {
243
- e.printStackTrace();
244
- exception = e;
245
- } finally {
246
- try {
247
- if (outputStream != null) {
248
- outputStream.close();
249
- }
250
- } catch (IOException e) {
251
- e.printStackTrace();
252
- }
253
- }
254
-
255
- if (exception != null) {
256
- throw exception;
257
- }
258
-
259
- return outputPath;
260
- }
261
-
262
- private Bitmap rotateBitmap(Bitmap source, int angle) {
263
- Matrix matrix = new Matrix();
264
- matrix.postRotate(angle);
265
- return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
266
- }
267
-
268
- // Get rotation degrees from Exif orientation enum
269
- private int getImageRotation(int orientation) {
270
- int rotationDegrees = 0;
271
- switch (orientation) {
272
- case ExifInterface.ORIENTATION_ROTATE_90:
273
- rotationDegrees = 90;
274
- break;
275
- case ExifInterface.ORIENTATION_ROTATE_180:
276
- rotationDegrees = 180;
277
- break;
278
- case ExifInterface.ORIENTATION_ROTATE_270:
279
- rotationDegrees = 270;
280
- break;
281
- }
282
- return rotationDegrees;
283
- }
284
-
285
- private boolean isOptionEnabled(String key) {
286
- return mOptions.get(key) != null && (Boolean) mOptions.get(key);
287
- }
288
- }
@@ -1,21 +0,0 @@
1
- package expo.modules.camera.utils;
2
-
3
- import java.io.File;
4
- import java.io.IOException;
5
- import java.util.UUID;
6
-
7
- public class FileSystemUtils {
8
- public static File ensureDirExists(File dir) throws IOException {
9
- if (!(dir.isDirectory() || dir.mkdirs())) {
10
- throw new IOException("Couldn't create directory '" + dir + "'");
11
- }
12
- return dir;
13
- }
14
-
15
- public static String generateOutputPath(File internalDirectory, String dirName, String extension) throws IOException {
16
- File directory = new File(internalDirectory + File.separator + dirName);
17
- FileSystemUtils.ensureDirExists(directory);
18
- String filename = UUID.randomUUID().toString();
19
- return directory + File.separator + filename + extension;
20
- }
21
- }
@@ -1,64 +0,0 @@
1
- package expo.modules.camera.utils;
2
-
3
- public class ImageDimensions {
4
- private int mWidth;
5
- private int mHeight;
6
- private int mFacing;
7
- private int mRotation;
8
-
9
- public ImageDimensions(int width, int height) {
10
- this(width, height, 0);
11
- }
12
-
13
- public ImageDimensions(int width, int height, int rotation) {
14
- this(width, height, rotation, -1);
15
- }
16
-
17
- public ImageDimensions(int width, int height, int rotation, int facing) {
18
- mWidth = width;
19
- mHeight = height;
20
- mFacing = facing;
21
- mRotation = rotation;
22
- }
23
-
24
- public boolean isLandscape() {
25
- return mRotation % 180 == 90;
26
- }
27
-
28
- public int getWidth() {
29
- if (isLandscape()) {
30
- return mHeight;
31
- }
32
-
33
- return mWidth;
34
- }
35
-
36
- public int getHeight() {
37
- if (isLandscape()) {
38
- return mWidth;
39
- }
40
-
41
- return mHeight;
42
- }
43
-
44
- public int getRotation() {
45
- return mRotation;
46
- }
47
-
48
- public int getFacing() {
49
- return mFacing;
50
- }
51
-
52
- @Override
53
- public boolean equals(Object obj) {
54
- if (obj instanceof ImageDimensions) {
55
- ImageDimensions otherDimensions = (ImageDimensions) obj;
56
- return (otherDimensions.getWidth() == getWidth() &&
57
- otherDimensions.getHeight() == getHeight() &&
58
- otherDimensions.getFacing() == getFacing() &&
59
- otherDimensions.getRotation() == getRotation());
60
- } else {
61
- return super.equals(obj);
62
- }
63
- }
64
- }