@capgo/camera-preview 4.0.0 → 5.0.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.
Files changed (133) hide show
  1. package/README.md +22 -30
  2. package/android/.gradle/8.0.2/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.0.2/dependencies-accessors/dependencies-accessors.lock +0 -0
  4. package/android/.gradle/8.0.2/dependencies-accessors/gc.properties +0 -0
  5. package/android/.gradle/8.0.2/executionHistory/executionHistory.bin +0 -0
  6. package/android/.gradle/8.0.2/executionHistory/executionHistory.lock +0 -0
  7. package/android/.gradle/8.0.2/fileChanges/last-build.bin +0 -0
  8. package/android/.gradle/8.0.2/fileHashes/fileHashes.bin +0 -0
  9. package/android/.gradle/8.0.2/fileHashes/fileHashes.lock +0 -0
  10. package/android/.gradle/8.0.2/fileHashes/resourceHashesCache.bin +0 -0
  11. package/android/.gradle/8.0.2/gc.properties +0 -0
  12. package/android/.gradle/8.2.1/checksums/checksums.lock +0 -0
  13. package/android/.gradle/8.2.1/dependencies-accessors/dependencies-accessors.lock +0 -0
  14. package/android/.gradle/8.2.1/dependencies-accessors/gc.properties +0 -0
  15. package/android/.gradle/8.2.1/executionHistory/executionHistory.bin +0 -0
  16. package/android/.gradle/8.2.1/executionHistory/executionHistory.lock +0 -0
  17. package/android/.gradle/8.2.1/fileChanges/last-build.bin +0 -0
  18. package/android/.gradle/8.2.1/fileHashes/fileHashes.bin +0 -0
  19. package/android/.gradle/8.2.1/fileHashes/fileHashes.lock +0 -0
  20. package/android/.gradle/8.2.1/gc.properties +0 -0
  21. package/android/.gradle/8.7/checksums/checksums.lock +0 -0
  22. package/android/.gradle/8.7/dependencies-accessors/gc.properties +0 -0
  23. package/android/.gradle/8.7/executionHistory/executionHistory.bin +0 -0
  24. package/android/.gradle/8.7/executionHistory/executionHistory.lock +0 -0
  25. package/android/.gradle/8.7/fileChanges/last-build.bin +0 -0
  26. package/android/.gradle/8.7/fileHashes/fileHashes.bin +0 -0
  27. package/android/.gradle/8.7/fileHashes/fileHashes.lock +0 -0
  28. package/android/.gradle/8.7/fileHashes/resourceHashesCache.bin +0 -0
  29. package/android/.gradle/8.7/gc.properties +0 -0
  30. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  31. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  32. package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
  33. package/android/.gradle/file-system.probe +0 -0
  34. package/android/.gradle/vcs-1/gc.properties +0 -0
  35. package/android/build.gradle +1 -1
  36. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  37. package/android/gradle/wrapper/gradle-wrapper.properties +1 -0
  38. package/android/gradlew +17 -12
  39. package/android/gradlew.bat +10 -10
  40. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraActivity.java +219 -219
  41. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +108 -85
  42. package/android/src/main/java/com/ahm/capacitor/camera/preview/CustomSurfaceView.java +4 -3
  43. package/android/src/main/java/com/ahm/capacitor/camera/preview/CustomTextureView.java +5 -5
  44. package/android/src/main/java/com/ahm/capacitor/camera/preview/Preview.java +44 -23
  45. package/dist/docs.json +29 -22
  46. package/dist/esm/definitions.d.ts +6 -2
  47. package/dist/esm/definitions.js.map +1 -1
  48. package/dist/esm/index.d.ts +2 -2
  49. package/dist/esm/index.js +4 -4
  50. package/dist/esm/index.js.map +1 -1
  51. package/dist/esm/web.d.ts +2 -2
  52. package/dist/esm/web.js +44 -45
  53. package/dist/esm/web.js.map +1 -1
  54. package/dist/plugin.cjs.js +45 -46
  55. package/dist/plugin.cjs.js.map +1 -1
  56. package/dist/plugin.js +45 -46
  57. package/dist/plugin.js.map +1 -1
  58. package/ios/Plugin/CameraController.swift +35 -14
  59. package/ios/Plugin/Plugin.swift +25 -26
  60. package/ios/Plugin.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  61. package/ios/Plugin.xcworkspace/xcuserdata/martindonadieu.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  62. package/ios/PluginTests/PluginTests.swift +61 -13
  63. package/ios/Podfile.lock +3 -3
  64. package/ios/Pods/CapacitorCordova/LICENSE +23 -0
  65. package/ios/Pods/CapacitorCordova/README.md +39 -0
  66. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/CapacitorCordova.h +21 -0
  67. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.h +8 -0
  68. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.m +5 -0
  69. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDV.h +28 -0
  70. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVAvailability.h +109 -0
  71. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegate.h +51 -0
  72. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.h +39 -0
  73. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.m +154 -0
  74. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.h +31 -0
  75. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.m +81 -0
  76. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.h +52 -0
  77. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.m +116 -0
  78. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.h +81 -0
  79. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.m +154 -0
  80. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.h +25 -0
  81. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.m +77 -0
  82. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.h +82 -0
  83. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.m +216 -0
  84. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVScreenOrientationDelegate.h +33 -0
  85. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVUIWebViewDelegate.h +41 -0
  86. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVUIWebViewDelegate.m +399 -0
  87. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.h +27 -0
  88. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.m +74 -0
  89. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVUserAgentUtil.h +27 -0
  90. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVUserAgentUtil.m +156 -0
  91. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.h +30 -0
  92. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.m +34 -0
  93. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.h +35 -0
  94. package/ios/Pods/CapacitorCordova/ios/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.m +63 -0
  95. package/ios/Pods/Local Podspecs/Capacitor.podspec.json +31 -0
  96. package/ios/Pods/Manifest.lock +23 -0
  97. package/ios/Pods/Pods.xcodeproj/project.pbxproj +1489 -0
  98. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/Capacitor.xcscheme +58 -0
  99. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/CapacitorCordova.xcscheme +58 -0
  100. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/Pods-Plugin.xcscheme +58 -0
  101. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/Pods-PluginTests.xcscheme +58 -0
  102. package/ios/Pods/Pods.xcodeproj/xcuserdata/martindonadieu.xcuserdatad/xcschemes/xcschememanagement.plist +39 -0
  103. package/ios/Pods/Target Support Files/Capacitor/Capacitor-Info.plist +26 -0
  104. package/ios/Pods/Target Support Files/Capacitor/Capacitor-dummy.m +5 -0
  105. package/ios/Pods/Target Support Files/Capacitor/Capacitor-prefix.pch +12 -0
  106. package/ios/Pods/Target Support Files/Capacitor/Capacitor.debug.xcconfig +16 -0
  107. package/ios/Pods/Target Support Files/Capacitor/Capacitor.modulemap +8 -0
  108. package/ios/Pods/Target Support Files/Capacitor/Capacitor.release.xcconfig +16 -0
  109. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-Info.plist +26 -0
  110. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-dummy.m +5 -0
  111. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-prefix.pch +12 -0
  112. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova-umbrella.h +32 -0
  113. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova.debug.xcconfig +13 -0
  114. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova.modulemap +6 -0
  115. package/ios/Pods/Target Support Files/CapacitorCordova/CapacitorCordova.release.xcconfig +13 -0
  116. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-Info.plist +26 -0
  117. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-acknowledgements.markdown +55 -0
  118. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-acknowledgements.plist +93 -0
  119. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-dummy.m +5 -0
  120. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin-umbrella.h +16 -0
  121. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin.debug.xcconfig +14 -0
  122. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin.modulemap +6 -0
  123. package/ios/Pods/Target Support Files/Pods-Plugin/Pods-Plugin.release.xcconfig +14 -0
  124. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-Info.plist +26 -0
  125. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-acknowledgements.markdown +55 -0
  126. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-acknowledgements.plist +93 -0
  127. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-dummy.m +5 -0
  128. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-frameworks.sh +188 -0
  129. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests-umbrella.h +16 -0
  130. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.debug.xcconfig +15 -0
  131. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.modulemap +6 -0
  132. package/ios/Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.release.xcconfig +15 -0
  133. package/package.json +41 -48
