Skip to content

Commit

Permalink
Merge pull request #5 from baltermia/upgrade-to-imagesharp-v2
Browse files Browse the repository at this point in the history
Upgrade to ImageSharp Verison 2
  • Loading branch information
baltermia authored Jun 24, 2022
2 parents 6c14dfd + eca58b2 commit e518ec4
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="coverlet.collector" Version="3.0.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public class ImageSharpBarcodeReader_Tests
private const string CodeText = "ImageSharpBarcodeReader";
private readonly string FolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "codes");

private BarcodeReader reader1D;
private BarcodeReader readerQR;
private BarcodeReader<Rgba32> reader1D;
private BarcodeReader<Rgba32> readerQR;

private Image<Rgba32> barcodeImage;
private Image<Rgba32> qrcodeImage;
Expand All @@ -38,8 +38,8 @@ public void Setup()
barcodeBytes = Convert.FromBase64String(barcodeBase64.Split(',')[1]);
qrcodeBytes = Convert.FromBase64String(qrcodeBase64.Split(',')[1]);

reader1D = new BarcodeReader();
readerQR = new BarcodeReader(types: ZXing.BarcodeFormat.QR_CODE);
reader1D = new BarcodeReader<Rgba32>();
readerQR = new BarcodeReader<Rgba32>(types: ZXing.BarcodeFormat.QR_CODE);
}

[Test]
Expand Down Expand Up @@ -128,11 +128,11 @@ public async Task DecodeWithEventAsync()
}
}

