using Extrudex.Domain.Enums; using Extrudex.Domain.Interfaces; using QRCoder; namespace Extrudex.Infrastructure.Services; /// /// Generates high-contrast QR codes encoding deep links to Extrudex resources. /// Optimized for small label printing with dark modules on white background. /// Uses QRCoder library with ECC-level High for robust scanning on tiny labels. /// public class QrCodeService : IQrCodeService { private const string BaseUrl = "https://extrudex.app"; /// public byte[] GeneratePng(QrResourceType resourceType, Guid id, int pixelsPerModule = 20) { var url = GetResourceUrl(resourceType, id); using var qrGenerator = new QRCodeGenerator(); var qrCodeData = qrGenerator.CreateQrCode( url, QRCodeGenerator.ECCLevel.H); // High error correction — critical for small labels using var qrCode = new PngByteQRCode(qrCodeData); return qrCode.GetGraphic( pixelsPerModule, darkColorRgba: new byte[] { 0, 0, 0, 255 }, // Pure black — maximum contrast lightColorRgba: new byte[] { 255, 255, 255, 255 }, // Pure white background drawQuietZones: true); // Quiet zones improve scan reliability } /// public string GenerateSvg(QrResourceType resourceType, Guid id) { var url = GetResourceUrl(resourceType, id); using var qrGenerator = new QRCodeGenerator(); var qrCodeData = qrGenerator.CreateQrCode( url, QRCodeGenerator.ECCLevel.H); using var svgQrCode = new SvgQRCode(qrCodeData); return svgQrCode.GetGraphic( pixelsPerModule: 20, darkColorHex: "#000000", // Pure black — maximum contrast lightColorHex: "#FFFFFF", // Pure white background drawQuietZones: true, sizingMode: SvgQRCode.SizingMode.WidthHeightAttribute); } /// public string GetResourceUrl(QrResourceType resourceType, Guid id) { var path = resourceType switch { QrResourceType.Spool => $"/spools/{id}", QrResourceType.Printer => $"/printers/{id}", QrResourceType.Location => $"/locations/{id}", _ => throw new ArgumentOutOfRangeException(nameof(resourceType), resourceType, $"Unsupported QR resource type: {resourceType}") }; return $"{BaseUrl}{path}"; } }