Skip to content
Client v5: BLE, BLE Hosting, HTTP, Jobs - Linux, MacOS, & Blazor Support! Full AOT, RX on BLE only & MANY other features! Power up!

Barcodes & QR Codes | Headless Rendering

BarcodeRenderer is a static, stateless class that produces barcode output directly — no view, no component, no platform dependency. It’s the engine the MAUI views and Blazor components both call, exposed for use from view models, services, PDF builders, background jobs, and server code.

using Shiny.Controls.Barcodes;

Everything here lives in the shared Shiny.Controls.Barcodes package, which is pulled in transitively by both the MAUI and Blazor packages — so if you’ve installed either UI package, the renderer is already available.

Three static methods, all overloads of “encode content as format using options”:

// Raw PNG bytes
byte[] RenderPng(string content, BarcodeFormat format, BarcodeRenderOptions? options = null);
// SVG markup (a complete <svg>…</svg> string)
string RenderSvg(string content, BarcodeFormat format, BarcodeRenderOptions? options = null);
// data: URI — pick PNG or SVG encoding
string RenderDataUri(string content, BarcodeFormat format, BarcodeImageFormat imageFormat, BarcodeRenderOptions? options = null);

options is optional — omit it to use the defaults. All three calls are pure and thread-safe; call them from anywhere.

var opts = new BarcodeRenderOptions
{
PixelWidth = 600,
PixelHeight = 200,
Margin = 10,
ForegroundColor = "#000000",
BackgroundColor = "#FFFFFF",
QRErrorCorrection = QRErrorCorrection.High // QR only — ignored for other formats
};
byte[] png = BarcodeRenderer.RenderPng("Hello", BarcodeFormat.QRCode, opts);
string svg = BarcodeRenderer.RenderSvg("Hello", BarcodeFormat.QRCode, opts);
string dataUri = BarcodeRenderer.RenderDataUri("Hello", BarcodeFormat.QRCode, BarcodeImageFormat.Png, opts);
PropertyTypeDefaultDescription
PixelWidthint250Output bitmap width
PixelHeightint250Output bitmap height
Marginint10Quiet-zone padding in pixels
ForegroundColorstring"#000000"Hex — #RGB, #RRGGBB, or #AARRGGBB (alpha is stripped)
BackgroundColorstring"#FFFFFF"Hex — same formats as above
QRErrorCorrectionQRErrorCorrectionMediumQR-only; ignored for all other formats
byte[] png = BarcodeRenderer.RenderPng("https://shinylib.net", BarcodeFormat.QRCode);
File.WriteAllBytes("join.png", png);

Most PDF libraries accept a byte[] or Stream for an image:

var png = BarcodeRenderer.RenderPng(invoice.Number, BarcodeFormat.Code128, new()
{
PixelWidth = 600,
PixelHeight = 160
});
pdf.AddImage(png); // e.g. QuestPDF, iText, etc.

A data URI drops straight into an <img src="…">, so the image travels with the message body:

var dataUri = BarcodeRenderer.RenderDataUri(
order.Tracking,
BarcodeFormat.Code128,
BarcodeImageFormat.Png // most email clients render PNG more reliably than inline SVG
);
var html = $"<img src=\"{dataUri}\" alt=\"Tracking {order.Tracking}\" />";
string svg = BarcodeRenderer.RenderSvg(label.Sku, BarcodeFormat.DataMatrix, new()
{
PixelWidth = 300,
PixelHeight = 300
});
// drop `svg` directly into your XAML/HTML print layout

The PNG path doesn’t depend on SkiaSharp or System.Drawing. It encodes the ZXing bit-matrix into a PNG by hand: a custom zlib deflate stream, CRC32 for the chunk checksums, and Adler32 for the zlib trailer. That’s what keeps the package fully managed and AOT/trim-safe across every target — including iOS and Blazor WASM, where System.Drawing isn’t an option.

The SVG path emits one <path> built from horizontal runs of dark modules, with shape-rendering="crispEdges" so it never anti-aliases the edges. That makes the SVG both small and pixel-sharp at any scale.