private static void Test(Func<BarcodeResult> func)
private static void Test(Func<BarcodeResult<Rgba32>> func)
{
try
{
BarcodeResult result = func.Invoke();
BarcodeResult<Rgba32> result = func.Invoke();

switch (result.Status)
{
Expand Down
8 changes: 4 additions & 4 deletions BarcodeReader.ImageSharp.sln
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31729.503
# Visual Studio Version 17
VisualStudioVersion = 17.2.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BarcodeReader.ImageSharp", "BarcodeReader.ImageSharp\BarcodeReader.ImageSharp.csproj", "{693BAFD9-50D3-4E25-A321-0BD2051C5E8A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BarcodeReader.ImageSharp", "BarcodeReader.ImageSharp\BarcodeReader.ImageSharp.csproj", "{693BAFD9-50D3-4E25-A321-0BD2051C5E8A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BarcodeReader.ImageSharp.UnitTests", "BarcodeReader.ImageSharp.UnitTests\BarcodeReader.ImageSharp.UnitTests.csproj", "{BB5116E1-AD9B-4A9E-A934-096C91F9BCC6}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BarcodeReader.ImageSharp.UnitTests", "BarcodeReader.ImageSharp.UnitTests\BarcodeReader.ImageSharp.UnitTests.csproj", "{BB5116E1-AD9B-4A9E-A934-096C91F9BCC6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
15 changes: 4 additions & 11 deletions BarcodeReader.ImageSharp/BarcodeEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
using System;
using SixLabors.ImageSharp.PixelFormats;
using System;

namespace BarcodeReader.ImageSharp
{
/// <summary>
/// EventArgs for BarcodeDetectedEvents but also other events using Barcodes
/// </summary>
public class BarcodeEventArgs : EventArgs
public class BarcodeEventArgs<T> : EventArgs where T : unmanaged, IPixel<T>
{
/// <summary>
/// Decoded value from the barcode as a string
/// </summary>
public BarcodeResult Result { get; }

/// <summary>
/// Creates a new instance of the BarcodeEventArgs class
/// </summary>
public BarcodeEventArgs(BarcodeResult result)
{
Result = result;
}
public BarcodeResult<T> Result { get; set; }
}
}
8 changes: 4 additions & 4 deletions BarcodeReader.ImageSharp/BarcodeReader.ImageSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ZXing.Net.Bindings.ImageSharp" Version="0.16.9-beta" />
</ItemGroup>

<ItemGroup>
<None Include="..\LICENSE.md" Pack="true" PackagePath="" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="ZXing.Net.Bindings.ImageSharp.V2" Version="0.16.14" />
</ItemGroup>

</Project>
56 changes: 35 additions & 21 deletions BarcodeReader.ImageSharp/BarcodeReader.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
using System;
using SixLabors;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp;
using ZXing.Common;
using ZXing;
using System;
using System.Threading.Tasks;
using ZXing;
using ZXing.Common;

namespace BarcodeReader.ImageSharp
{
public class BarcodeReader
public class BarcodeReader<T> where T : unmanaged, IPixel<T>
{
/// <summary>
/// Represents the method that will handle the event raised when a barcode is detected
/// </summary>
/// <param name="sender">The object which raises the event</param>
/// <param name="e">Arguments such as the barcode value and bitmap are given through the EventArgs</param>
public delegate void BarcodeDetectedEventHandler(object sender, BarcodeEventArgs e);
public delegate void BarcodeDetectedEventHandler<U>(object sender, BarcodeEventArgs<U> e) where U : unmanaged, IPixel<U>;

/// <summary>
/// Event which is raised when a barcode is detected. It is only raised with the Status Found (0).
/// </summary>
public event BarcodeDetectedEventHandler DetectedBarcode;
public event BarcodeDetectedEventHandler<T> DetectedBarcode;

/// <summary>
/// ZXing BarcodeReader object which is being used for decoding possible barcodes in a bitmap
/// </summary>
private readonly ZXing.ImageSharp.BarcodeReader<Rgba32> reader;
private readonly ZXing.ImageSharp.BarcodeReader<T> reader;

/// <summary>
/// Creates a new instance of the BarcodeReader class. The Constructor will set any settings for decoding barcodes with the Decode() method
Expand All @@ -34,7 +33,7 @@ public class BarcodeReader
/// <param name="performanceMode">The decoder will take less resources to search for the barcodes. By default the mode is set to performance</param>
public BarcodeReader(bool performanceMode = true, params BarcodeFormat[] types)
{
reader = new ZXing.ImageSharp.BarcodeReader<Rgba32>()
reader = new ZXing.ImageSharp.BarcodeReader<T>()
{
AutoRotate = !performanceMode,
Options = new DecodingOptions()
Expand All @@ -53,7 +52,7 @@ public BarcodeReader(bool performanceMode = true, params BarcodeFormat[] types)
/// <param name="type">What type of barcode the provided bitmap should be searched for. By defualt all one-dimensional barcodes will be detected</param>
public BarcodeReader(bool tryHarder, bool autoRotate, params BarcodeFormat[] types)
{
reader = new ZXing.ImageSharp.BarcodeReader<Rgba32>()
reader = new ZXing.ImageSharp.BarcodeReader<T>()
{
AutoRotate = autoRotate,
Options = new DecodingOptions()
Expand All @@ -68,7 +67,7 @@ public BarcodeReader(bool tryHarder, bool autoRotate, params BarcodeFormat[] typ
/// Decodes a barcode from the provided ImageSharp.Image
/// </summary>
/// <returns>Result holding the value if a barcode is found or the error message</returns>
public BarcodeResult Decode(Image<Rgba32> image)
public BarcodeResult<T> Decode(Image<T> image)
{
try
{
Expand All @@ -78,60 +77,75 @@ public BarcodeResult Decode(Image<Rgba32> image)

if (result?.Text != null)
{
BarcodeResult barcodeResult = new BarcodeResult(result.Text, Status.Found, "Barcode found in image", image);
BarcodeResult<T> barcodeResult = new BarcodeResult<T>
{
Message = result.Text,
Status = Status.Found,
Value = result.Text,
Image = image
};

// '?.Invoke' is needed as oherwise an exception would be thrown if ther are no subscribers to the DetectedBarcode event
DetectedBarcode?.Invoke(this, new BarcodeEventArgs(barcodeResult));
DetectedBarcode?.Invoke(this, new BarcodeEventArgs<T> { Result = barcodeResult});

return barcodeResult;
}
else
{
return new BarcodeResult(null, Status.NotFound, "The provided image did not contain a readable barcode", image);
return new BarcodeResult<T>
{
Message = "The provided image did not contain a readable barcode",
Status = Status.NotFound,
Image = image
};
}
}
}
catch (Exception ex)
{
image?.Dispose();

return new BarcodeResult(null, Status.Error, ex.Message, null);
return new BarcodeResult<T>
{
Message = ex.Message,
Status = Status.Error
};
}
}

/// <summary>
/// Decodes a barcode asynchronously from the provided ImageSharp.Image. Make sure to await this method
/// </summary>
/// <returns>Result holding the value if a barcode is found or the error message</returns>
public Task<BarcodeResult> DecodeAsync(Image<Rgba32> image) => Task.Run(() => Decode(image));
public Task<BarcodeResult<T>> DecodeAsync(Image<T> image) => Task.Run(() => Decode(image));

/// <summary>
/// Decodes a barcode from the provided ImageSharp.Image
/// </summary>
/// <param name="data">Array of bytes representing the image</param>
/// <returns>Result holding the value if a barcode is found or the error message</returns>
public BarcodeResult Decode(byte[] data) => Decode(Image.Load(data));
public BarcodeResult<T> Decode(byte[] data) => Decode(Image.Load<T>(data));

/// <summary>
/// Decodes a barcode from the provided ImageSharp.Image
/// </summary>
/// <param name="data">Array of bytes representing the image</param>
/// <returns>Result holding the value if a barcode is found or the error message</returns>
public Task<BarcodeResult> DecodeAsync(byte[] data) => DecodeAsync(Image.Load(data));
public Task<BarcodeResult<T>> DecodeAsync(byte[] data) => DecodeAsync(Image.Load<T>(data));

/// <summary>
/// Decodes a barcode from the provided ImageSharp.Image
/// </summary>
/// <param name="data">Base64 string representing the image</param>
/// <returns>Result holding the value if a barcode is found or the error message</returns>
public BarcodeResult Decode(string data) => Decode(Convert.FromBase64String(RemoveBase64Prefix(data)));
public BarcodeResult<T> Decode(string data) => Decode(Convert.FromBase64String(RemoveBase64Prefix(data)));

/// <summary>
/// Decodes a barcode asynchronously from the provided ImageSharp.Image. Make sure to await this method
/// </summary>
/// <param name="data">Base64 string representing the image</param>
/// <returns>Result holding the value if a barcode is found or the error message</returns>
public Task<BarcodeResult> DecodeAsync(string data) => DecodeAsync(Image.Load(Convert.FromBase64String(RemoveBase64Prefix(data))));
public Task<BarcodeResult<T>> DecodeAsync(string data) => DecodeAsync(Image.Load<T>(Convert.FromBase64String(RemoveBase64Prefix(data))));

/// <summary>
/// Cuts off the prefix of a base64 image string if it has one
Expand Down
21 changes: 5 additions & 16 deletions BarcodeReader.ImageSharp/BarcodeResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,27 @@ namespace BarcodeReader.ImageSharp
/// <summary>
/// Class representing the results after (trying) decoding a barcode from a image
/// </summary>
public class BarcodeResult
public class BarcodeResult<T> where T : unmanaged, IPixel<T>
{
/// <summary>
/// String value of the barcode if one could be decoded
/// </summary>
public string Value { get; }
public string Value { get; set; }

/// <summary>
/// Status of the operation
/// </summary>
public Status Status { get; }
public Status Status { get; set; }

/// <summary>
/// The message. Only really usefull if the Status is Error (2)
/// </summary>
public string Message { get; }
public string Message { get; set; }

/// <summary>
/// The image
/// </summary>
public Image<Rgba32> Image { get; }

/// <summary>
/// Creates a new instance of BarcodeResult
/// </summary>
public BarcodeResult(string value, Status status, string message, Image<Rgba32> image)
{
Value = value;
Status = status;
Message = message;
Image = image;
}
public Image<T> Image { get; set; }
}

/// <summary>
Expand Down

0 comments on commit e518ec4

Please sign in to comment.