diff --git a/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj b/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj
index 845d018..ff206f4 100644
--- a/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj
+++ b/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj
@@ -10,7 +10,7 @@
true
true
enable
- 2.0.1
+ 2.1.0
Alen Friščić
MIT
README.md
@@ -51,12 +51,15 @@
-
-
+
+
+
+
+
diff --git a/BarcodeScanning.Native.Maui/Platform/Android/CameraManager.cs b/BarcodeScanning.Native.Maui/Platform/Android/CameraManager.cs
index 18430a2..1e82b4a 100644
--- a/BarcodeScanning.Native.Maui/Platform/Android/CameraManager.cs
+++ b/BarcodeScanning.Native.Maui/Platform/Android/CameraManager.cs
@@ -230,7 +230,7 @@ internal void UpdateZoomFactor()
UsingRotationDegrees = true
}
.GetOutputTransform(proxy);
- var previewOutputTransform = MainThread.InvokeOnMainThreadAsync(() => _previewView?.OutputTransform).Result;
+ var previewOutputTransform = MainThread.InvokeOnMainThreadAsync(() => _previewView?.OutputTransform).GetAwaiter().GetResult();
if (imageOutputTransform is not null && previewOutputTransform is not null)
return new CoordinateTransform(imageOutputTransform, previewOutputTransform);
diff --git a/BarcodeScanning.Native.Maui/Platform/Android/Methods.cs b/BarcodeScanning.Native.Maui/Platform/Android/Methods.cs
index 3c30485..3e49814 100644
--- a/BarcodeScanning.Native.Maui/Platform/Android/Methods.cs
+++ b/BarcodeScanning.Native.Maui/Platform/Android/Methods.cs
@@ -3,8 +3,7 @@
using Android.Runtime;
using Java.Net;
using Java.Util;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.Arm;
+using System.Runtime.InteropServices;
using Xamarin.Google.MLKit.Vision.Barcode.Common;
using Xamarin.Google.MLKit.Vision.BarCode;
using Xamarin.Google.MLKit.Vision.Common;
@@ -17,11 +16,12 @@ namespace BarcodeScanning;
public static partial class Methods
{
+ private static readonly bool neonSupported = IsNeonSupported();
private static readonly ParallelOptions parallelOptions = new()
{
MaxDegreeOfParallelism = Environment.ProcessorCount * 2
};
-
+
public static async Task> ScanFromImageAsync(byte[] imageArray)
=> await ProcessBitmapAsync(await BitmapFactory.DecodeByteArrayAsync(imageArray, 0, imageArray.Length));
public static async Task> ScanFromImageAsync(FileResult file)
@@ -85,34 +85,32 @@ private static void ProcessBarcodeResult(Java.Lang.Object? inputResults, HashSet
}
}
+ [LibraryImport("InvertBytes.so")]
+ private static partial int InvertBytes(IntPtr data, int length);
+
internal static void InvertLuminance(Image image)
{
var yBuffer = image.GetPlanes()?[0].Buffer;
if (yBuffer is null)
return;
-
+
if (yBuffer.IsDirect)
{
- unsafe
+ var data = yBuffer.GetDirectBufferAddress();
+ var length = yBuffer.Capacity();
+
+ int result;
+ if (neonSupported)
+ result = InvertBytes(data, length);
+ else
+ result = -1;
+
+ if (result != 0)
{
- if (AdvSimd.IsSupported)
+ unsafe
{
- var data = (byte*)yBuffer.GetDirectBufferAddress();
- var length = yBuffer.Capacity();
-
- for (int i = 0; i < length; i += Vector128.Count)
- {
- var vector = AdvSimd.LoadVector128(data + i);
- var inverted = AdvSimd.Not(vector);
- AdvSimd.Store(data + i, inverted);
- }
- }
- else
- {
- var data = (ulong*)yBuffer.GetDirectBufferAddress();
- var length = yBuffer.Capacity() >> 3;
-
- Parallel.For(0, length, parallelOptions, (i) => data[i] = ~data[i]);
+ var dataPtr = (ulong*)data;
+ Parallel.For(0, length >> 3, parallelOptions, (i) => dataPtr[i] = ~dataPtr[i]);
}
}
}
@@ -191,4 +189,17 @@ internal static Size TargetResolution(CaptureQuality? captureQuality)
_ => new Size(1280, 720)
};
}
+
+ private static bool IsNeonSupported()
+ {
+ try
+ {
+ var info = File.ReadAllText("/proc/cpuinfo");
+ return info.Contains("neon") || info.Contains("asimd");
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
}
\ No newline at end of file
diff --git a/BarcodeScanning.Native.Maui/Platform/Android/Native/InvertBytes.cpp b/BarcodeScanning.Native.Maui/Platform/Android/Native/InvertBytes.cpp
new file mode 100644
index 0000000..6a06dbb
--- /dev/null
+++ b/BarcodeScanning.Native.Maui/Platform/Android/Native/InvertBytes.cpp
@@ -0,0 +1,33 @@
+#include
+#include
+
+extern "C" int InvertBytes(uint8_t* data, int length) {
+ if (!data || length <= 0) {
+ return -1;
+ }
+
+ const int vectorSize = 64;
+ int i;
+
+ try {
+ for (i = 0; i <= length - vectorSize; i += vectorSize) {
+ uint8x16x4_t vec = vld1q_u8_x4(data + i);
+
+ vec.val[0] = vmvnq_u8(vec.val[0]);
+ vec.val[1] = vmvnq_u8(vec.val[1]);
+ vec.val[2] = vmvnq_u8(vec.val[2]);
+ vec.val[3] = vmvnq_u8(vec.val[3]);
+
+ vst1q_u8_x4(data + i, vec);
+ }
+
+ for (; i < length; i++) {
+ data[i] = ~data[i];
+ }
+ }
+ catch (...) {
+ return -1;
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/BarcodeScanning.Native.Maui/Platform/Android/Native/arm64-v8a/InvertBytes.so b/BarcodeScanning.Native.Maui/Platform/Android/Native/arm64-v8a/InvertBytes.so
new file mode 100755
index 0000000..ef9a75c
Binary files /dev/null and b/BarcodeScanning.Native.Maui/Platform/Android/Native/arm64-v8a/InvertBytes.so differ
diff --git a/BarcodeScanning.Native.Maui/Platform/Android/Native/armeabi-v7a/InvertBytes.so b/BarcodeScanning.Native.Maui/Platform/Android/Native/armeabi-v7a/InvertBytes.so
new file mode 100755
index 0000000..056dccf
Binary files /dev/null and b/BarcodeScanning.Native.Maui/Platform/Android/Native/armeabi-v7a/InvertBytes.so differ
diff --git a/BarcodeScanning.Native.Maui/Platform/MaciOS/Extensions.cs b/BarcodeScanning.Native.Maui/Platform/MaciOS/Extensions.cs
index 44f7c93..372b3e2 100644
--- a/BarcodeScanning.Native.Maui/Platform/MaciOS/Extensions.cs
+++ b/BarcodeScanning.Native.Maui/Platform/MaciOS/Extensions.cs
@@ -16,7 +16,7 @@ public static BarcodeResult AsBarcodeResult(this VNBarcodeObservation barcode, A
BarcodeFormat = Methods.ConvertFromIOSFormats(barcode.Symbology),
DisplayValue = barcode.PayloadStringValue ?? string.Empty,
RawValue = barcode.PayloadStringValue ?? string.Empty,
- RawBytes = OperatingSystem.IsIOSVersionAtLeast(17) ? [.. barcode.PayloadData ?? []] : Encoding.ASCII.GetBytes(barcode.PayloadStringValue ?? string.Empty),
+ RawBytes = OperatingSystem.IsIOSVersionAtLeast(17) ? barcode.PayloadData?.ToArray() ?? [] : Encoding.ASCII.GetBytes(barcode.PayloadStringValue ?? string.Empty),
PreviewBoundingBox = previewLayer?.MapToLayerCoordinates(InvertY(barcode.BoundingBox)).AsRectangleF() ?? RectF.Zero,
ImageBoundingBox = barcode.BoundingBox.AsRectangleF()
};
diff --git a/README.md b/README.md
index f1a9e0a..0506933 100644
--- a/README.md
+++ b/README.md
@@ -75,9 +75,9 @@ This library was inspired by existing MAUI barcode scanning libraries: [BarcodeS
```csharp
public ICommand DetectionFinishedCommand { get; set; }
...
- DetectionFinishedCommand = new Command(BarcodeResult[] result) =>
+ DetectionFinishedCommand = new Command(IReadOnlySet result) =>
{
- if (result.Length > 0)
+ if (result.Count > 0)
...
}
```