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
|
-
|
|
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)
|
|
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)
|
|
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
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
);
|
|
727
|
-
|
|
728
|
-
BarcodeScanner scanner =
|
|
729
|
-
BarcodeScanning.getClient();
|
|
776
|
+
InputImage image = InputImage.fromMediaImage(
|
|
777
|
+
mediaImage,
|
|
778
|
+
imageProxy.getImageInfo().getRotationDegrees()
|
|
779
|
+
);
|
|
730
780
|
|
|
731
|
-
|
|
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
|
-
|
|
744
|
-
|
|
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
|
-
|
|
761
|
-
cameraProvider
|
|
762
|
-
|
|
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);
|