Implement Gen2
MODIFY
WalletWasabi.Fluent.Desktop/packages.lock.json
WalletWasabi.Fluent.Desktop/packages.lock.json
"Avalonia": "0.10.999-cibuild0014678-beta",
"Avalonia.Diagnostics": "0.10.999-cibuild0014678-beta",
"Avalonia.ReactiveUI": "0.10.999-cibuild0014678-beta",
+ "Avalonia.Xaml.Behaviors": "0.10.6.7",
"OpenCvSharp4": "4.5.2.20210404",
"OpenCvSharp4.runtime.win": "4.5.2.20210404",
- "Avalonia.Xaml.Behaviors": "0.10.6.7",
"WalletWasabi": "1.0.0",
"Wasabi Wallet": "1.0.0"
}

MODIFY
WalletWasabi.Fluent/Models/WebcamQrReader.cs
WalletWasabi.Fluent/Models/WebcamQrReader.cs
@@ -47,12 +47,15 @@ namespace WalletWasabi.Fluent.Models
}
ScanningTask = Task.Run(() =>
{
- VideoCapture? camera = null;
+ using VideoCapture? camera = new();
try
{
- camera = OpenCamera();
+ if (!camera.Open(DefaultCameraId))
+ {
+ throw new InvalidOperationException("Could not open webcam.");
+ }
RequestEnd = false;
- Scan(camera);
+ KeepScan(camera);
}
catch (Exception exc)
{
@@ -62,7 +65,6 @@ namespace WalletWasabi.Fluent.Models
finally
{
camera?.Release();
- camera?.Dispose();
}
});
}
@@ -82,26 +84,28 @@ namespace WalletWasabi.Fluent.Models
}
}
- private void Scan(VideoCapture camera)
+ private void KeepScan(VideoCapture camera)
{
- WriteableBitmap? lastBitmap = null;
- WriteableBitmap? currentBitmap = null;
+ PixelSize pixelSize = new(camera.FrameWidth, camera.FrameHeight);
+ Vector dpi = new(96, 96);
+ using WriteableBitmap writeableBitmap = new(pixelSize, dpi, PixelFormat.Rgba8888, AlphaFormat.Unpremul);
+
+ int dataSize = camera.FrameWidth * camera.FrameHeight;
+ int[] helperArray = new int[dataSize];
using QRCodeDetector qRCodeDetector = new();
+ using Mat frame = new();
while (!RequestEnd)
{
try
{
- using Mat frame = new();
bool gotBackFrame = camera.Read(frame);
if (!gotBackFrame || frame.Width == 0 || frame.Height == 0)
{
continue;
}
- currentBitmap = ConvertMatToWriteableBitmap(frame);
+ ConvertMatToWriteableBitmap(frame, writeableBitmap, helperArray);
- NewImageArrived?.Invoke(this, currentBitmap);
- lastBitmap?.Dispose();
- lastBitmap = currentBitmap;
+ NewImageArrived?.Invoke(this, writeableBitmap);
if (qRCodeDetector.Detect(frame, out Point2f[] points))
{
@@ -125,48 +129,29 @@ namespace WalletWasabi.Fluent.Models
catch (OpenCVException exc)
{
Logger.LogWarning(exc);
- currentBitmap?.Dispose();
}
}
- lastBitmap?.Dispose();
- currentBitmap?.Dispose();
}
- private VideoCapture OpenCamera()
+ private void ConvertMatToWriteableBitmap(Mat frame, WriteableBitmap writeableBitmap, int[] helperArray)
{
- VideoCapture camera = new();
- if (!camera.Open(DefaultCameraId))
- {
- throw new InvalidOperationException("Could not open webcam.");
- }
- return camera;
- }
-
- private WriteableBitmap ConvertMatToWriteableBitmap(Mat frame)
- {
- PixelSize pixelSize = new(frame.Width, frame.Height);
- Vector dpi = new(96, 96);
- var writeableBitmap = new WriteableBitmap(pixelSize, dpi, PixelFormat.Rgba8888, AlphaFormat.Unpremul);
+ using ILockedFramebuffer fb = writeableBitmap.Lock();
+ Mat.Indexer<Vec3b> indexer = frame.GetGenericIndexer<Vec3b>();
- using (var fb = writeableBitmap.Lock())
- {
- var indexer = frame.GetGenericIndexer<Vec3b>();
- int[] data = new int[fb.Size.Width * fb.Size.Height];
for (int y = 0; y < frame.Height; y++)
{
+ int rowIndex = y * fb.Size.Width;
+
for (int x = 0; x < frame.Width; x++)
{
- Vec3b pixel = indexer[y, x];
- byte r = pixel.Item0;
- byte g = pixel.Item1;
- byte b = pixel.Item2;
- var color = new Color(255, r, g, b);
- data[y * fb.Size.Width + x] = (int)color.ToUint32();
- }
+ (byte r, byte g, byte b) = indexer[y, x];
+ Color color = new(255, r, g, b);
+
+ helperArray[rowIndex + x] = (int)color.ToUint32();
}
- Marshal.Copy(data, 0, fb.Address, fb.Size.Width * fb.Size.Height);
}
- return writeableBitmap;
+
+ Marshal.Copy(helperArray, 0, fb.Address, helperArray.Length);
}
}
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendViewModel.cs
@@ -28,6 +28,7 @@ using WalletWasabi.Wallets;
using WalletWasabi.WebClients.PayJoin;
using Constants = WalletWasabi.Helpers.Constants;
using WalletWasabi.Fluent.Helpers;
+using WalletWasabi.Fluent.Views.Wallets.Send;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
@@ -77,7 +78,15 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
IsCameraLoadingAnimationVisible = false;
}
+
+ if (QrImage == null)
+ {
QrImage = args.EventArgs;
+ }
+ else
+ {
+ SendView.QrImage?.InvalidateVisual();
+ }
});
Observable.FromEventPattern<string>(_qrReader, nameof(_qrReader.CorrectAddressFound))

MODIFY
WalletWasabi.Fluent/Views/Wallets/Send/SendView.axaml.cs
WalletWasabi.Fluent/Views/Wallets/Send/SendView.axaml.cs
@@ -5,9 +5,13 @@ namespace WalletWasabi.Fluent.Views.Wallets.Send
{
public class SendView : UserControl
{
+ // NASTY HACK! DO NOT USE IN PRODUCTION. kiminuo
+ public static volatile Image? QrImage;
+
public SendView()
{
InitializeComponent();
+ QrImage = this.FindControl<Image>("qrImage");
}
private void InitializeComponent()

Implement Gen2