diff --git a/DocumentOperator.Infrastructure/Services/QrCodeProcessing/DevExpressSwissQrCodeProcessor.cs b/DocumentOperator.Infrastructure/Services/QrCodeProcessing/DevExpressSwissQrCodeProcessor.cs
index e767283..73d26e0 100644
--- a/DocumentOperator.Infrastructure/Services/QrCodeProcessing/DevExpressSwissQrCodeProcessor.cs
+++ b/DocumentOperator.Infrastructure/Services/QrCodeProcessing/DevExpressSwissQrCodeProcessor.cs
@@ -1,9 +1,11 @@
using Codecrete.SwissQRBill.Generator;
+using DevExpress.Drawing;
using DevExpress.Pdf;
using DocumentOperator.Application.Common.Interfaces;
using DocumentOperator.Domain.Exceptions;
using DocumentOperator.Domain.ValueObjects;
using System.Drawing;
+using System.Runtime.Versioning;
using ZXing;
namespace DocumentOperator.Infrastructure.Services.QrCodeProcessing;
@@ -17,6 +19,7 @@ public sealed class DevExpressSwissQrCodeProcessor : ISwissQrCodeProcessor
private const int QrCodeSearchDpi = 300; // High DPI for better QR code recognition
///
+ [SupportedOSPlatform("windows")]
public async Task ExtractSwissQrCodeAsync(byte[] pdfBytes, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(pdfBytes);
@@ -64,30 +67,39 @@ public sealed class DevExpressSwissQrCodeProcessor : ISwissQrCodeProcessor
///
/// Renders a PDF page to a high-resolution bitmap for QR code detection
///
- private static Bitmap RenderPageToImage(PdfDocumentProcessor processor, int pageIndex)
+ private static DXBitmap RenderPageToImage(PdfDocumentProcessor processor, int pageIndex)
{
// Render page at high DPI for better QR code recognition
- var pageImage = processor.CreateBitmap(pageIndex + 1, QrCodeSearchDpi);
+ var pageImage = processor.CreateDXBitmap(pageIndex + 1, QrCodeSearchDpi);
return pageImage;
}
///
- /// Decodes QR code from an image using ZXing library
+ /// Decodes QR code from a DXBitmap image using ZXing library
///
- private static string? DecodeQrCodeFromImage(Bitmap image)
+ [SupportedOSPlatform("windows")]
+ private static string? DecodeQrCodeFromImage(DXBitmap dxImage)
{
+ // Convert DXBitmap to System.Drawing.Bitmap via MemoryStream
+ using var ms = new MemoryStream();
+ dxImage.Save(ms, DXImageFormat.Png);
+ ms.Position = 0;
+
+ using var gdiImage = Image.FromStream(ms);
+ using var gdiBitmap = new Bitmap(gdiImage);
+
var reader = new ZXing.Windows.Compatibility.BarcodeReader
{
AutoRotate = true,
- TryInverted = true,
Options = new ZXing.Common.DecodingOptions
{
- PossibleFormats = new[] { BarcodeFormat.QR_CODE },
- TryHarder = true
+ PossibleFormats = [BarcodeFormat.QR_CODE],
+ TryHarder = true,
+ TryInverted = true
}
};
- var result = reader.Decode(image);
+ var result = reader.Decode(gdiBitmap);
return result?.Text;
}
@@ -155,7 +167,13 @@ public sealed class DevExpressSwissQrCodeProcessor : ISwissQrCodeProcessor
}
///
- /// Maps Codecrete Address to our AddressData value object
+ /// Maps Codecrete Address to our AddressData value object.
+ ///
+ /// NOTE: AddressLine1 and AddressLine2 (Combined Address / K-Type) are deprecated
+ /// as of Swiss Payment Standards 2025 (effective 21 Nov 2025).
+ /// The Swiss QR Bill now mandates Structured Address (S-Type) format.
+ /// These fields are retained for backward compatibility with legacy QR codes
+ /// generated before the deprecation date.
///
private static AddressData MapAddress(Codecrete.SwissQRBill.Generator.Address address)
{
@@ -165,8 +183,10 @@ public sealed class DevExpressSwissQrCodeProcessor : ISwissQrCodeProcessor
Name = address.Name ?? string.Empty,
Street = address.Street,
BuildingNumber = address.HouseNo,
+#pragma warning disable CS0618 // AddressLine1/AddressLine2 obsolete but required for backward compatibility
AddressLine1 = address.AddressLine1,
AddressLine2 = address.AddressLine2,
+#pragma warning restore CS0618
PostalCode = address.PostalCode ?? string.Empty,
City = address.Town ?? string.Empty,
Country = address.CountryCode ?? string.Empty