No-deps QR + barcode toolkit for .NET (encode/decode, payload helpers, and renderers: SVG/HTML/PNG/JPEG/BMP/PPM/PBM/PGM/PAM/XBM/XPM/TGA/ICO/PDF/EPS/SVGZ/ASCII).
$ dotnet add package CodeGlyphXCodeGlyphX is a fast, dependency-free toolkit for QR codes and barcodes, with robust decoding and a minimal API. It targets modern .NET as well as legacy .NET Framework, and includes renderers, payload helpers, and WPF controls.
📦 NuGet Package
🛠️ Project Information
👨💻 Author & Social
CodeGlyphX is a no-deps QR + barcode toolkit for .NET with:
ROADMAP.mdWEBSITE.mddotnet add package CodeGlyphXusing CodeGlyphX;
using CodeGlyphX.Rendering;
var options = new CodeGlyphDecodeOptions {
PreferBarcode = false,
Qr = new QrPixelDecodeOptions {
Profile = QrDecodeProfile.Robust,
MaxMilliseconds = 800
}
};
if (CodeGlyph.TryDecode(pixels, width, height, stride, PixelFormat.Rgba32, out var decoded, options)) {
Console.WriteLine($"{decoded.Kind}: {decoded.Text}");
}Presets for easy tuning:
var fast = CodeGlyphDecodeOptions.Fast();
var robust = CodeGlyphDecodeOptions.Robust();
var stylized = CodeGlyphDecodeOptions.Stylized();
var screen = CodeGlyphDecodeOptions.Screen(maxMilliseconds: 300, maxDimension: 1200);Barcode checksum policy:
var options = new CodeGlyphDecodeOptions {
ExpectedBarcode = BarcodeType.Code39,
Code39Checksum = Code39ChecksumPolicy.StripIfValid,
PreferBarcode = true
};Cancellation and time budget:
using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(500));
var options = new CodeGlyphDecodeOptions {
Qr = new QrPixelDecodeOptions { Profile = QrDecodeProfile.Robust },
CancellationToken = cts.Token
};
if (CodeGlyph.TryDecode(pixels, width, height, stride, PixelFormat.Rgba32, out var decoded, options)) {
Console.WriteLine(decoded.Text);
}Screen-friendly preset:
var options = CodeGlyphDecodeOptions.Screen(maxMilliseconds: 300, maxDimension: 1200);
if (CodeGlyph.TryDecode(pixels, width, height, stride, PixelFormat.Rgba32, out var decoded, options)) {
Console.WriteLine(decoded.Text);
}| Feature | Windows | Linux | macOS |
|---|---|---|---|
| Core encode/decode (QR/1D/2D) | ✅ | ✅ | ✅ |
| Renderers (PNG/SVG/SVGZ/HTML/JPEG/BMP/PPM/PBM/PGM/PAM/XBM/XPM/TGA/ICO/PDF/EPS/ASCII) | ✅ | ✅ | ✅ |
| Image decoding (PNG/JPEG/GIF/BMP/PPM/PBM/PGM/PAM/XBM/XPM/TGA) | ✅ | ✅ | ✅ |
| WPF controls | ✅ | ❌ | ❌ |
Cross-Platform Testing: Builds and tests run on Windows, Linux, and macOS. Windows additionally builds WPF and .NET Framework targets.
Benchmarks were run on 2026-01-19 (Linux Ubuntu 24.04, Ryzen 9 9950X, .NET 8.0.22). Your results will vary.
| Scenario | Mean (us) | Allocated |
|---|---|---|
| QR PNG (short text) | 331.33 | 431.94 KB |
| QR PNG (medium text) | 713.68 | 837.75 KB |
| QR PNG (long text) | 2197.99 | 3041.06 KB |
| QR SVG (medium text) | 99.17 | 20.03 KB |
| QR PNG (High EC) | 1094.94 | 1535.88 KB |
| QR HTML (medium text) | 115.46 | 137.43 KB |
| Scenario | Mean (ms) | Allocated | Notes |
|---|---|---|---|
| QR decode (clean, fast) | 2.148 | 103.9 KB | qr-clean-small.png |
| QR decode (clean, balanced) | 2.124 | 103.9 KB | qr-clean-small.png |
| QR decode (clean, robust) | 2.193 | 103.9 KB | qr-clean-small.png |
| QR decode (noisy, robust) | 170.949 | 8507.41 KB | qr-noisy-ui.png (Robust, MaxMilliseconds=800) |
| Scenario | Mean (us) | Allocated |
|---|---|---|
| Code 128 PNG | 442.41 | 756.24 KB |
| Code 128 SVG | 2.52 | 17.61 KB |
| EAN PNG | 191.33 | 338.54 KB |
| Code 39 PNG | 311.37 | 414.49 KB |
| Code 93 PNG | 222.69 | 367.76 KB |
| UPC-A PNG | 175.83 | 338.85 KB |
| Scenario | Mean (us) | Allocated |
|---|---|---|
| Data Matrix PNG (medium) | 303.48 | 447.73 KB |
| Data Matrix PNG (long) | 711.93 | 1509.06 KB |
| Data Matrix SVG | 5.64 | 12.29 KB |
| PDF417 PNG | 1730.92 | 3154.87 KB |
| PDF417 SVG | 28.79 | 64.53 KB |
| Aztec PNG | 260.70 | 452.30 KB |
| Aztec SVG | 12.76 | 59.74 KB |
dotnet run -c Release --framework net8.0 --project CodeGlyphX.Benchmarks/CodeGlyphX.Benchmarks.csproj -- --filter "*"Based on public docs as of 2026-01-18. Capabilities depend on optional renderer packages.
| Library | Encode | Decode | 2D Codes | 1D Codes | Image Dependencies |
|---|---|---|---|---|---|
| CodeGlyphX | ✅ | ✅ | QR, Micro QR, Data Matrix, PDF417, Aztec | ✅ | None |
| ZXing.Net | ✅ | ✅ | QR, Data Matrix, PDF417, Aztec, more | ✅ | Bindings for System.Drawing / ImageSharp / SkiaSharp / OpenCV |
| QRCoder | ✅ | ❌ | QR only | ❌ | System.Drawing renderer (Windows) or alt renderers |
| Barcoder | ✅ | ❌ | QR, Data Matrix, PDF417, Aztec | ✅ | ImageSharp.Drawing for image renderer |
| Symbology | Encode | Decode | Outputs | Notes |
|---|---|---|---|---|
| QR | ✅ | ✅ | All (see Output formats) | ECI, FNC1/GS1, Kanji, structured append |
| Micro QR | ✅ | ✅ | All (see Output formats) | Versions M1–M4 |
| Code128 | ✅ | ✅ | All (see Output formats) | Set A/B/C |
| GS1-128 | ✅ | ✅ | All (see Output formats) | FNC1 + AI helpers |
| Code39 | ✅ | ✅ | All (see Output formats) | Optional checksum |
| Code93 | ✅ | ✅ | All (see Output formats) | Optional checksum |
| Code11 | ✅ | ✅ | All (see Output formats) | Optional checksum |
| Codabar | ✅ | ✅ | All (see Output formats) | A/B/C/D start/stop |
| MSI | ✅ | ✅ | All (see Output formats) | Mod10 / Mod10Mod10 |
| Plessey | ✅ | ✅ | All (see Output formats) | CRC |
| EAN-8 / EAN-13 | ✅ | ✅ | All (see Output formats) | Checksum validation |
| UPC-A / UPC-E | ✅ | ✅ | All (see Output formats) | Checksum validation |
| ITF-14 | ✅ | ✅ | All (see Output formats) | Checksum validation |
| Data Matrix | ✅ | ✅ | All (see Output formats) | ASCII/C40/Text/X12/EDIFACT/Base256 |
| PDF417 | ✅ | ✅ | All (see Output formats) | Full encode/decode |
| Aztec | ✅ | ✅ | All (see Output formats) | Module matrix + basic pixel decode |
CodeGlyphX is AOT-friendly (no reflection, no runtime codegen) and ships with trimming/AOT analyzers enabled for .NET 8+ targets.
Recommended publish flags: PublishAot=true (native), or PublishTrimmed=true (size) for app projects.
Save(...) chooses the output based on file extension for QR/Barcode/DataMatrix/PDF417/Aztec.
| Format | Extensions | Notes |
|---|---|---|
| PNG | .png | Raster |
| JPEG | .jpg, .jpeg | Raster, quality via options |
| BMP | .bmp | Raster |
| PPM | .ppm | Raster (portable pixmap) |
| PBM | .pbm | Raster (portable bitmap) |
| PGM | .pgm | Raster (portable graymap) |
| PAM | .pam | Raster (portable anymap, RGBA) |
| XBM | .xbm | Text (1-bit) |
| XPM | .xpm | Text (2-color) |
| TGA | .tga | Raster |
| ICO | .ico | Raster (PNG inside, multi-size by default) |
| SVG | .svg | Vector |
| SVGZ | .svgz, .svg.gz | Vector (gzip-compressed SVG) |
| HTML | .html, .htm | Table-based output |
.pdf | Vector by default, raster via RenderMode | |
| EPS | .eps, .ps | Vector by default, raster via RenderMode |
| ASCII | API only | Use RenderAscii methods |
| Raw RGBA | API only | Use RenderPixels methods |
using CodeGlyphX;
var opts = new QrEasyOptions {
IcoSizes = new[] { 32, 64, 128 },
IcoPreserveAspectRatio = true
};
QR.Save("https://example.com", "qr.ico", opts);QR payload helpers generate well-known structured strings so scanners can trigger the right action.
| Category | Payloads |
|---|---|
| Core | Text, URL, Bookmark, WiFi |
| Communication | Email (Mailto/MATMSG/SMTP), Phone, SMS, MMS, Skype |
| Location & Calendar | Geo, Calendar (iCal/vEvent) |
| Contacts | vCard / MeCard |
| OTP | TOTP / HOTP (otpauth://) |
| Social & Stores | App Store (Apple/Google), Facebook, X/Twitter, TikTok, LinkedIn, WhatsApp |
| Payments | UPI, SEPA Girocode (EPC), BezahlCode (contact/payment/debit/periodic), Swiss QR Bill, Slovenian UPN, Russia Payment Order (ST00012) |
| Crypto & Network | Bitcoin / Bitcoin Cash / Litecoin, Monero, ShadowSocks |
using CodeGlyphX;
QR.Save("https://example.com", "qr.png");
QR.Save("https://example.com", "qr.svg");
QR.Save("https://example.com", "qr.jpg");
QR.Save("https://example.com", "qr.pdf");using CodeGlyphX;
// Simple styling (colored eyes + rounded modules)
var opts = new QrEasyOptions {
ModuleShape = QrPngModuleShape.Rounded,
ModuleCornerRadiusPx = 3,
Eyes = new QrPngEyeOptions {
UseFrame = true,
OuterShape = QrPngModuleShape.Circle,
InnerShape = QrPngModuleShape.Circle,
OuterColor = new Rgba32(220, 20, 60),
InnerColor = new Rgba32(220, 20, 60),
}
};
QR.Save("https://example.com", "qr-styled.png", opts);using CodeGlyphX;
using CodeGlyphX.Rendering;
// PDF/EPS are vector by default. Use Raster when you need pixels.
QR.SavePdf("https://example.com", "qr-raster.pdf", mode: RenderMode.Raster);Notes:
using CodeGlyphX;
Barcode.Save(BarcodeType.Code128, "CODE128-12345", "code128.png");
Barcode.Save(BarcodeType.Code128, "CODE128-12345", "code128.pdf");
Barcode.Save(BarcodeType.Code128, "CODE128-12345", "code128.eps");using CodeGlyphX;
// One-liners with defaults
var png = BarcodeEasy.RenderPng(BarcodeType.Code128, "CODE128-12345");using CodeGlyphX;
DataMatrixCode.Save("DataMatrix-12345", "datamatrix.png");
DataMatrixCode.Save("DataMatrix-12345", "datamatrix.pdf");
DataMatrixCode.Save("DataMatrix-12345", "datamatrix.eps");
Pdf417Code.Save("PDF417-12345", "pdf417.png");
Pdf417Code.Save("PDF417-12345", "pdf417.pdf");
Pdf417Code.Save("PDF417-12345", "pdf417.eps");using CodeGlyphX;
using CodeGlyphX.Payloads;
QR.Save(QrPayloads.Url("https://example.com"), "url.png");
QR.Save(QrPayloads.Wifi("MyWiFi", "p@ssw0rd"), "wifi.png");
QR.Save(QrPayloads.OneTimePassword(OtpAuthType.Totp, "JBSWY3DPEHPK3PXP", label: "user@example.com", issuer: "AuthIMO"), "otp.png");using CodeGlyphX;
if (QrImageDecoder.TryDecodeImage(File.ReadAllBytes("code.bmp"), out var decoded)) {
Console.WriteLine(decoded.Text);
}using CodeGlyphX;
var options = QrPixelDecodeOptions.Fast();
if (QrImageDecoder.TryDecodeImage(File.ReadAllBytes("screen.png"), options, out var decoded)) {
Console.WriteLine(decoded.Text);
}using CodeGlyphX;
var options = QrPixelDecodeOptions.Screen(maxMilliseconds: 300, maxDimension: 1200);
if (QrImageDecoder.TryDecodeImage(File.ReadAllBytes("screen.png"), options, out var decoded)) {
Console.WriteLine(decoded.Text);
}using CodeGlyphX;
var bytes = File.ReadAllBytes("screen.png");
if (QR.TryDecodeImage(bytes, QrPixelDecodeOptions.Screen(), out var decoded)) {
Console.WriteLine(decoded.Text);
}using CodeGlyphX;
if (!QrImageDecoder.TryDecodeImage(File.ReadAllBytes("screen.png"), out var decoded, out var info)) {
QrDiagnosticsDump.WriteText("decode-diagnostics.txt", info, source: "screen.png");
}using CodeGlyphX;
if (CodeGlyph.TryDecodeAllPng(File.ReadAllBytes("unknown.png"), out var results)) {
foreach (var item in results) Console.WriteLine($"{item.Kind}: {item.Text}");
}using CodeGlyphX;
if (Barcode.TryDecodeImage(File.ReadAllBytes("code.png"), BarcodeType.Code128, out var barcode))
Console.WriteLine(barcode.Text);using CodeGlyphX;
if (DataMatrixCode.TryDecodeImage(File.ReadAllBytes("dm.png"), out var text))
Console.WriteLine(text);using CodeGlyphX;
if (Pdf417Code.TryDecodeImage(File.ReadAllBytes("pdf417.png"), out var text))
Console.WriteLine(text);using CodeGlyphX;
if (AztecCode.TryDecodeImage(File.ReadAllBytes("aztec.png"), out var text))
Console.WriteLine(text);using CodeGlyphX;
var opts = ImageDecodeOptions.Screen(maxMilliseconds: 300, maxDimension: 1200);
Barcode.TryDecodePng(File.ReadAllBytes("barcode.png"), BarcodeType.Code128, opts, out var barcode);xmlns:wpf="clr-namespace:CodeGlyphX.Wpf;assembly=CodeGlyphX.Wpf"<wpf:QrCodeControl Text="{Binding QrText}" Ecc="M" ModuleSize="6" QuietZone="4" />
<wpf:Barcode128Control Value="{Binding BarcodeValue}" ModuleSize="2" QuietZone="10" />Apache-2.0.