From cfb1311eb32a5ac40e8e9154a580fc61f5a496ff Mon Sep 17 00:00:00 2001
From: Glenn <33450392+glenn2223@users.noreply.github.com>
Date: Tue, 13 Dec 2022 11:49:27 +0000
Subject: [PATCH 1/3] Implement `Decode(Stream)`
Implemented stream decoding
Not happy with: (WIP - for now)
- Windows: having to use `Skia`
- Android: seems slow but it's no the stream conversion
---
ZXing.Net.MAUI/IBarcodeReader.cs | 8 +--
ZXing.Net.MAUI/PixelBufferHolder.cs | 103 ++++++++++++++++++++++++++-
ZXing.Net.MAUI/ZXing.Net.MAUI.csproj | 3 +
ZXing.Net.MAUI/ZXingBarcodeReader.cs | 41 +++++++----
4 files changed, 137 insertions(+), 18 deletions(-)
diff --git a/ZXing.Net.MAUI/IBarcodeReader.cs b/ZXing.Net.MAUI/IBarcodeReader.cs
index 24649a1..ddce73c 100644
--- a/ZXing.Net.MAUI/IBarcodeReader.cs
+++ b/ZXing.Net.MAUI/IBarcodeReader.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.IO;
namespace ZXing.Net.Maui.Readers
{
@@ -11,5 +7,7 @@ public interface IBarcodeReader
BarcodeReaderOptions Options { get; set; }
BarcodeResult[] Decode(PixelBufferHolder image);
+
+ BarcodeResult[] Decode(Stream stream);
}
}
diff --git a/ZXing.Net.MAUI/PixelBufferHolder.cs b/ZXing.Net.MAUI/PixelBufferHolder.cs
index bcebd8a..3e37c41 100644
--- a/ZXing.Net.MAUI/PixelBufferHolder.cs
+++ b/ZXing.Net.MAUI/PixelBufferHolder.cs
@@ -1,4 +1,11 @@
using Microsoft.Maui.Graphics;
+using System.IO;
+using System;
+#if WINDOWS || ANDROID
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+#endif
namespace ZXing.Net.Maui.Readers
{
@@ -17,5 +24,99 @@ public record PixelBufferHolder
#endif
Data { get; init; }
+
+ internal byte[] ByteData { get; set; }
+
+ public PixelBufferHolder() { }
+
+ ///
+ /// Create the necessary from a stream
+ ///
+ /// The stream to pick pixel data from
+ ///
+ ///
+ public static PixelBufferHolder FromStream(Stream stream)
+ {
+#if WINDOWS
+
+ var image = new Microsoft.Maui.Graphics.Skia.SkiaImageLoadingService().FromStream(stream) as Microsoft.Maui.Graphics.Skia.SkiaImage;
+
+ var dataList = new List { };
+
+ var mySpan = CollectionsMarshal.AsSpan(image!.PlatformRepresentation.Pixels.ToList());
+ for (var i = 0; i < mySpan.Length; i++)
+ {
+ dataList.Add(mySpan[i].Red);
+ dataList.Add(mySpan[i].Green);
+ dataList.Add(mySpan[i].Blue);
+ }
+
+ var data = dataList.ToArray();
+
+#else
+
+ var image =
+ (Microsoft.Maui.Graphics.Platform.PlatformImage.FromStream(stream)
+ as Microsoft.Maui.Graphics.Platform.PlatformImage)!;
+
+#if IOS || MACCATALYST
+
+ var uiImage = image.PlatformRepresentation;
+
+ var pixelBuffer = uiImage.CIImage?.PixelBuffer;
+
+ if (pixelBuffer != null)
+ return new PixelBufferHolder
+ {
+ Size = new(image.Width, image.Height),
+ Data = pixelBuffer
+ };
+
+ var data = uiImage.CGImage?.DataProvider.CopyData()?.ToArray();
+
+ if (data == null)
+ throw new NullReferenceException("Could not convert stream to native bytes");
+
+#elif ANDROID
+
+ var pixelArr = new int[(int)(image.Width * image.Height)];
+
+ image!.PlatformRepresentation.GetPixels(pixelArr, 0, (int)image.Width, 0, 0, (int)image.Width, (int)image.Height);
+ image!.PlatformRepresentation.Recycle();
+
+ var dataList = new List { };
+
+ var mySpan = CollectionsMarshal.AsSpan(pixelArr.ToList());
+
+ for (var i = 0; i < mySpan.Length; i++)
+ {
+ var intValue = mySpan[i];
+
+ dataList.Add(
+ (byte)((
+ (intValue >> 24) +
+ (intValue >> 16) +
+ (intValue >> 8) +
+ (byte)intValue
+ ) / 4)
+ );
+ }
+
+ var data = dataList.ToArray();
+
+#else
+
+ throw new PlatformNotSupportedException();
+
+#endif
+
+#endif
+
+ return new PixelBufferHolder
+ {
+ Size = new(image.Width, image.Height),
+ ByteData = data
+ };
+ }
}
-}
+}
\ No newline at end of file
diff --git a/ZXing.Net.MAUI/ZXing.Net.MAUI.csproj b/ZXing.Net.MAUI/ZXing.Net.MAUI.csproj
index 98985af..a3586b0 100644
--- a/ZXing.Net.MAUI/ZXing.Net.MAUI.csproj
+++ b/ZXing.Net.MAUI/ZXing.Net.MAUI.csproj
@@ -36,6 +36,9 @@
+
+
+
diff --git a/ZXing.Net.MAUI/ZXingBarcodeReader.cs b/ZXing.Net.MAUI/ZXingBarcodeReader.cs
index f7c39da..42d0d9e 100644
--- a/ZXing.Net.MAUI/ZXingBarcodeReader.cs
+++ b/ZXing.Net.MAUI/ZXingBarcodeReader.cs
@@ -1,8 +1,8 @@
-using Microsoft.Maui.Graphics;
+using System.IO;
namespace ZXing.Net.Maui.Readers
{
- public class ZXingBarcodeReader : Readers.IBarcodeReader
+ public class ZXingBarcodeReader : IBarcodeReader
{
BarcodeReaderGeneric zxingReader;
@@ -28,16 +28,7 @@ public BarcodeReaderOptions Options
public BarcodeResult[] Decode(PixelBufferHolder image)
{
- var w = (int)image.Size.Width;
- var h = (int)image.Size.Height;
-
- LuminanceSource ls = default;
-
-#if ANDROID
- ls = new ByteBufferYUVLuminanceSource(image.Data, w, h, 0, 0, w, h);
-#elif MACCATALYST || IOS
- ls = new CVPixelBufferBGRA32LuminanceSource(image.Data, w, h);
-#endif
+ LuminanceSource ls = GetLuminanceSource(image);
if (Options.Multiple)
return zxingReader.DecodeMultiple(ls)?.ToBarcodeResults();
@@ -48,5 +39,31 @@ public BarcodeResult[] Decode(PixelBufferHolder image)
return null;
}
+
+ public BarcodeResult[] Decode(Stream stream)
+ => Decode(PixelBufferHolder.FromStream(stream));
+
+ static LuminanceSource GetLuminanceSource(PixelBufferHolder image)
+ {
+ var w = (int)image.Size.Width;
+ var h = (int)image.Size.Height;
+
+#if MACCATALYST || IOS
+ if (image.Data != null)
+ return new CVPixelBufferBGRA32LuminanceSource(image.Data, w, h);
+#elif ANDROID
+ if (image.Data != null)
+ return new ByteBufferYUVLuminanceSource(image.Data, w, h, 0, 0, w, h);
+#endif
+
+ return
+ new RGBLuminanceSource(
+ image.ByteData,
+ w, h
+#if ANDROID || MACCATALYST || IOS
+ , RGBLuminanceSource.BitmapFormat.Gray8
+#endif
+ );
+ }
}
}
From fc34dcf2411cbb21effec270c3a45b4617b1a865 Mon Sep 17 00:00:00 2001
From: Glenn <33450392+glenn2223@users.noreply.github.com>
Date: Tue, 13 Dec 2022 11:52:14 +0000
Subject: [PATCH 2/3] Extended example project
Extended the example project to use stream decoding on two new pages
---
BigIslandBarcode/App.xaml.cs | 2 +-
BigIslandBarcode/MainPage.xaml | 16 ++-
BigIslandBarcode/MainPage.xaml.cs | 14 ++-
BigIslandBarcode/PickImage.xaml | 56 +++++++++
BigIslandBarcode/PickImage.xaml.cs | 164 +++++++++++++++++++++++++++
BigIslandBarcode/TakeImage.xaml | 56 +++++++++
BigIslandBarcode/TakeImage.xaml.cs | 175 +++++++++++++++++++++++++++++
7 files changed, 479 insertions(+), 4 deletions(-)
create mode 100644 BigIslandBarcode/PickImage.xaml
create mode 100644 BigIslandBarcode/PickImage.xaml.cs
create mode 100644 BigIslandBarcode/TakeImage.xaml
create mode 100644 BigIslandBarcode/TakeImage.xaml.cs
diff --git a/BigIslandBarcode/App.xaml.cs b/BigIslandBarcode/App.xaml.cs
index d570a94..675cc5a 100644
--- a/BigIslandBarcode/App.xaml.cs
+++ b/BigIslandBarcode/App.xaml.cs
@@ -11,7 +11,7 @@ public App()
{
InitializeComponent();
- MainPage = new MainPage();
+ MainPage = new NavigationPage(new MainPage());
}
}
}
diff --git a/BigIslandBarcode/MainPage.xaml b/BigIslandBarcode/MainPage.xaml
index 42d5db3..f1118b9 100644
--- a/BigIslandBarcode/MainPage.xaml
+++ b/BigIslandBarcode/MainPage.xaml
@@ -15,7 +15,21 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BigIslandBarcode/PickImage.xaml.cs b/BigIslandBarcode/PickImage.xaml.cs
new file mode 100644
index 0000000..1f6f901
--- /dev/null
+++ b/BigIslandBarcode/PickImage.xaml.cs
@@ -0,0 +1,164 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Maui.ApplicationModel;
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Storage;
+using ZXing.Net.Maui;
+using ZXing.Net.Maui.Readers;
+
+namespace BigIslandBarcode;
+
+public partial class PickImagePage : ContentPage
+{
+ readonly IBarcodeReader _reader;
+ bool _working = false;
+
+ public PickImagePage()
+ {
+ InitializeComponent();
+
+ _reader =
+ new ZXingBarcodeReader
+ {
+ Options = new BarcodeReaderOptions
+ {
+ Formats = BarcodeFormats.All,
+ AutoRotate = true
+ }
+ };
+
+ NavigatedTo += PageNavigatedTo;
+ }
+
+ async void PageNavigatedTo(object? sender, NavigatedToEventArgs e)
+ => await CallFilePicker();
+
+ async void PickClicked(object sender, EventArgs e)
+ => await CallFilePicker();
+
+ async Task CallFilePicker()
+ {
+ if (!_working)
+ {
+ _working = true;
+
+ FileInfo.Text = "Awaiting file selection";
+ ParseResult.Text = "";
+ ImageOutput.Source = null;
+
+ try
+ {
+ var result =
+ await FilePicker.PickAsync(
+ new PickOptions
+ {
+ FileTypes = FilePickerFileType.Images,
+ PickerTitle = "Choose your barcode"
+ }
+ );
+
+ if (result == null)
+ {
+ FileInfo.Text = "No file selected";
+ _working = false;
+ }
+ else
+ {
+ ActivityContainer.IsVisible = true;
+ ActivityIndicator.IsRunning = true;
+ PickButton.IsEnabled = false;
+ barcodeGenerator.IsVisible = false;
+
+ var worker = new BackgroundWorker();
+ worker.DoWork += Worker_DoWork;
+ worker.RunWorkerCompleted += Worker_Completed;
+
+ worker.RunWorkerAsync(result);
+ }
+ }
+ catch (Exception ex)
+ {
+ FileInfo.Text = $"Something's wrong: {ex.Message}";
+ ParseResult.Text = $"Something's wrong: {ex.Message}";
+
+ _working = false;
+ }
+ }
+ else
+ {
+ await DisplayAlert("Task Already Running", "Please cancel the runnning task first", "Okay");
+ }
+ }
+
+ async void Worker_DoWork(object? sender, DoWorkEventArgs e)
+ {
+ var fileResult = e.Argument as FileResult;
+ BarcodeResult? result = null;
+
+ var sW = new Stopwatch();
+
+ if (fileResult != null)
+ {
+
+ await MainThread.InvokeOnMainThreadAsync(() => ActivityLabel.Text = "Loading file");
+
+ using var stream = await fileResult.OpenReadAsync();
+
+ await MainThread.InvokeOnMainThreadAsync(() =>
+ {
+ FileInfo.Text = $"Name: {fileResult.FileName} - Size: {(stream.Length / 1024d):#.##} KiB";
+ ActivityLabel.Text = "Decoding";
+ });
+
+ sW.Start();
+
+ var decodeResult = _reader.Decode(stream);
+
+ sW.Stop();
+
+ result = decodeResult?.FirstOrDefault();
+ }
+
+ await MainThread.InvokeOnMainThreadAsync(() =>
+ {
+ if (fileResult != null)
+ ImageOutput.Source = ImageSource.FromFile(fileResult.FullPath);
+
+ if (result != null)
+ {
+ ParseResult.Text = $"Found Barcode (in {sW.ElapsedMilliseconds}ms)\nValue: {result.Value}";
+
+ try
+ {
+ barcodeGenerator.Value = result.Value;
+ barcodeGenerator.Format = result.Format;
+ barcodeGenerator.IsVisible = true;
+ }
+ catch (Exception ex)
+ {
+ ParseResult.Text += "\r\nError displaying barcode: " + ex.Message;
+ }
+ }
+ else
+ {
+ ParseResult.Text = $"No Barcode Found (in {sW.ElapsedMilliseconds}ms)";
+ }
+
+ Worker_Completed(true, null!);
+ });
+ }
+
+ void Worker_Completed(object? sender, RunWorkerCompletedEventArgs e)
+ {
+ if (sender is bool finished && finished == true)
+ {
+ ActivityContainer.IsVisible = false;
+ ActivityIndicator.IsRunning = false;
+ PickButton.IsEnabled = true;
+ _working = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/BigIslandBarcode/TakeImage.xaml b/BigIslandBarcode/TakeImage.xaml
new file mode 100644
index 0000000..cb5c699
--- /dev/null
+++ b/BigIslandBarcode/TakeImage.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BigIslandBarcode/TakeImage.xaml.cs b/BigIslandBarcode/TakeImage.xaml.cs
new file mode 100644
index 0000000..2ff6354
--- /dev/null
+++ b/BigIslandBarcode/TakeImage.xaml.cs
@@ -0,0 +1,175 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Maui.ApplicationModel;
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Media;
+using Microsoft.Maui.Storage;
+using ZXing.Net.Maui;
+using ZXing.Net.Maui.Readers;
+
+namespace BigIslandBarcode;
+
+public partial class TakeImagePage : ContentPage
+{
+ readonly IBarcodeReader _reader;
+ bool _working = false;
+
+ public TakeImagePage()
+ {
+ InitializeComponent();
+
+ _reader =
+ new ZXingBarcodeReader
+ {
+ Options = new BarcodeReaderOptions
+ {
+ Formats = BarcodeFormats.All,
+ AutoRotate = true
+ }
+ };
+ }
+
+ async void CaptureClicked(object sender, EventArgs e)
+ => await CallFilePicker();
+
+ async Task CallFilePicker()
+ {
+ if (!_working)
+ {
+ _working = true;
+
+ FileInfo.Text = "Awaiting file selection";
+ ParseResult.Text = "";
+ ImageOutput.Source = null;
+
+ var mediaPicker = MediaPicker.Default;
+
+ if (!mediaPicker.IsCaptureSupported)
+ {
+ FileInfo.Text = $"No capture device is available";
+
+ _working = false;
+
+ return;
+ }
+
+ try
+ {
+ var result = await MediaPicker.Default.CapturePhotoAsync(new MediaPickerOptions
+ {
+ Title = "Take a photo of the barcode"
+ });
+
+ if (result == null)
+ {
+ FileInfo.Text = "No picture taken";
+ _working = false;
+ }
+ else
+ {
+ ActivityContainer.IsVisible = true;
+ ActivityIndicator.IsRunning = true;
+ CaptureButton.IsEnabled = false;
+ barcodeGenerator.IsVisible = false;
+
+ var worker = new BackgroundWorker();
+ worker.DoWork += Worker_DoWork;
+ worker.RunWorkerCompleted += Worker_Completed;
+
+ worker.RunWorkerAsync(result);
+ }
+ }
+ catch (Exception ex)
+ {
+ FileInfo.Text = $"Something's wrong: {ex.Message}";
+
+ _working = false;
+ }
+ }
+ else
+ {
+ await DisplayAlert("Task Already Running", "Please cancel the runnning task first", "Okay");
+ }
+ }
+
+ async void Worker_DoWork(object sender, DoWorkEventArgs e)
+ {
+ var fileResult = e.Argument as FileResult;
+ BarcodeResult result = null;
+ string error = null;
+
+ var sW = new Stopwatch();
+
+ if (fileResult != null)
+ {
+
+ await MainThread.InvokeOnMainThreadAsync(() => ActivityLabel.Text = "Loading file");
+
+ using var stream = await fileResult.OpenReadAsync();
+
+ await MainThread.InvokeOnMainThreadAsync(() =>
+ {
+ FileInfo.Text = $"Name: {fileResult.FileName} - Size: {(stream.Length / 1024d):#.##} KiB";
+ ActivityLabel.Text = "Decoding";
+ });
+
+ try
+ {
+ sW.Start();
+
+ var decodeResult = _reader.Decode(stream);
+
+ sW.Stop();
+
+ result = decodeResult?.FirstOrDefault();
+ }
+ catch (Exception ex)
+ {
+ error = $"Error: {ex.Message}";
+ }
+ }
+
+ await MainThread.InvokeOnMainThreadAsync(() =>
+ {
+ if (fileResult != null)
+ ImageOutput.Source = ImageSource.FromFile(fileResult.FullPath);
+
+ if (result != null)
+ {
+ ParseResult.Text = $"Found Barcode (in {sW.ElapsedMilliseconds}ms)\nValue: {result.Value}";
+
+ try
+ {
+ barcodeGenerator.IsVisible = true;
+ barcodeGenerator.Value = result.Value;
+ barcodeGenerator.Format = result.Format;
+ }
+ catch (Exception ex)
+ {
+ barcodeGenerator.IsVisible = false;
+ ParseResult.Text = ex.Message;
+ }
+ }
+ else
+ {
+ ParseResult.Text = error ?? $"No Barcode Found (in {sW.ElapsedMilliseconds}ms)";
+ }
+
+ Worker_Completed(true, null!);
+ });
+ }
+
+ void Worker_Completed(object sender, RunWorkerCompletedEventArgs e)
+ {
+ if (sender is bool finished && finished == true)
+ {
+ ActivityContainer.IsVisible = false;
+ ActivityIndicator.IsRunning = false;
+ CaptureButton.IsEnabled = true;
+ _working = false;
+ }
+ }
+}
\ No newline at end of file
From e2e416e8be87be3056a7371b540df5585dbd6558 Mon Sep 17 00:00:00 2001
From: Glenn <33450392+glenn2223@users.noreply.github.com>
Date: Wed, 4 Jan 2023 17:36:04 +0000
Subject: [PATCH 3/3] Improvements
- Improved speed slightly on android
- Dropped requirement for `Microsoft.Maui.Graphics.Skia`
- Let `RGBLuminanceSource` do the hard work of discovering the `BitmapFormat`
---
ZXing.Net.MAUI/PixelBufferHolder.cs | 61 +++++++++++++---------------
ZXing.Net.MAUI/ZXing.Net.MAUI.csproj | 3 --
ZXing.Net.MAUI/ZXingBarcodeReader.cs | 7 ++--
3 files changed, 32 insertions(+), 39 deletions(-)
diff --git a/ZXing.Net.MAUI/PixelBufferHolder.cs b/ZXing.Net.MAUI/PixelBufferHolder.cs
index 3e37c41..0f68b6d 100644
--- a/ZXing.Net.MAUI/PixelBufferHolder.cs
+++ b/ZXing.Net.MAUI/PixelBufferHolder.cs
@@ -1,8 +1,7 @@
using Microsoft.Maui.Graphics;
using System.IO;
using System;
-#if WINDOWS || ANDROID
-using System.Collections.Generic;
+#if ANDROID || WINDOWS
using System.Linq;
using System.Runtime.InteropServices;
#endif
@@ -39,19 +38,18 @@ public static PixelBufferHolder FromStream(Stream stream)
{
#if WINDOWS
- var image = new Microsoft.Maui.Graphics.Skia.SkiaImageLoadingService().FromStream(stream) as Microsoft.Maui.Graphics.Skia.SkiaImage;
+ var decoder = Run(Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(stream.AsRandomAccessStream()));
- var dataList = new List { };
-
- var mySpan = CollectionsMarshal.AsSpan(image!.PlatformRepresentation.Pixels.ToList());
- for (var i = 0; i < mySpan.Length; i++)
- {
- dataList.Add(mySpan[i].Red);
- dataList.Add(mySpan[i].Green);
- dataList.Add(mySpan[i].Blue);
- }
+ var image =
+ new
+ {
+ Width = decoder.PixelWidth,
+ Height = decoder.PixelHeight
+ };
- var data = dataList.ToArray();
+ var pixelData = Run(decoder.GetPixelDataAsync());
+
+ var data = pixelData.DetachPixelData();
#else
@@ -84,25 +82,9 @@ public static PixelBufferHolder FromStream(Stream stream)
image!.PlatformRepresentation.GetPixels(pixelArr, 0, (int)image.Width, 0, 0, (int)image.Width, (int)image.Height);
image!.PlatformRepresentation.Recycle();
- var dataList = new List { };
-
- var mySpan = CollectionsMarshal.AsSpan(pixelArr.ToList());
-
- for (var i = 0; i < mySpan.Length; i++)
- {
- var intValue = mySpan[i];
-
- dataList.Add(
- (byte)((
- (intValue >> 24) +
- (intValue >> 16) +
- (intValue >> 8) +
- (byte)intValue
- ) / 4)
- );
- }
-
- var data = dataList.ToArray();
+ var data =
+ MemoryMarshal.Cast(CollectionsMarshal.AsSpan(pixelArr.ToList()))
+ .ToArray();
#else
@@ -118,5 +100,20 @@ public static PixelBufferHolder FromStream(Stream stream)
ByteData = data
};
}
+
+#if WINDOWS
+ static T Run(Windows.Foundation.IAsyncOperation operation)
+ {
+
+ var task = System.Threading.Tasks.Task.Run(async () => await operation);
+
+ task.Wait();
+
+ if (task.Exception != null)
+ throw task.Exception;
+
+ return task.Result;
+ }
+#endif
}
}
\ No newline at end of file
diff --git a/ZXing.Net.MAUI/ZXing.Net.MAUI.csproj b/ZXing.Net.MAUI/ZXing.Net.MAUI.csproj
index a3586b0..98985af 100644
--- a/ZXing.Net.MAUI/ZXing.Net.MAUI.csproj
+++ b/ZXing.Net.MAUI/ZXing.Net.MAUI.csproj
@@ -36,9 +36,6 @@
-
-
-
diff --git a/ZXing.Net.MAUI/ZXingBarcodeReader.cs b/ZXing.Net.MAUI/ZXingBarcodeReader.cs
index 42d0d9e..c29a672 100644
--- a/ZXing.Net.MAUI/ZXingBarcodeReader.cs
+++ b/ZXing.Net.MAUI/ZXingBarcodeReader.cs
@@ -59,10 +59,9 @@ static LuminanceSource GetLuminanceSource(PixelBufferHolder image)
return
new RGBLuminanceSource(
image.ByteData,
- w, h
-#if ANDROID || MACCATALYST || IOS
- , RGBLuminanceSource.BitmapFormat.Gray8
-#endif
+ w,
+ h,
+ RGBLuminanceSource.BitmapFormat.Unknown
);
}
}