Skip to content

Commit

Permalink
use zxingcpp
Browse files Browse the repository at this point in the history
  • Loading branch information
jamie-mh committed Nov 11, 2024
1 parent 31a6089 commit 7016155
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 76 deletions.
6 changes: 3 additions & 3 deletions Stratum.Droid/Assets/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ <h3>Konscious.Security.Cryptography</h3>
<p>MIT License</p>
<a href="https://github.com/kmaragon/Konscious.Security.Cryptography">https://github.com/kmaragon/Konscious.Security.Cryptography</a>

<h3>ZXing.Net</h3>
<p>Copyright &copy; Michael Jahn, ZXing authors</p>
<h3>ZXing-C++</h3>
<p>Copyright &copy; Axel Waggershauser, ZXing authors</p>
<p>Apache-2.0 License</p>
<a href="https://github.com/micjahn/ZXing.Net">https://github.com/micjahn/ZXing.Net</a>
<a href="https://github.com/zxing-cpp/zxing-cpp">https://github.com/zxing-cpp/zxing-cpp</a>

%LICENSE
</body>
Expand Down
3 changes: 2 additions & 1 deletion Stratum.Droid/Stratum.Droid.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<LangVersion>12</LangVersion>
<AndroidVersionCodePattern>{versionCode}</AndroidVersionCodePattern>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<AndroidUseSharedRuntime>true</AndroidUseSharedRuntime>
Expand Down Expand Up @@ -51,7 +52,7 @@
<PackageReference Include="Xamarin.AndroidX.ViewPager2" Version="1.1.0.1" />
<PackageReference Include="Xamarin.AndroidX.Work.Runtime" Version="2.9.0.5" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.10.0.6" />
<PackageReference Include="ZXing.Net" Version="0.16.9" />
<PackageReference Include="StratumAuth.ZXing" Version="1.0.0" />
</ItemGroup>
<ItemGroup Condition="!$(DefineConstants.Contains(FDROID))">
<PackageReference Include="Xamarin.GooglePlayServices.Wearable" Version="118.2.0" />
Expand Down
2 changes: 1 addition & 1 deletion Stratum.Droid/src/Activity/ScanActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected override async void OnCreate(Bundle savedInstanceState)

var analysis = new ImageAnalysis.Builder()
.SetBackpressureStrategy(ImageAnalysis.StrategyKeepOnlyLatest)
.SetOutputImageFormat(ImageAnalysis.OutputImageFormatYuv420888)
.SetOutputImageFormat(ImageAnalysis.OutputImageFormatRgba8888)
.Build();

var analyser = new QrCodeImageAnalyser();
Expand Down
67 changes: 37 additions & 30 deletions Stratum.Droid/src/QrCode/QrCodeImageAnalyser.cs
Original file line number Diff line number Diff line change
@@ -1,43 +1,38 @@
// Copyright (C) 2023 jmh
// Copyright (C) 2024 jmh
// SPDX-License-Identifier: GPL-3.0-only

using System;
using System.Collections.Generic;
using Android.Graphics;
using Android.Util;
using AndroidX.Camera.Core;
using ZXing;
using ZXing.Common;
using Stratum.ZXing;
using Serilog;
using ImageFormat = Stratum.ZXing.ImageFormat;
using Log = Serilog.Log;

namespace Stratum.Droid.QrCode
{
public class QrCodeImageAnalyser : Java.Lang.Object, ImageAnalysis.IAnalyzer
{
public event EventHandler<string> QrCodeScanned;
public Size DefaultTargetResolution => new(640, 480);
public Size DefaultTargetResolution => new(1920, 1080);

private readonly BarcodeReader<Bitmap> _barcodeReader;
public QrCodeImageAnalyser()
private readonly ILogger _log = Log.ForContext<QrCodeImageAnalyser>();

private readonly QrCodeReader _qrCodeReader = new(new ReaderOptions
{
_barcodeReader = new BarcodeReader<Bitmap>(null, null, ls => new HybridBinarizer(ls))
{
AutoRotate = true,
Options = new DecodingOptions
{
PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE },
TryInverted = true
}
};
}
TryRotate = true,
TryHarder = true,
TryInvert = true,
Binarizer = Binarizer.LocalAverage
});

public void Analyze(IImageProxy imageProxy)
{
if (imageProxy.Image == null)
{
return;
}

try
{
AnalyseInternal(imageProxy);
Expand All @@ -47,23 +42,35 @@ public void Analyze(IImageProxy imageProxy)
imageProxy.Close();
}
}