@@ -8,8 +8,6 @@ import android.content.res.Configuration;
8
8
  import android.graphics.Bitmap;
9
9
  import android.graphics.Bitmap.CompressFormat;
10
10
  import android.graphics.BitmapFactory;
11
- import android.graphics.Canvas;
12
- import android.graphics.ImageFormat;
13
11
  import android.graphics.Matrix;
14
12
  import android.graphics.Rect;
15
13
  import android.graphics.YuvImage;
@@ -28,9 +26,6 @@ import android.view.Gravity;
28
26
  import android.view.LayoutInflater;
29
27
  import android.view.MotionEvent;
30
28
  import android.view.Surface;
31
- import android.view.Surface;
32
- import android.view.SurfaceHolder;
33
- import android.view.SurfaceView;
34
29
  import android.view.View;
35
30
  import android.view.ViewGroup;
36
31
  import android.view.ViewTreeObserver;
@@ -43,7 +38,9 @@ import java.io.File;
43
38
  import java.io.FileOutputStream;
44
39
  import java.io.IOException;
45
40
  import java.util.Arrays;
41
+ import java.util.Collections;
46
42
  import java.util.List;
43
+ import java.util.Objects;
47
44
  import java.util.UUID;
48
45
 
49
46
  public class CameraActivity extends Fragment {
@@ -84,10 +81,9 @@ public class CameraActivity extends Fragment {
84
81
  STOPPED,
85
82
  }
86
83
 
87
- private RecordingState mRecordingState = RecordingState.INITIALIZING;
84
+ private final RecordingState mRecordingState = RecordingState.INITIALIZING;
88
85
  private MediaRecorder mRecorder = null;
89
86
  private String recordFilePath;
90
- private float opacity;
91
87
 
92
88
  // The first rear facing camera
93
89
  private int defaultCameraId;
@@ -121,13 +117,12 @@ public class CameraActivity extends Fragment {
121
117
  appResourcesPackage = getActivity().getPackageName();
122
118
 
123
119
  // Inflate the layout for this fragment
124
- view =
125
- inflater.inflate(
126
- getResources()
127
- .getIdentifier("camera_activity", "layout", appResourcesPackage),
128
- container,
129
- false
130
- );
120
+ view = inflater.inflate(
121
+ getResources()
122
+ .getIdentifier("camera_activity", "layout", appResourcesPackage),
123
+ container,
124
+ false
125
+ );
131
126
  createCameraPreview();
132
127
  return view;
133
128
  }
@@ -149,19 +144,17 @@ public class CameraActivity extends Fragment {
149
144
  height
150
145
  );
151
146
  layoutParams.setMargins(x, y, 0, 0);
152
- frameContainerLayout =
153
- (FrameLayout) view.findViewById(
154
- getResources()
155
- .getIdentifier("frame_container", "id", appResourcesPackage)
156
- );
147
+ frameContainerLayout = (FrameLayout) view.findViewById(
148
+ getResources()
149
+ .getIdentifier("frame_container", "id", appResourcesPackage)
150
+ );
157
151
  frameContainerLayout.setLayoutParams(layoutParams);
158
152
 
159
153
  //video view
160
154
  mPreview = new Preview(getActivity(), enableOpacity);
161
- mainLayout =
162
- (FrameLayout) view.findViewById(
163
- getResources().getIdentifier("video_view", "id", appResourcesPackage)
164
- );
155
+ mainLayout = (FrameLayout) view.findViewById(
156
+ getResources().getIdentifier("video_view", "id", appResourcesPackage)
157
+ );
165
158
  mainLayout.setLayoutParams(
166
159
  new RelativeLayout.LayoutParams(
167
160
  RelativeLayout.LayoutParams.MATCH_PARENT,
@@ -280,10 +273,10 @@ public class CameraActivity extends Fragment {
280
273
  switch (event.getAction()) {
281
274
  case MotionEvent.ACTION_DOWN:
282
275
  if (mLastTouchX == 0 || mLastTouchY == 0) {
283
- mLastTouchX =
284
- (int) event.getRawX() - layoutParams.leftMargin;
285
- mLastTouchY =
286
- (int) event.getRawY() - layoutParams.topMargin;
276
+ mLastTouchX = (int) event.getRawX() -
277
+ layoutParams.leftMargin;
278
+ mLastTouchY = (int) event.getRawY() -
279
+ layoutParams.topMargin;
287
280
  } else {
288
281
  mLastTouchX = (int) event.getRawX();
289
282
  mLastTouchY = (int) event.getRawY();
@@ -363,17 +356,22 @@ public class CameraActivity extends Fragment {
363
356
  );
364
357
  }
365
358
 
366
- private void setDefaultCameraId() {
367
- // Find the total number of cameras available
368
- numberOfCameras = Camera.getNumberOfCameras();
359
+ private int getNumberOfCameras() {
360
+ if (numberOfCameras == 0) {
361
+ numberOfCameras = Camera.getNumberOfCameras();
362
+ }
369
363
 
364
+ return numberOfCameras;
365
+ }
366
+
367
+ private void setDefaultCameraId() {
370
368
  int facing = "front".equals(defaultCamera)
371
369
  ? Camera.CameraInfo.CAMERA_FACING_FRONT
372
370
  : Camera.CameraInfo.CAMERA_FACING_BACK;
373
371
 
374
372
  // Find the ID of the default camera
375
373
  Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
376
- for (int i = 0; i < numberOfCameras; i++) {
374
+ for (int i = 0; i < getNumberOfCameras(); i++) {
377
375
  Camera.getCameraInfo(i, cameraInfo);
378
376
  if (cameraInfo.facing == facing) {
379
377
  defaultCameraId = i;
@@ -384,16 +382,17 @@ public class CameraActivity extends Fragment {
384
382
 
385
383
  @Override
386
384
  public void onResume() {
385
+ // This gets called when getting started AND after the app gets resumed.
387
386
  super.onResume();
388
387
 
389
- mCamera = Camera.open(defaultCameraId);
388
+ // Make sure that we load the currently "locked" camera. If the camera gets changed
389
+ // during use, we want to "restore" that camera back as soon as we come back to the app.
390
+ mCamera = Camera.open(cameraCurrentlyLocked);
390
391
 
391
- if (cameraParameters != null) {
392
+ if (cameraCurrentlyLocked == 0 && cameraParameters != null) {
392
393
  mCamera.setParameters(cameraParameters);
393
394
  }
394
395
 
395
- cameraCurrentlyLocked = defaultCameraId;
396
-
397
396
  if (mPreview.mPreviewSize == null) {
398
397
  mPreview.setCamera(mCamera, cameraCurrentlyLocked);
399
398
  eventListener.onCameraStarted();
@@ -440,8 +439,8 @@ public class CameraActivity extends Fragment {
440
439
  frameContainerLayout.getWidth(),
441
440
  frameContainerLayout.getHeight()
442
441
  );
443
- camViewLayout.gravity =
444
- Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
442
+ camViewLayout.gravity = Gravity.CENTER_HORIZONTAL |
443
+ Gravity.CENTER_VERTICAL;
445
444
  frameCamContainerLayout.setLayoutParams(camViewLayout);
446
445
  }
447
446
  }
@@ -458,7 +457,6 @@ public class CameraActivity extends Fragment {
458
457
  if (mCamera != null) {
459
458
  setDefaultCameraId();
460
459
  mPreview.setCamera(null, -1);
461
- mCamera.setPreviewCallback(null);
462
460
  mCamera.release();
463
461
  mCamera = null;
464
462
  }
@@ -512,7 +510,7 @@ public class CameraActivity extends Fragment {
512
510
  if (numberOfCameras == 1) {
513
511
  //There is only one camera available
514
512
  } else {
515
- Log.d(TAG, "numberOfCameras: " + numberOfCameras);
513
+ Log.d(TAG, "numberOfCameras: " + getNumberOfCameras());
516
514
 
517
515
  // OK, we have multiple cameras. Release this camera -> cameraCurrentlyLocked
518
516
  if (mCamera != null) {
@@ -527,10 +525,11 @@ public class CameraActivity extends Fragment {
527
525
  "cameraCurrentlyLocked := " + Integer.toString(cameraCurrentlyLocked)
528
526
  );
529
527
  try {
530
- cameraCurrentlyLocked = (cameraCurrentlyLocked + 1) % numberOfCameras;
528
+ cameraCurrentlyLocked = (cameraCurrentlyLocked + 1) %
529
+ getNumberOfCameras();
531
530
  Log.d(TAG, "cameraCurrentlyLocked new: " + cameraCurrentlyLocked);
532
531
  } catch (Exception exception) {
533
- Log.d(TAG, exception.getMessage());
532
+ Log.d(TAG, Objects.requireNonNull(exception.getMessage()));
534
533
  }
535
534
 
536
535
  // Acquire the next camera and request Preview to reconfigure parameters.
@@ -619,7 +618,7 @@ public class CameraActivity extends Fragment {
619
618
  cache = getActivity().getCacheDir();
620
619
 
621
620
  // Create the cache directory if it doesn't exist
622
- cache.mkdirs();
621
+ final boolean mkdirs = cache.mkdirs();
623
622
  return cache.getAbsolutePath();
624
623
  }
625
624
 
@@ -637,39 +636,109 @@ public class CameraActivity extends Fragment {
637
636
  Log.d(TAG, "CameraPreview jpegPictureCallback");
638
637
 
639
638
  try {
640
- if (!disableExifHeaderStripping) {
641
- Matrix matrix = new Matrix();
642
- if (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT) {
643
- matrix.preScale(1.0f, -1.0f);
644
- }
645
-
646
- ExifInterface exifInterface = new ExifInterface(
647
- new ByteArrayInputStream(data)
648
- );
649
- int rotation = exifInterface.getAttributeInt(
650
- ExifInterface.TAG_ORIENTATION,
651
- ExifInterface.ORIENTATION_NORMAL
652
- );
653
- int rotationInDegrees = exifToDegrees(rotation);
639
+ Log.d(TAG, "Inside jpegPictureCallback");
654
640
 
655
- if (rotation != 0f) {
656
- matrix.preRotate(rotationInDegrees);
657
- }
641
+ if (!disableExifHeaderStripping) {
642
+ try {
643
+ ExifInterface exifInterface = new ExifInterface(
644
+ new ByteArrayInputStream(data)
645
+ );
646
+ int orientation = exifInterface.getAttributeInt(
647
+ ExifInterface.TAG_ORIENTATION,
648
+ ExifInterface.ORIENTATION_NORMAL
649
+ );
650
+ Log.d(TAG, "EXIF Orientation: " + orientation);
658
651
 
659
- // Check if matrix has changed. In that case, apply matrix and override data
660
- if (!matrix.isIdentity()) {
661
- Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
662
- bitmap = applyMatrix(bitmap, matrix);
652
+ int rotation = 0;
653
+ switch (orientation) {
654
+ case ExifInterface.ORIENTATION_ROTATE_90:
655
+ rotation = 90;
656
+ break;
657
+ case ExifInterface.ORIENTATION_ROTATE_180:
658
+ rotation = 180;
659
+ break;
660
+ case ExifInterface.ORIENTATION_ROTATE_270:
661
+ rotation = 270;
662
+ break;
663
+ }
664
+ Log.d(
665
+ TAG,
666
+ "Camera facing: " +
667
+ (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT
668
+ ? "front"
669
+ : "rear")
670
+ );
671
+ Log.d(TAG, "Image rotation: " + rotation);
672
+ Log.d(
673
+ TAG,
674
+ "Image flipped: " +
675
+ (cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT)
676
+ );
663
677
 
664
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
665
- bitmap.compress(CompressFormat.JPEG, currentQuality, outputStream);
666
- data = outputStream.toByteArray();
678
+ if (
679
+ cameraCurrentlyLocked == Camera.CameraInfo.CAMERA_FACING_FRONT
680
+ ) {
681
+ Log.d(TAG, "Front camera EXIF Orientation: " + orientation);
682
+ // Rotate the bitmap based on the orientation value
683
+ Matrix matrix = new Matrix();
684
+ switch (orientation) {
685
+ case ExifInterface.ORIENTATION_ROTATE_90:
686
+ matrix.postRotate(270);
687
+ break;
688
+ case ExifInterface.ORIENTATION_ROTATE_180:
689
+ matrix.postRotate(180);
690
+ break;
691
+ case ExifInterface.ORIENTATION_ROTATE_270:
692
+ matrix.postRotate(90);
693
+ break;
694
+ }
695
+ // Flip the bitmap horizontally for the front camera
696
+ matrix.postScale(-1, 1);
697
+ Bitmap bitmap = BitmapFactory.decodeByteArray(
698
+ data,
699
+ 0,
700
+ data.length
701
+ );
702
+ bitmap = Bitmap.createBitmap(
703
+ bitmap,
704
+ 0,
705
+ 0,
706
+ bitmap.getWidth(),
707
+ bitmap.getHeight(),
708
+ matrix,
709
+ true
710
+ );
711
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
712
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
713
+ data = outputStream.toByteArray();
714
+ } else if (rotation != 0) {
715
+ Matrix matrix = new Matrix();
716
+ matrix.postRotate(rotation);
717
+ Bitmap bitmap = BitmapFactory.decodeByteArray(
718
+ data,
719
+ 0,
720
+ data.length
721
+ );
722
+ bitmap = Bitmap.createBitmap(
723
+ bitmap,
724
+ 0,
725
+ 0,
726
+ bitmap.getWidth(),
727
+ bitmap.getHeight(),
728
+ matrix,
729
+ true
730
+ );
731
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
732
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
733
+ data = outputStream.toByteArray();
734
+ }
735
+ } catch (IOException e) {
736
+ Log.e(TAG, "Failed to read EXIF data", e);
667
737
  }
668
738
  }
669
739
 
670
740
  if (!storeToFile) {
671
741
  String encodedImage = Base64.encodeToString(data, Base64.NO_WRAP);
672
-
673
742
  eventListener.onPictureTaken(encodedImage);
674
743
  } else {
675
744
  String path = getTempFilePath();
@@ -696,105 +765,6 @@ public class CameraActivity extends Fragment {
696
765
  }
697
766
  };
698
767
 
699
- private Camera.Size getOptimalPictureSize(
700
- final int width,
701
- final int height,
702
- final Camera.Size previewSize,
703
- final List<Camera.Size> supportedSizes
704
- ) {
705
- /*
706
- get the supportedPictureSize that:
707
- - matches exactly width and height
708
- - has the closest aspect ratio to the preview aspect ratio
709
- - has picture.width and picture.height closest to width and height
710
- - has the highest supported picture width and height up to 2 Megapixel if width == 0 || height == 0
711
- */
712
- Camera.Size size = mCamera.new Size(width, height);
713
-
714
- // convert to landscape if necessary
715
- if (size.width < size.height) {
716
- int temp = size.width;
717
- size.width = size.height;
718
- size.height = temp;
719
- }
720
-
721
- Camera.Size requestedSize = mCamera.new Size(size.width, size.height);
722
-
723
- double previewAspectRatio = (double) previewSize.width /
724
- (double) previewSize.height;
725
-
726
- if (previewAspectRatio < 1.0) {
727
- // reset ratio to landscape
728
- previewAspectRatio = 1.0 / previewAspectRatio;
729
- }
730
-
731
- Log.d(TAG, "CameraPreview previewAspectRatio " + previewAspectRatio);
732
-
733
- double aspectTolerance = 0.1;
734
- double bestDifference = Double.MAX_VALUE;
735
-
736
- for (int i = 0; i < supportedSizes.size(); i++) {
737
- Camera.Size supportedSize = supportedSizes.get(i);
738
-
739
- // Perfect match
740
- if (supportedSize.equals(requestedSize)) {
741
- Log.d(
742
- TAG,
743
- "CameraPreview optimalPictureSize " +
744
- supportedSize.width +
745
- 'x' +
746
- supportedSize.height
747
- );
748
- return supportedSize;
749
- }
750
-
751
- double difference = Math.abs(
752
- previewAspectRatio -
753
- ((double) supportedSize.width / (double) supportedSize.height)
754
- );
755
-
756
- if (difference < bestDifference - aspectTolerance) {
757
- // better aspectRatio found
758
- if (
759
- (width != 0 && height != 0) ||
760
- (supportedSize.width * supportedSize.height < 2048 * 1024)
761
- ) {
762
- size.width = supportedSize.width;
763
- size.height = supportedSize.height;
764
- bestDifference = difference;
765
- }
766
- } else if (difference < bestDifference + aspectTolerance) {
767
- // same aspectRatio found (within tolerance)
768
- if (width == 0 || height == 0) {
769
- // set highest supported resolution below 2 Megapixel
770
- if (
771
- (size.width < supportedSize.width) &&
772
- (supportedSize.width * supportedSize.height < 2048 * 1024)
773
- ) {
774
- size.width = supportedSize.width;
775
- size.height = supportedSize.height;
776
- }
777
- } else {
778
- // check if this pictureSize closer to requested width and height
779
- if (
780
- Math.abs(
781
- width * height - supportedSize.width * supportedSize.height
782
- ) <
783
- Math.abs(width * height - size.width * size.height)
784
- ) {
785
- size.width = supportedSize.width;
786
- size.height = supportedSize.height;
787
- }
788
- }
789
- }
790
- }
791
- Log.d(
792
- TAG,
793
- "CameraPreview optimalPictureSize " + size.width + 'x' + size.height
794
- );
795
- return size;
796
- }
797
-
798
768
  static byte[] rotateNV21(
799
769
  final byte[] yuv,
800
770
  final int width,
@@ -841,7 +811,6 @@ public class CameraActivity extends Fragment {
841
811
 
842
812
  public void setOpacity(final float opacity) {
843
813
  Log.d(TAG, "set opacity:" + opacity);
844
- this.opacity = opacity;
845
814
  mPreview.setOpacity(opacity);
846
815
  }
847
816
 
@@ -858,13 +827,12 @@ public class CameraActivity extends Fragment {
858
827
  mPreview.getCameraFacing() ==
859
828
  Camera.CameraInfo.CAMERA_FACING_FRONT
860
829
  ) {
861
- bytes =
862
- rotateNV21(
863
- bytes,
864
- size.width,
865
- size.height,
866
- (360 - orientation) % 360
867
- );
830
+ bytes = rotateNV21(
831
+ bytes,
832
+ size.width,
833
+ size.height,
834
+ (360 - orientation) % 360
835
+ );
868
836
  } else {
869
837
  bytes = rotateNV21(bytes, size.width, size.height, orientation);
870
838
  }
@@ -898,6 +866,43 @@ public class CameraActivity extends Fragment {
898
866
  );
899
867
  }
900
868
 
869
+ private Camera.Size getOptimalPictureSizeForPreview(
870
+ int width,
871
+ int height,
872
+ Camera.Size previewSize,
873
+ List<Camera.Size> supportedSizes
874
+ ) {
875
+ Log.d(TAG, "Requested picture size: " + width + "x" + height);
876
+ Log.d(TAG, "Preview size: " + previewSize.width + "x" + previewSize.height);
877
+ double targetRatio = (double) previewSize.width / previewSize.height;
878
+ Camera.Size optimalSize = null;
879
+ double minDiff = Double.MAX_VALUE;
880
+
881
+ for (Camera.Size size : supportedSizes) {
882
+ double ratio = (double) size.width / size.height;
883
+ if (Math.abs(ratio - targetRatio) > 0.1) continue;
884
+ if (Math.abs(size.height - height) < minDiff) {
885
+ optimalSize = size;
886
+ minDiff = Math.abs(size.height - height);
887
+ }
888
+ }
889
+
890
+ if (optimalSize == null) {
891
+ minDiff = Double.MAX_VALUE;
892
+ for (Camera.Size size : supportedSizes) {
893
+ if (Math.abs(size.height - height) < minDiff) {
894
+ optimalSize = size;
895
+ minDiff = Math.abs(size.height - height);
896
+ }
897
+ }
898
+ }
899
+ Log.d(
900
+ TAG,
901
+ "Optimal picture size: " + optimalSize.width + "x" + optimalSize.height
902
+ );
903
+ return optimalSize;
904
+ }
905
+
901
906
  public void takePicture(
902
907
  final int width,
903
908
  final int height,
@@ -924,7 +929,7 @@ public class CameraActivity extends Fragment {
924
929
  public void run() {
925
930
  Camera.Parameters params = mCamera.getParameters();
926
931
 
927
- Camera.Size size = getOptimalPictureSize(
932
+ Camera.Size size = getOptimalPictureSizeForPreview(
928
933
  width,
929
934
  height,
930
935
  params.getPreviewSize(),
@@ -1026,11 +1031,7 @@ public class CameraActivity extends Fragment {
1026
1031
 
1027
1032
  Camera.Parameters cameraParams = mCamera.getParameters();
1028
1033
  if (withFlash) {
1029
- cameraParams.setFlashMode(
1030
- withFlash
1031
- ? Camera.Parameters.FLASH_MODE_TORCH
1032
- : Camera.Parameters.FLASH_MODE_OFF
1033
- );
1034
+ cameraParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
1034
1035
  mCamera.setParameters(cameraParams);
1035
1036
  mCamera.startPreview();
1036
1037
  }
@@ -1048,8 +1049,10 @@ public class CameraActivity extends Fragment {
1048
1049
  CamcorderProfile.QUALITY_HIGH
1049
1050
  )
1050
1051
  ) {
1051
- profile =
1052
- CamcorderProfile.get(defaultCameraId, CamcorderProfile.QUALITY_HIGH);
1052
+ profile = CamcorderProfile.get(
1053
+ defaultCameraId,
1054
+ CamcorderProfile.QUALITY_HIGH
1055
+ );
1053
1056
  } else {
1054
1057
  if (
1055
1058
  CamcorderProfile.hasProfile(
@@ -1057,11 +1060,10 @@ public class CameraActivity extends Fragment {
1057
1060
  CamcorderProfile.QUALITY_480P
1058
1061
  )
1059
1062
  ) {
1060
- profile =
1061
- CamcorderProfile.get(
1062
- defaultCameraId,
1063
- CamcorderProfile.QUALITY_480P
1064
- );
1063
+ profile = CamcorderProfile.get(
1064
+ defaultCameraId,
1065
+ CamcorderProfile.QUALITY_480P
1066
+ );
1065
1067
  } else {
1066
1068
  if (
1067
1069
  CamcorderProfile.hasProfile(
@@ -1069,11 +1071,10 @@ public class CameraActivity extends Fragment {
1069
1071
  CamcorderProfile.QUALITY_720P
1070
1072
  )
1071
1073
  ) {
1072
- profile =
1073
- CamcorderProfile.get(
1074
- defaultCameraId,
1075
- CamcorderProfile.QUALITY_720P
1076
- );
1074
+ profile = CamcorderProfile.get(
1075
+ defaultCameraId,
1076
+ CamcorderProfile.QUALITY_720P
1077
+ );
1077
1078
  } else {
1078
1079
  if (
1079
1080
  CamcorderProfile.hasProfile(
@@ -1081,17 +1082,15 @@ public class CameraActivity extends Fragment {
1081
1082
  CamcorderProfile.QUALITY_1080P
1082
1083
  )
1083
1084
  ) {
1084
- profile =
1085
- CamcorderProfile.get(
1086
- defaultCameraId,
1087
- CamcorderProfile.QUALITY_1080P
1088
- );
1085
+ profile = CamcorderProfile.get(
1086
+ defaultCameraId,
1087
+ CamcorderProfile.QUALITY_1080P
1088
+ );
1089
1089
  } else {
1090
- profile =
1091
- CamcorderProfile.get(
1092
- defaultCameraId,
1093
- CamcorderProfile.QUALITY_LOW
1094
- );
1090
+ profile = CamcorderProfile.get(
1091
+ defaultCameraId,
1092
+ CamcorderProfile.QUALITY_LOW
1093
+ );
1095
1094
  }
1096
1095
  }
1097
1096
  }
@@ -1128,9 +1127,6 @@ public class CameraActivity extends Fragment {
1128
1127
 
1129
1128
  int degrees = 0;
1130
1129
  switch (currentScreenRotation) {
1131
- case Surface.ROTATION_0:
1132
- degrees = 0;
1133
- break;
1134
1130
  case Surface.ROTATION_90:
1135
1131
  degrees = 90;
1136
1132
  break;
@@ -1140,6 +1136,8 @@ public class CameraActivity extends Fragment {
1140
1136
  case Surface.ROTATION_270:
1141
1137
  degrees = 270;
1142
1138
  break;
1139
+ default:
1140
+ break;
1143
1141
  }
1144
1142
 
1145
1143
  int orientation;
@@ -1177,14 +1175,14 @@ public class CameraActivity extends Fragment {
1177
1175
 
1178
1176
  public void muteStream(boolean mute, Activity activity) {
1179
1177
  AudioManager audioManager =
1180
- (
1181
- (AudioManager) activity
1178
+ ((AudioManager) activity
1182
1179
  .getApplicationContext()
1183
- .getSystemService(Context.AUDIO_SERVICE)
1184
- );
1185
- int direction = mute
1186
- ? audioManager.ADJUST_MUTE
1187
- : audioManager.ADJUST_UNMUTE;
1180
+ .getSystemService(Context.AUDIO_SERVICE));
1181
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
1182
+ int direction = mute
1183
+ ? AudioManager.ADJUST_MUTE
1184
+ : AudioManager.ADJUST_UNMUTE;
1185
+ }
1188
1186
  }
1189
1187
 
1190
1188
  public void setFocusArea(
@@ -1199,12 +1197,14 @@ public class CameraActivity extends Fragment {
1199
1197
 
1200
1198
  Rect focusRect = calculateTapArea(pointX, pointY, 1f);
1201
1199
  parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
1202
- parameters.setFocusAreas(Arrays.asList(new Camera.Area(focusRect, 1000)));
1200
+ parameters.setFocusAreas(
1201
+ Collections.singletonList(new Camera.Area(focusRect, 1000))
1202
+ );
1203
1203
 
1204
1204
  if (parameters.getMaxNumMeteringAreas() > 0) {
1205
1205
  Rect meteringRect = calculateTapArea(pointX, pointY, 1.5f);
1206
1206
  parameters.setMeteringAreas(
1207
- Arrays.asList(new Camera.Area(meteringRect, 1000))
1207
+ Collections.singletonList(new Camera.Area(meteringRect, 1000))
1208
1208
  );
1209
1209
  }
1210
1210
 
@@ -1212,7 +1212,7 @@ public class CameraActivity extends Fragment {
1212
1212
  setCameraParameters(parameters);
1213
1213
  mCamera.autoFocus(callback);
1214
1214
  } catch (Exception e) {
1215
- Log.d(TAG, e.getMessage());
1215
+ Log.d(TAG, Objects.requireNonNull(e.getMessage()));
1216
1216
  callback.onAutoFocus(false, this.mCamera);
1217
1217
  }
1218
1218
  }
@@ -1232,10 +1232,10 @@ public class CameraActivity extends Fragment {
1232
1232
  y = height - 100;
1233
1233
  }
1234
1234
  return new Rect(
1235
- Math.round((x - 100) * 2000 / width - 1000),
1236
- Math.round((y - 100) * 2000 / height - 1000),
1237
- Math.round((x + 100) * 2000 / width - 1000),
1238
- Math.round((y + 100) * 2000 / height - 1000)
1235
+ Math.round(((x - 100) * 2000) / width - 1000),
1236
+ Math.round(((y - 100) * 2000) / height - 1000),
1237
+ Math.round(((x + 100) * 2000) / width - 1000),
1238
+ Math.round(((y + 100) * 2000) / height - 1000)
1239
1239
  );
1240
1240
  }
1241
1241