capacitor-camera-module 0.0.33 → 0.0.34

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.
@@ -15,7 +15,6 @@ import com.getcapacitor.annotation.PermissionCallback;
15
15
 
16
16
  import android.view.ViewGroup;
17
17
  import android.widget.FrameLayout;
18
- import androidx.appcompat.app.AppCompatActivity;
19
18
  import androidx.core.content.ContextCompat;
20
19
  import androidx.camera.core.CameraSelector;
21
20
  import androidx.camera.core.Preview;
@@ -67,7 +66,11 @@ import com.google.mlkit.vision.barcode.common.Barcode;
67
66
  import com.google.mlkit.vision.barcode.BarcodeScanner;
68
67
  import com.google.mlkit.vision.barcode.BarcodeScanning;
69
68
 
69
+ import android.graphics.YuvImage;
70
+ import android.graphics.Rect;
71
+ import java.util.concurrent.Executors;
70
72
 
73
+ import java.util.concurrent.ExecutorService;
71
74
 
72
75
 
73
76
  @CapacitorPlugin(
@@ -92,7 +95,6 @@ public class CameraModulePlugin extends Plugin {
92
95
 
93
96
  private PreviewView previewView;
94
97
  private ProcessCameraProvider cameraProvider;
95
- private CameraSelector cameraSelector;
96
98
 
97
99
  private Camera camera;
98
100
 
@@ -101,12 +103,17 @@ public class CameraModulePlugin extends Plugin {
101
103
 
102
104
  private ImageCapture imageCapture;
103
105
 
104
- private PluginCall pendingCaptureCall;
105
-
106
106
  private ImageAnalysis imageAnalysis;
107
107
  private boolean isScanning = false;
108
108
  private PluginCall scanCall;
109
109
 
110
+ private CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
111
+
112
+ private BarcodeScanner barcodeScanner;
113
+
114
+ private final ExecutorService barcodeExecutor = Executors.newSingleThreadExecutor();
115
+
116
+
110
117
 
111
118
  @Override
112
119
  public void load() {
@@ -236,6 +243,12 @@ public class CameraModulePlugin extends Plugin {
236
243
  @PluginMethod
237
244
  public void startPreview(PluginCall call) {
238
245
  getActivity().runOnUiThread(() -> {
246
+
247
+ if (previewView != null) {
248
+ call.resolve();
249
+ return;
250
+ }
251
+
239
252
  previewView = new PreviewView(getContext());
240
253
  previewView.setLayoutParams(
241
254
  new FrameLayout.LayoutParams(
@@ -269,7 +282,7 @@ public class CameraModulePlugin extends Plugin {
269
282
  .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
270
283
  .build();
271
284
 
272
- cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
285
+
273
286
 
274
287
  cameraProvider.unbindAll();
275
288
 
@@ -306,6 +319,11 @@ public class CameraModulePlugin extends Plugin {
306
319
  previewView = null;
307
320
  }
308
321
 
322
+ if (barcodeScanner != null) {
323
+ barcodeScanner.close();
324
+ barcodeScanner = null;
325
+ }
326
+
309
327
  call.resolve();
310
328
  });
311
329
  }
@@ -355,6 +373,10 @@ public class CameraModulePlugin extends Plugin {
355
373
  return;
356
374
  }
357
375
 
376
+ if (savedCall != null) {
377
+ call.reject("Gallery already open");
378
+ return;
379
+ }
358
380
  savedCall = call;
359
381
 
360
382
  Intent intent = new Intent(
@@ -404,11 +426,19 @@ public class CameraModulePlugin extends Plugin {
404
426
  float ratio = (float) width / height;
405
427
 
406
428
  if (width > height) {
407
- if (width <= maxSize) return bitmap;
429
+ if (width <= maxSize && height <= maxSize) {
430
+ Bitmap.Config config =
431
+ bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888;
432
+ return bitmap.copy(config, false);
433
+ }
408
434
  width = maxSize;
409
435
  height = Math.round(width / ratio);
410
436
  } else {
411
- if (height <= maxSize) return bitmap;
437
+ if (height <= maxSize && width <= maxSize) {
438
+ Bitmap.Config config =
439
+ bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888;
440
+ return bitmap.copy(config, false);
441
+ }
412
442
  height = maxSize;
413
443
  width = Math.round(height * ratio);
414
444
  }
@@ -558,6 +588,11 @@ public class CameraModulePlugin extends Plugin {
558
588
  ) {
559
589
  try {
560
590
  Bitmap bitmap = imageProxyToBitmap(image);
591
+ if (bitmap == null) {
592
+ image.close();
593
+ call.reject("Failed to convert image");
594
+ return;
595
+ }
561
596
  int rotation = image.getImageInfo().getRotationDegrees();
562
597
  bitmap = rotateBitmap(bitmap, rotation);
563
598
  image.close();
@@ -600,15 +635,45 @@ public class CameraModulePlugin extends Plugin {
600
635
  }
601
636
 
602
637
  private Bitmap imageProxyToBitmap(ImageProxy image) {
603
- ImageProxy.PlaneProxy[] planes = image.getPlanes();
604
- ByteBuffer buffer = planes[0].getBuffer();
605
- byte[] bytes = new byte[buffer.remaining()];
606
- buffer.get(bytes);
638
+ Image mediaImage = image.getImage();
639
+ if (mediaImage == null) return null;
640
+
641
+ ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
642
+ ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
643
+ ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
644
+
645
+ int ySize = yBuffer.remaining();
646
+ int uSize = uBuffer.remaining();
647
+ int vSize = vBuffer.remaining();
648
+
649
+ byte[] nv21 = new byte[ySize + uSize + vSize];
650
+
651
+ yBuffer.get(nv21, 0, ySize);
652
+ vBuffer.get(nv21, ySize, vSize);
653
+ uBuffer.get(nv21, ySize + vSize, uSize);
654
+
655
+ YuvImage yuvImage =
656
+ new YuvImage(
657
+ nv21,
658
+ ImageFormat.NV21,
659
+ image.getWidth(),
660
+ image.getHeight(),
661
+ null
662
+ );
607
663
 
608
- return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
664
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
665
+ yuvImage.compressToJpeg(
666
+ new Rect(0, 0, image.getWidth(), image.getHeight()),
667
+ 100,
668
+ out
669
+ );
670
+
671
+ byte[] jpegBytes = out.toByteArray();
672
+ return BitmapFactory.decodeByteArray(jpegBytes, 0, jpegBytes.length);
609
673
  }
610
674
 
611
675
 
676
+
612
677
  private Bitmap rotateBitmap(Bitmap bitmap, int rotationDegrees) {
613
678
  if (rotationDegrees == 0) return bitmap;
614
679
 
@@ -627,29 +692,6 @@ public class CameraModulePlugin extends Plugin {
627
692
  }
628
693
 
629
694
 
630
-
631
- private Bitmap mirrorBitmap(Bitmap bitmap) {
632
- Matrix matrix = new Matrix();
633
- matrix.preScale(-1, 1);
634
-
635
- return Bitmap.createBitmap(
636
- bitmap,
637
- 0,
638
- 0,
639
- bitmap.getWidth(),
640
- bitmap.getHeight(),
641
- matrix,
642
- true
643
- );
644
- }
645
-
646
- private String bitmapToBase64(Bitmap bitmap) {
647
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
648
- bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream);
649
- byte[] bytes = outputStream.toByteArray();
650
- return Base64.encodeToString(bytes, Base64.NO_WRAP);
651
- }
652
-
653
695
  @PluginMethod
654
696
  public void startBarcodeScan(PluginCall call) {
655
697
 
@@ -673,6 +715,10 @@ public class CameraModulePlugin extends Plugin {
673
715
  return;
674
716
  }
675
717
 
718
+ barcodeScanner = BarcodeScanning.getClient();
719
+
720
+ call.setKeepAlive(true);
721
+
676
722
  scanCall = call;
677
723
  isScanning = true;
678
724
 
@@ -684,7 +730,7 @@ public class CameraModulePlugin extends Plugin {
684
730
  .build();
685
731
 
686
732
  imageAnalysis.setAnalyzer(
687
- ContextCompat.getMainExecutor(getContext()),
733
+ barcodeExecutor,
688
734
  this::processBarcode
689
735
  );
690
736
 
@@ -698,6 +744,10 @@ public class CameraModulePlugin extends Plugin {
698
744
  .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
699
745
  .build();
700
746
 
747
+ if (cameraSelector == null) {
748
+ cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
749
+ }
750
+
701
751
  camera = cameraProvider.bindToLifecycle(
702
752
  getActivity(),
703
753
  cameraSelector,
@@ -705,9 +755,13 @@ public class CameraModulePlugin extends Plugin {
705
755
  imageCapture,
706
756
  imageAnalysis
707
757
  );
758
+
759
+ call.resolve();
760
+
708
761
  }
709
762
 
710
763
  private void processBarcode(ImageProxy imageProxy) {
764
+
711
765
  if (!isScanning) {
712
766
  imageProxy.close();
713
767
  return;
@@ -719,19 +773,26 @@ public class CameraModulePlugin extends Plugin {
719
773
  return;
720
774
  }
721
775
 
722
- InputImage image =
723
- InputImage.fromMediaImage(
724
- mediaImage,
725
- imageProxy.getImageInfo().getRotationDegrees()
726
- );
727
-
728
- BarcodeScanner scanner =
729
- BarcodeScanning.getClient();
776
+ InputImage image = InputImage.fromMediaImage(
777
+ mediaImage,
778
+ imageProxy.getImageInfo().getRotationDegrees()
779
+ );
730
780
 
731
- scanner.process(image)
781
+ if (barcodeScanner == null) {
782
+ imageProxy.close();
783
+ return;
784
+ }
785
+ barcodeScanner.process(image)
732
786
  .addOnSuccessListener(barcodes -> {
733
- if (!barcodes.isEmpty() && isScanning) {
734
787
 
788
+ if (!isScanning) {
789
+ imageProxy.close();
790
+ return;
791
+ }
792
+
793
+ if (!barcodes.isEmpty()) {
794
+
795
+ isScanning = false;
735
796
  vibrateOnce();
736
797
 
737
798
  Barcode barcode = barcodes.get(0);
@@ -740,36 +801,63 @@ public class CameraModulePlugin extends Plugin {
740
801
  ret.put("rawValue", barcode.getRawValue());
741
802
  ret.put("format", barcode.getFormat());
742
803
 
743
- isScanning = false;
744
- imageProxy.close();
804
+ if (scanCall != null) {
805
+ scanCall.resolve(ret);
806
+ scanCall.setKeepAlive(false);
807
+ scanCall = null;
808
+
809
+ }
810
+
811
+ if (barcodeScanner != null) {
812
+ barcodeScanner.close();
813
+ barcodeScanner = null;
814
+ }
745
815
 
746
- scanCall.resolve(ret);
747
- scanCall = null;
748
816
 
749
817
  stopBarcodeScanInternal();
750
- } else {
751
- imageProxy.close();
752
818
  }
819
+
820
+ imageProxy.close();
753
821
  })
754
822
  .addOnFailureListener(e -> {
755
823
  imageProxy.close();
756
824
  });
757
825
  }
758
826
 
827
+
759
828
  private void stopBarcodeScanInternal() {
760
- if (imageAnalysis != null) {
761
- cameraProvider.unbind(imageAnalysis);
762
- imageAnalysis = null;
763
- }
829
+ getActivity().runOnUiThread(() -> {
830
+ if (cameraProvider != null) {
831
+ cameraProvider.unbindAll();
832
+ startCamera();
833
+ }
834
+ });
764
835
  }
765
836
 
837
+
838
+
766
839
  @PluginMethod
767
840
  public void stopBarcodeScan(PluginCall call) {
768
841
  isScanning = false;
842
+ imageAnalysis = null;
843
+
844
+ if (scanCall != null) {
845
+ scanCall.setKeepAlive(false);
846
+ scanCall = null;
847
+ }
848
+
849
+ if (barcodeScanner != null) {
850
+ barcodeScanner.close();
851
+ barcodeScanner = null;
852
+ }
853
+
769
854
  stopBarcodeScanInternal();
855
+
770
856
  call.resolve();
771
857
  }
772
858
 
859
+
860
+
773
861
  private void vibrateOnce() {
774
862
  Vibrator vibrator =
775
863
  (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-camera-module",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
4
4
  "description": "Plugin to request permissiones view camera take phots",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",