private void AnalyseInternal(IImageProxy imageProxy)
{
using var plane = imageProxy.Image.GetPlanes()[0];

var bytes = new byte[plane.Buffer.Capacity()];
plane.Buffer.Get(bytes);
using var rgbaPlane = imageProxy.Image.GetPlanes()[0];
ReadOnlySpan<byte> bytes;

var source = new PlanarYUVLuminanceSource(
bytes, imageProxy.Width, imageProxy.Height, 0, 0, imageProxy.Width, imageProxy.Height, false);
unsafe
{
var bufferAddress = rgbaPlane.Buffer.GetDirectBufferAddress().ToPointer();
bytes = new ReadOnlySpan<byte>(bufferAddress, rgbaPlane.Buffer.Capacity());
}

var result = _barcodeReader.Decode(source);
using var imageView = new ImageView(bytes, imageProxy.Width, imageProxy.Height, ImageFormat.RGBA);
string result;

try
{
result = _qrCodeReader.Read(imageView);
}
catch (QrCodeException e)
{
_log.Warning(e, "Error scanning QR code: {Type}", e.Type);
return;
}

if (result != null)
{
QrCodeScanned?.Invoke(this, result.Text);
QrCodeScanned?.Invoke(this, result);
}
}
}
}
}
40 changes: 17 additions & 23 deletions Stratum.Droid/src/QrCode/QrCodeImageReader.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
// Copyright (C) 2023 jmh
// Copyright (C) 2024 jmh
// SPDX-License-Identifier: GPL-3.0-only

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Android.Content;
using Android.Graphics;
using Java.Nio;
using Stratum.Droid.Util;
using ZXing;
using ZXing.Common;
using Stratum.ZXing;
using Java.Nio;
using ImageFormat = Stratum.ZXing.ImageFormat;
using Uri = Android.Net.Uri;

namespace Stratum.Droid.QrCode
Expand All @@ -20,7 +19,7 @@ public static class QrCodeImageReader
public static async Task<string> ScanImageFromFileAsync(Context context, Uri uri)
{
Bitmap bitmap;

try
{
var data = await FileUtil.ReadFileAsync(context, uri);
Expand All @@ -30,34 +29,29 @@ public static async Task<string> ScanImageFromFileAsync(Context context, Uri uri
{
throw new IOException("Failed to read file", e);
}

if (bitmap == null)
{
throw new IOException("Failed to decode bitmap");
}

var reader = new BarcodeReader<Bitmap>(null, null, ls => new HybridBinarizer(ls))
var reader = new QrCodeReader(new ReaderOptions
{
AutoRotate = true,
Options = new DecodingOptions
{
PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE },
TryHarder = true,
TryInverted = true
}
};
Binarizer = Binarizer.LocalAverage,
TryRotate = true,
TryHarder = true,
TryInvert = true
});

using var buffer = ByteBuffer.Allocate(bitmap.ByteCount);
await bitmap.CopyPixelsToBufferAsync(buffer);
buffer.Rewind();

var bytes = new byte[buffer.Remaining()];
buffer.Get(bytes);

var source = new RGBLuminanceSource(bytes, bitmap.Width, bitmap.Height, RGBLuminanceSource.BitmapFormat.RGBA32);
var result = await Task.Run(() => reader.Decode(source));

return result?.Text;

using var imageView = new ImageView(bytes, bitmap.Width, bitmap.Height, ImageFormat.RGBA);
return await Task.Run(() => reader.Read(imageView));
}
}
}
}
6 changes: 3 additions & 3 deletions Stratum.Test/Stratum.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
<PackageReference Include="SkiaSharp" Version="2.88.8" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.88.8" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="ZXing.Net" Version="0.16.9" />
<PackageReference Include="ZXing.Net.Bindings.ImageSharp.V2" Version="0.16.16" />
<PackageReference Include="StratumAuth.ZXing" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Stratum.Core\Stratum.Core.csproj" />
Expand Down
22 changes: 7 additions & 15 deletions Stratum.Test/src/Service/BackupServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
using Stratum.Core.Persistence;
using Stratum.Core.Service;
using Stratum.Core.Service.Impl;
using Stratum.ZXing;
using HtmlAgilityPack;
using Moq;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SkiaSharp;
using Xunit;
using ZXing;
using ZXing.Common;

namespace Stratum.Test.Service
{
Expand Down Expand Up @@ -105,13 +103,7 @@ public async Task CreateHtmlBackupAsync()
var rows = document.DocumentNode.SelectNodes("//tr");
Assert.Equal(2, rows.Count);

var barcodeReader = new ZXing.ImageSharp.BarcodeReader<Rgba32>
{
Options = new DecodingOptions
{
PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE }
}
};
var qrCodeReader = new QrCodeReader();

void AssertRowMatches(HtmlNode node, Authenticator auth)
{
Expand All @@ -123,10 +115,10 @@ void AssertRowMatches(HtmlNode node, Authenticator auth)
var img = tds[3].SelectSingleNode("img");
var src = img.Attributes["src"].Value;
var data = Convert.FromBase64String(src["data:image/png;base64,".Length..]);

using var decodedImage = Image.Load<Rgba32>(data);
var qrCodeResult = barcodeReader.Decode(decodedImage);
Assert.Equal(auth.GetUri(), qrCodeResult.Text);
using var image = SKBitmap.Decode(data);
using var imageView = new ImageView(image.GetPixelSpan(), image.Width, image.Height, ImageFormat.Lum);
Assert.Equal(auth.GetUri(), qrCodeReader.Read(imageView));
}

AssertRowMatches(rows[0], authA);
Expand Down

0 comments on commit 7016155

Please sign in to comment.