Skip to content

Commit

Permalink
2.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
afriscic committed Nov 23, 2024
1 parent cf544f2 commit 00872bc
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsAotCompatible>true</IsAotCompatible>
<Nullable>enable</Nullable>
<Version>2.0.1</Version>
<Version>2.1.0</Version>
<Authors>Alen Friščić</Authors>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
Expand Down Expand Up @@ -51,12 +51,15 @@

<ItemGroup Condition="'$(TargetFramework)' == 'net9.0-android'">
<PackageReference Include="Xamarin.Google.MLKit.BarcodeScanning" Version="117.3.0.1" />
<PackageReference Include="Xamarin.AndroidX.Camera.View" Version="1.4.0.1" />
<PackageReference Include="Xamarin.AndroidX.Camera.Camera2" Version="1.4.0.1" />
<PackageReference Include="Xamarin.AndroidX.Camera.View" Version="1.4.0.2" />
<PackageReference Include="Xamarin.AndroidX.Camera.Camera2" Version="1.4.0.2" />

<PackageReference Include="Xamarin.AndroidX.Activity.Ktx" Version="1.9.3.1" />
<PackageReference Include="Xamarin.AndroidX.Collection.Ktx" Version="1.4.5.1" />
<PackageReference Include="Xamarin.AndroidX.Fragment.Ktx" Version="1.8.5.1" />

<AndroidNativeLibrary Include="**\Android\Native\arm64-v8a\InvertBytes.so" />
<AndroidNativeLibrary Include="**\Android\Native\armeabi-v7a\InvertBytes.so" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('net9.0-windows'))">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
55 changes: 33 additions & 22 deletions BarcodeScanning.Native.Maui/Platform/Android/Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<IReadOnlySet<BarcodeResult>> ScanFromImageAsync(byte[] imageArray)
=> await ProcessBitmapAsync(await BitmapFactory.DecodeByteArrayAsync(imageArray, 0, imageArray.Length));
public static async Task<IReadOnlySet<BarcodeResult>> ScanFromImageAsync(FileResult file)
Expand Down Expand Up @@ -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<byte>.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]);
}
}
}
Expand Down Expand Up @@ -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;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <arm_neon.h>
#include <stdint.h>

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;
}
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion BarcodeScanning.Native.Maui/Platform/MaciOS/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
};
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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[]>(BarcodeResult[] result) =>
DetectionFinishedCommand = new Command<BarcodeResult[]>(IReadOnlySet<BarcodeResult> result) =>
{
if (result.Length > 0)
if (result.Count > 0)
...
}
```
Expand Down

0 comments on commit 00872bc

Please sign in to comment.