BarcodeAnalayzer.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. 
  2. using Android.Gms.Tasks;
  3. using Android.Runtime;
  4. using AndroidX.Camera.Core;
  5. using AndroidX.Camera.View.Transform;
  6. using Avalonia.Threading;
  7. using InABox.Avalonia.Platform.Barcodes;
  8. using Microsoft.Maui.Graphics.Platform;
  9. using System.Diagnostics;
  10. using Xamarin.Google.MLKit.Vision.Barcode.Common;
  11. using Xamarin.Google.MLKit.Vision.BarCode;
  12. using Xamarin.Google.MLKit.Vision.Common;
  13. using Scanner = Xamarin.Google.MLKit.Vision.BarCode.BarcodeScanning;
  14. using Size = Android.Util.Size;
  15. using Point = Microsoft.Maui.Graphics.Point;
  16. using Rect = Microsoft.Maui.Graphics.Rect;
  17. using Android.Graphics;
  18. namespace InABox.Avalonia.Platform.Android.Barcodes;
  19. internal class BarcodeAnalyzer : Java.Lang.Object, ImageAnalysis.IAnalyzer
  20. {
  21. public Size DefaultTargetResolution => Methods.TargetResolution(null);
  22. public int TargetCoordinateSystem => ImageAnalysis.CoordinateSystemViewReferenced;
  23. private readonly HashSet<BarcodeResult> _barcodeResults;
  24. private readonly CameraManager _cameraManager;
  25. private readonly object _resultsLock;
  26. private IBarcodeScanner? _barcodeScanner;
  27. private CoordinateTransform? _coordinateTransform;
  28. private bool _updateCoordinateTransform = false;
  29. private Point _previewViewCenter = new();
  30. private Rect _previewViewRect = new();
  31. internal BarcodeAnalyzer(CameraManager cameraManager)
  32. {
  33. _barcodeResults = [];
  34. _cameraManager = cameraManager;
  35. _resultsLock = new();
  36. _previewViewRect.X = 0;
  37. _previewViewRect.Y = 0;
  38. }
  39. internal void UpdateSymbologies()
  40. {
  41. _barcodeScanner?.Dispose();
  42. _barcodeScanner = Scanner.GetClient(new BarcodeScannerOptions.Builder()
  43. .SetBarcodeFormats(Methods.ConvertBarcodeFormats(_cameraManager?.CameraView?.BarcodeSymbologies ?? BarcodeFormats.All))
  44. .Build());
  45. }
  46. public void Analyze(IImageProxy proxy)
  47. {
  48. try
  49. {
  50. ArgumentNullException.ThrowIfNull(proxy?.Image);
  51. ArgumentNullException.ThrowIfNull(_cameraManager?.CameraView);
  52. ArgumentNullException.ThrowIfNull(_barcodeScanner);
  53. if (_cameraManager._pauseScanning)
  54. return;
  55. if (_updateCoordinateTransform)
  56. {
  57. _coordinateTransform?.Dispose();
  58. _coordinateTransform = _cameraManager.GetCoordinateTransform(proxy);
  59. _previewViewCenter.X = _cameraManager.PreviewView.Width * 0.5;
  60. _previewViewCenter.Y = _cameraManager.PreviewView.Height * 0.5;
  61. _previewViewRect.Width = _cameraManager.PreviewView.Width;
  62. _previewViewRect.Height = _cameraManager.PreviewView.Height;
  63. _updateCoordinateTransform = false;
  64. }
  65. using var inputImage = InputImage.FromMediaImage(proxy.Image, 0);
  66. using var task = _barcodeScanner.Process(inputImage);
  67. var result = TasksClass.Await(task);
  68. Java.Lang.Object? invertedResult = null;
  69. if (_cameraManager._forceInverted)
  70. {
  71. Methods.InvertLuminance(proxy.Image);
  72. using var invertedImage = InputImage.FromMediaImage(proxy.Image, 0);
  73. using var invertedTask = _barcodeScanner.Process(invertedImage);
  74. invertedResult = TasksClass.Await(invertedTask);
  75. }
  76. lock (_resultsLock)
  77. {
  78. _barcodeResults.Clear();
  79. AddResultToSet(result);
  80. AddResultToSet(invertedResult);
  81. _cameraManager.CameraView.DetectionFinished(_barcodeResults);
  82. }
  83. if (_cameraManager._forceFrameCapture || (_cameraManager._captureNextFrame && _barcodeResults.Count > 0))
  84. {
  85. // using var stream = new MemoryStream();
  86. // var bitmap = proxy.ToBitmap();
  87. // bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
  88. // var image = new PlatformImage(stream.ToArray());
  89. // _cameraManager.CameraView.TriggerOnImageCaptured(image);
  90. }
  91. result?.Dispose();
  92. invertedResult?.Dispose();
  93. }
  94. catch (Exception ex)
  95. {
  96. Debug.WriteLine(ex);
  97. }
  98. finally
  99. {
  100. try
  101. {
  102. proxy?.Close();
  103. }
  104. catch (Exception ex)
  105. {
  106. Debug.WriteLine(ex);
  107. Dispatcher.UIThread.InvokeAsync(() => _cameraManager?.Start());
  108. }
  109. }
  110. }
  111. private void AddResultToSet(Java.Lang.Object? result)
  112. {
  113. if (result is not JavaList javaList)
  114. return;
  115. foreach (Barcode barcode in javaList)
  116. {
  117. if (barcode is null)
  118. continue;
  119. if (string.IsNullOrEmpty(barcode.DisplayValue) && string.IsNullOrEmpty(barcode.RawValue))
  120. continue;
  121. var barcodeResult = barcode.AsBarcodeResult(_coordinateTransform);
  122. if ((_cameraManager?._aimMode ?? false) && !barcodeResult.PreviewBoundingBox.Contains(_previewViewCenter))
  123. continue;
  124. if ((_cameraManager?._viewFinderMode ?? false) && !_previewViewRect.Contains(barcodeResult.PreviewBoundingBox))
  125. continue;
  126. _barcodeResults.Add(barcodeResult);
  127. }
  128. }
  129. public void UpdateTransform(Matrix? matrix)
  130. {
  131. _updateCoordinateTransform = true;
  132. }
  133. protected override void Dispose(bool disposing)
  134. {
  135. _coordinateTransform?.Dispose();
  136. _barcodeScanner?.Dispose();
  137. base.Dispose(disposing);
  138. }
  139. }