Migrating from QRCoder to IronBarcode
This guide is written for development teams whose projects started with QRCoder and have grown to require capabilities beyond QR code generation. QRCoder is a well-maintained, high-quality library for its intended scope, and migration is not a reflection of its quality. It is a response to requirements — format expansion, barcode reading, PDF integration — that fall outside what QRCoder was designed to do. This guide covers the complete technical path from QRCoder to IronBarcode: package replacement, namespace changes, code translation for every common pattern, a mapping of API equivalences, and solutions to the issues that arise during the transition.
Why Migrate from QRCoder
Format Requirements Beyond QR: QRCoder generates QR codes exclusively. Projects that grow to require Code 128 labels for logistics, EAN-13 codes for retail product identification, DataMatrix for pharmaceutical serialization, or PDF417 for government document compliance must introduce a separate library for each additional format. As the number of required formats increases, so does the number of independent packages, APIs, and maintenance obligations.
Barcode Reading Requirements: QRCoder has no barcode reading API — it is a generation-only library by design. Any application that needs to decode QR codes from incoming images, verify barcodes on scanned documents, or process shipment labels must add a dedicated reading library alongside QRCoder. That second library brings its own API surface, its own update cycle, and its own compatibility concerns on each .NET upgrade.
Multi-Library Maintenance: The realistic accumulation pattern for a QRCoder-based project runs from QRCoder for QR generation to a 1D barcode library for shipping labels to a reading library for decoding. Managing three or four independent packages means tracking separate release notes, resolving version conflicts when any one of them updates, and maintaining familiarity with multiple APIs across a development team. The maintenance burden compounds over time in ways that are not visible in the initial integration estimate.
PDF Support: Embedding barcodes in PDF documents or extracting barcodes from incoming PDF files are both outside QRCoder's scope. Document-processing pipelines — invoice handling, label generation from PDF templates, compliance reporting — encounter this boundary early. A dedicated PDF library must be added alongside QRCoder, or the architecture must route barcode generation and PDF generation through separate subsystems.
The Fundamental Problem
QRCoder solves QR generation efficiently. The moment any requirement reaches past QR, the codebase must start pulling in additional packages to fill each gap:
// QRCoder handles QR generation well — but no further
using QRCoder;
using System.IO;
var generator = new QRCodeGenerator();
var qrCodeData = generator.CreateQrCode("SHIP-12345", QRCodeGenerator.ECCLevel.M);
var qrCode = new PngByteQRCode(qrCodeData);
File.WriteAllBytes("qr.png", qrCode.GetGraphic(10));
// Now the shipping team asks for Code 128 — add NetBarcode
// Now the warehouse needs to scan barcodes — add ZXing.Net
// Now a report needs a barcode in a PDF — add a PDF library
// Each addition: new namespace, new API, new maintenance cycle
// QRCoder handles QR generation well — but no further
using QRCoder;
using System.IO;
var generator = new QRCodeGenerator();
var qrCodeData = generator.CreateQrCode("SHIP-12345", QRCodeGenerator.ECCLevel.M);
var qrCode = new PngByteQRCode(qrCodeData);
File.WriteAllBytes("qr.png", qrCode.GetGraphic(10));
// Now the shipping team asks for Code 128 — add NetBarcode
// Now the warehouse needs to scan barcodes — add ZXing.Net
// Now a report needs a barcode in a PDF — add a PDF library
// Each addition: new namespace, new API, new maintenance cycle
Imports QRCoder
Imports System.IO
Dim generator As New QRCodeGenerator()
Dim qrCodeData = generator.CreateQrCode("SHIP-12345", QRCodeGenerator.ECCLevel.M)
Dim qrCode As New PngByteQRCode(qrCodeData)
File.WriteAllBytes("qr.png", qrCode.GetGraphic(10))
' Now the shipping team asks for Code 128 — add NetBarcode
' Now the warehouse needs to scan barcodes — add ZXing.Net
' Now a report needs a barcode in a PDF — add a PDF library
' Each addition: new namespace, new API, new maintenance cycle
IronBarcode consolidates generation, reading, and PDF integration under one API:
// IronBarcode — one library covers all of the above
using IronBarCode;
// Generate QR
BarcodeWriter.CreateBarcode("SHIP-12345", BarcodeEncoding.QRCode)
.SaveAsPng("qr.png");
// Generate Code 128 — same API
BarcodeWriter.CreateBarcode("SHIP-12345", BarcodeEncoding.Code128)
.SaveAsPng("label.png");
// Read a barcode from an image — built in
var results = BarcodeReader.Read("incoming.png");
// IronBarcode — one library covers all of the above
using IronBarCode;
// Generate QR
BarcodeWriter.CreateBarcode("SHIP-12345", BarcodeEncoding.QRCode)
.SaveAsPng("qr.png");
// Generate Code 128 — same API
BarcodeWriter.CreateBarcode("SHIP-12345", BarcodeEncoding.Code128)
.SaveAsPng("label.png");
// Read a barcode from an image — built in
var results = BarcodeReader.Read("incoming.png");
Imports IronBarCode
' Generate QR
BarcodeWriter.CreateBarcode("SHIP-12345", BarcodeEncoding.QRCode) _
.SaveAsPng("qr.png")
' Generate Code 128 — same API
BarcodeWriter.CreateBarcode("SHIP-12345", BarcodeEncoding.Code128) _
.SaveAsPng("label.png")
' Read a barcode from an image — built in
Dim results = BarcodeReader.Read("incoming.png")
IronBarcode vs QRCoder: Feature Comparison
| Feature | QRCoder | IronBarcode |
|---|---|---|
| QR Code Generation | Yes — excellent | Yes |
| Micro QR | Yes | Yes |
| Code 128 / Code 39 | No | Yes |
| EAN-13 / UPC-A | No | Yes |
| DataMatrix | No | Yes |
| PDF417 | No | Yes |
| Aztec | No | Yes |
| Total Formats | 1 | 50+ |
| Barcode Reading | No | Yes — auto-detection |
| PDF Barcode Extraction | No | Yes |
| PDF Barcode Stamping | No | Yes |
| Logo Embedding | Yes | Yes |
| Colour Customisation | Yes | Yes |
| SVG Output | Yes | Yes |
| PayloadGenerator Helpers | Yes | No — manual string construction |
| Zero External Dependencies | Yes | Self-contained |
| Licence | MIT — unrestricted | Commercial ($999 single developer) |
Quick Start: QRCoder to IronBarcode Migration
Step 1: Replace NuGet Package
Remove QRCoder from the project:
dotnet remove package QRCoder
dotnet remove package QRCoder
Install IronBarcode:
dotnet add package IronBarcode
dotnet add package IronBarcode
If the project was using ZXing.Net alongside QRCoder for barcode reading, that package can also be removed at this stage:
dotnet remove package ZXing.Net
dotnet remove package ZXing.Net
Step 2: Update Namespaces
Replace the QRCoder namespace import with the IronBarcode namespace:
// Before (QRCoder)
using QRCoder;
// After (IronBarcode)
using IronBarCode;
// Before (QRCoder)
using QRCoder;
// After (IronBarcode)
using IronBarCode;
' Before (QRCoder)
Imports QRCoder
' After (IronBarcode)
Imports IronBarCode
Step 3: Initialize License
Add licence initialization at application startup — Program.cs, Startup.cs, or a static constructor:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
A free trial key is available without registration. Production deployments require a purchased licence.
Code Migration Examples
Basic QR Code Generation
The most common QRCoder pattern requires three objects: a QRCodeGenerator instance, a QRCodeData intermediate object, and a renderer class such as PngByteQRCode. In IronBarcode, a single static call replaces this chain.
QRCoder Approach:
using QRCoder;
public class BarcodeService
{
private readonly QRCodeGenerator _generator = new QRCodeGenerator();
public byte[] GenerateQR(string content)
{
var qrCodeData = _generator.CreateQrCode(content, QRCodeGenerator.ECCLevel.M);
var qrCode = new PngByteQRCode(qrCodeData);
return qrCode.GetGraphic(10); // 10px per module
}
}
using QRCoder;
public class BarcodeService
{
private readonly QRCodeGenerator _generator = new QRCodeGenerator();
public byte[] GenerateQR(string content)
{
var qrCodeData = _generator.CreateQrCode(content, QRCodeGenerator.ECCLevel.M);
var qrCode = new PngByteQRCode(qrCodeData);
return qrCode.GetGraphic(10); // 10px per module
}
}
Imports QRCoder
Public Class BarcodeService
Private ReadOnly _generator As New QRCodeGenerator()
Public Function GenerateQR(content As String) As Byte()
Dim qrCodeData = _generator.CreateQrCode(content, QRCodeGenerator.ECCLevel.M)
Dim qrCode = New PngByteQRCode(qrCodeData)
Return qrCode.GetGraphic(10) ' 10px per module
End Function
End Class
IronBarcode Approach:
using IronBarCode;
public class BarcodeService
{
public byte[] GenerateQR(string content)
{
return BarcodeWriter.CreateBarcode(content, BarcodeEncoding.QRCode)
.ResizeTo(200, 200)
.ToPngBinaryData();
}
}
using IronBarCode;
public class BarcodeService
{
public byte[] GenerateQR(string content)
{
return BarcodeWriter.CreateBarcode(content, BarcodeEncoding.QRCode)
.ResizeTo(200, 200)
.ToPngBinaryData();
}
}
Imports IronBarCode
Public Class BarcodeService
Public Function GenerateQR(content As String) As Byte()
Return BarcodeWriter.CreateBarcode(content, BarcodeEncoding.QRCode) _
.ResizeTo(200, 200) _
.ToPngBinaryData()
End Function
End Class
BarcodeWriter is a static class — no instance is required, and there is no intermediate data object. The ResizeTo(width, height) method replaces the pixel-per-module integer that QRCoder accepts in GetGraphic. Where QRCoder sizes the output by module count (e.g., GetGraphic(10) for a 10px-per-module image), IronBarcode takes absolute pixel dimensions.
Saving QR Codes to File
QRCoder separates in-memory bytes from file output only by the terminal step — the renderer chain is the same. IronBarcode uses different terminal methods on the same chain.
QRCoder Approach:
using QRCoder;
using System.IO;
var generator = new QRCodeGenerator();
var qrCodeData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.M);
var pngBytes = new PngByteQRCode(qrCodeData).GetGraphic(10);
File.WriteAllBytes("output.png", pngBytes);
using QRCoder;
using System.IO;
var generator = new QRCodeGenerator();
var qrCodeData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.M);
var pngBytes = new PngByteQRCode(qrCodeData).GetGraphic(10);
File.WriteAllBytes("output.png", pngBytes);
Imports QRCoder
Imports System.IO
Dim generator As New QRCodeGenerator()
Dim qrCodeData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.M)
Dim pngBytes = New PngByteQRCode(qrCodeData).GetGraphic(10)
File.WriteAllBytes("output.png", pngBytes)
IronBarcode Approach:
using IronBarCode;
// Save directly — no intermediate byte array needed
BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode)
.ResizeTo(300, 300)
.SaveAsPng("output.png");
// Or obtain bytes for in-memory use
byte[] pngBytes = BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode)
.ResizeTo(300, 300)
.ToPngBinaryData();
using IronBarCode;
// Save directly — no intermediate byte array needed
BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode)
.ResizeTo(300, 300)
.SaveAsPng("output.png");
// Or obtain bytes for in-memory use
byte[] pngBytes = BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode)
.ResizeTo(300, 300)
.ToPngBinaryData();
Imports IronBarCode
' Save directly — no intermediate byte array needed
BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode) _
.ResizeTo(300, 300) _
.SaveAsPng("output.png")
' Or obtain bytes for in-memory use
Dim pngBytes As Byte() = BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode) _
.ResizeTo(300, 300) _
.ToPngBinaryData()
The SaveAsPng method is a terminal that writes directly to disk. ToPngBinaryData returns a byte[] for streaming, HTTP responses, or database storage.
SVG Output
QRCoder Approach:
using QRCoder;
using System.IO;
var generator = new QRCodeGenerator();
var qrCodeData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.M);
string svgContent = new SvgQRCode(qrCodeData).GetGraphic(10);
File.WriteAllText("output.svg", svgContent);
using QRCoder;
using System.IO;
var generator = new QRCodeGenerator();
var qrCodeData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.M);
string svgContent = new SvgQRCode(qrCodeData).GetGraphic(10);
File.WriteAllText("output.svg", svgContent);
Imports QRCoder
Imports System.IO
Dim generator As New QRCodeGenerator()
Dim qrCodeData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.M)
Dim svgContent As String = New SvgQRCode(qrCodeData).GetGraphic(10)
File.WriteAllText("output.svg", svgContent)
IronBarcode Approach:
using IronBarCode;
BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode)
.SaveAsImage("output.svg");
using IronBarCode;
BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode)
.SaveAsImage("output.svg");
Imports IronBarCode
BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode) _
.SaveAsImage("output.svg")
The SvgQRCode renderer class and its GetGraphic call collapse into a single SaveAsImage terminal method (passing an .svg extension produces SVG output).
Error Correction Level Mapping
QRCoder requires explicit ECC selection on every CreateQrCode call using the QRCodeGenerator.ECCLevel enum. IronBarcode applies a sensible default when using BarcodeWriter.CreateBarcode, and exposes explicit control through QRCodeWriter.QrErrorCorrectionLevel.
QRCoder Approach:
using QRCoder;
var generator = new QRCodeGenerator();
// Medium — suitable for most generation without logos
var dataMedium = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.M);
// High — required when a logo will occlude part of the code
var dataHigh = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.H);
using QRCoder;
var generator = new QRCodeGenerator();
// Medium — suitable for most generation without logos
var dataMedium = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.M);
// High — required when a logo will occlude part of the code
var dataHigh = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.H);
Imports QRCoder
Dim generator As New QRCodeGenerator()
' Medium — suitable for most generation without logos
Dim dataMedium = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.M)
' High — required when a logo will occlude part of the code
Dim dataHigh = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.H)
IronBarcode Approach:
using IronBarCode;
// Default — equivalent to Medium, applied automatically
BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode)
.SaveAsPng("default-ecc.png");
// Explicit level via QRCodeWriter
var qr = QRCodeWriter.CreateQrCode(
"https://example.com",
500,
QRCodeWriter.QrErrorCorrectionLevel.Highest
);
qr.SaveAsPng("high-ecc.png");
using IronBarCode;
// Default — equivalent to Medium, applied automatically
BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode)
.SaveAsPng("default-ecc.png");
// Explicit level via QRCodeWriter
var qr = QRCodeWriter.CreateQrCode(
"https://example.com",
500,
QRCodeWriter.QrErrorCorrectionLevel.Highest
);
qr.SaveAsPng("high-ecc.png");
Imports IronBarCode
' Default — equivalent to Medium, applied automatically
BarcodeWriter.CreateBarcode("https://example.com", BarcodeEncoding.QRCode) _
.SaveAsPng("default-ecc.png")
' Explicit level via QRCodeWriter
Dim qr = QRCodeWriter.CreateQrCode( _
"https://example.com", _
500, _
QRCodeWriter.QrErrorCorrectionLevel.Highest _
)
qr.SaveAsPng("high-ecc.png")
The level mapping is: ECCLevel.L → Low, ECCLevel.M → Medium, ECCLevel.Q → High, ECCLevel.H → Highest.
Logo Embedding
Both libraries support logo embedding on QR codes. QRCoder routes this through the QRCode renderer class (not PngByteQRCode) with System.Drawing.Bitmap parameters. IronBarcode provides QRCodeWriter.CreateQrCodeWithLogo() as a dedicated factory method accepting file paths for both the URL and the logo. The QR code style customisation guide covers logo sizing, positioning, and colour combination options.
QRCoder Approach:
using QRCoder;
using System.Drawing;
using System.Drawing.Imaging;
var generator = new QRCodeGenerator();
// ECCLevel.H is required — the logo occludes part of the code
var qrCodeData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.H);
var qrCode = new QRCode(qrCodeData);
var logoBitmap = new Bitmap("logo.png");
var qrBitmap = qrCode.GetGraphic(10, Color.Black, Color.White, logoBitmap);
qrBitmap.Save("qr-logo.png", ImageFormat.Png);
using QRCoder;
using System.Drawing;
using System.Drawing.Imaging;
var generator = new QRCodeGenerator();
// ECCLevel.H is required — the logo occludes part of the code
var qrCodeData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.H);
var qrCode = new QRCode(qrCodeData);
var logoBitmap = new Bitmap("logo.png");
var qrBitmap = qrCode.GetGraphic(10, Color.Black, Color.White, logoBitmap);
qrBitmap.Save("qr-logo.png", ImageFormat.Png);
Imports QRCoder
Imports System.Drawing
Imports System.Drawing.Imaging
Dim generator As New QRCodeGenerator()
' ECCLevel.H is required — the logo occludes part of the code
Dim qrCodeData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.H)
Dim qrCode As New QRCode(qrCodeData)
Dim logoBitmap As New Bitmap("logo.png")
Dim qrBitmap = qrCode.GetGraphic(10, Color.Black, Color.White, logoBitmap)
qrBitmap.Save("qr-logo.png", ImageFormat.Png)
IronBarcode Approach:
using IronBarCode;
QRCodeWriter.CreateQrCodeWithLogo("https://example.com", "logo.png", 500)
.SaveAsPng("qr-logo.png");
using IronBarCode;
QRCodeWriter.CreateQrCodeWithLogo("https://example.com", "logo.png", 500)
.SaveAsPng("qr-logo.png");
Imports IronBarCode
QRCodeWriter.CreateQrCodeWithLogo("https://example.com", "logo.png", 500) _
.SaveAsPng("qr-logo.png")
The System.Drawing.Bitmap dependency is removed — CreateQrCodeWithLogo accepts file path strings for both the content and the logo image. Error correction is automatically set to the level required for logo embedding; no explicit ECC configuration is needed.
PayloadGenerator.WiFi Migration
QRCoder's PayloadGenerator.WiFi formats the standard WiFi QR payload string. The output format is a public standard (WIFI:T:{auth};S:{ssid};P:{password};;) defined by the QR code specification. When migrating, these strings can be constructed directly.
QRCoder Approach:
using QRCoder;
var wifi = new PayloadGenerator.WiFi(
ssid: "OfficeNetwork",
password: "SecurePass123",
authenticationMode: PayloadGenerator.WiFi.Authentication.WPA
);
// wifi.ToString() produces: WIFI:T:WPA;S:OfficeNetwork;P:SecurePass123;;
var generator = new QRCodeGenerator();
var qrData = generator.CreateQrCode(wifi.ToString(), QRCodeGenerator.ECCLevel.M);
var qrCode = new PngByteQRCode(qrData);
System.IO.File.WriteAllBytes("wifi.png", qrCode.GetGraphic(10));
using QRCoder;
var wifi = new PayloadGenerator.WiFi(
ssid: "OfficeNetwork",
password: "SecurePass123",
authenticationMode: PayloadGenerator.WiFi.Authentication.WPA
);
// wifi.ToString() produces: WIFI:T:WPA;S:OfficeNetwork;P:SecurePass123;;
var generator = new QRCodeGenerator();
var qrData = generator.CreateQrCode(wifi.ToString(), QRCodeGenerator.ECCLevel.M);
var qrCode = new PngByteQRCode(qrData);
System.IO.File.WriteAllBytes("wifi.png", qrCode.GetGraphic(10));
Imports QRCoder
Dim wifi = New PayloadGenerator.WiFi(
ssid:="OfficeNetwork",
password:="SecurePass123",
authenticationMode:=PayloadGenerator.WiFi.Authentication.WPA
)
' wifi.ToString() produces: WIFI:T:WPA;S:OfficeNetwork;P:SecurePass123;;
Dim generator = New QRCodeGenerator()
Dim qrData = generator.CreateQrCode(wifi.ToString(), QRCodeGenerator.ECCLevel.M)
Dim qrCode = New PngByteQRCode(qrData)
System.IO.File.WriteAllBytes("wifi.png", qrCode.GetGraphic(10))
IronBarcode Approach:
using IronBarCode;
// Construct the standard WiFi QR string directly
string wifiPayload = "WIFI:T:WPA;S:OfficeNetwork;P:SecurePass123;;";
BarcodeWriter.CreateBarcode(wifiPayload, BarcodeEncoding.QRCode)
.ResizeTo(300, 300)
.SaveAsPng("wifi.png");
using IronBarCode;
// Construct the standard WiFi QR string directly
string wifiPayload = "WIFI:T:WPA;S:OfficeNetwork;P:SecurePass123;;";
BarcodeWriter.CreateBarcode(wifiPayload, BarcodeEncoding.QRCode)
.ResizeTo(300, 300)
.SaveAsPng("wifi.png");
Imports IronBarCode
' Construct the standard WiFi QR string directly
Dim wifiPayload As String = "WIFI:T:WPA;S:OfficeNetwork;P:SecurePass123;;"
BarcodeWriter.CreateBarcode(wifiPayload, BarcodeEncoding.QRCode) _
.ResizeTo(300, 300) _
.SaveAsPng("wifi.png")
For teams with many PayloadGenerator types in use (vCard, CalendarEvent, Geo, SMS), the approach is the same: identify the formatted string that each generator produces using its .ToString() output, then construct that string directly or through a small static helper method.
QRCoder API to IronBarcode Mapping Reference
| QRCoder | IronBarcode | Notes |
|---|---|---|
new QRCodeGenerator() |
Static class — no instance | BarcodeWriter requires no instantiation |
qrGenerator.CreateQrCode(data, ECCLevel.M) |
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.QRCode) |
Direct replacement |
new PngByteQRCode(qrCodeData) |
Not needed | Rendering is part of the fluent chain |
qrCode.GetGraphic(20) returning byte[] |
.ToPngBinaryData() |
Size via .ResizeTo(w, h) |
File.WriteAllBytes(path, bytes) pattern |
.SaveAsPng(path) |
Terminal method on GeneratedBarcode |
new SvgQRCode(qrCodeData).GetGraphic(10) |
.SaveAsImage(path) |
Pass .svg extension for SVG output |
new QRCode(qrCodeData).GetGraphic(...) |
QRCodeWriter.CreateQrCode(data, size, level) |
Used for logo and colour customisation |
QRCodeGenerator.ECCLevel.L |
QRCodeWriter.QrErrorCorrectionLevel.Low |
|
QRCodeGenerator.ECCLevel.M |
QRCodeWriter.QrErrorCorrectionLevel.Medium |
Default when unspecified |
QRCodeGenerator.ECCLevel.Q |
QRCodeWriter.QrErrorCorrectionLevel.High |
|
QRCodeGenerator.ECCLevel.H |
QRCodeWriter.QrErrorCorrectionLevel.Highest |
Required for logo embedding |
PayloadGenerator.WiFi(...).ToString() |
"WIFI:T:WPA;S:{ssid};P:{pass};;" |
Construct standard string directly |
PayloadGenerator.ContactData(...).ToString() |
"BEGIN:VCARD\n..." |
vCard is a public standard |
| No reading API | BarcodeReader.Read(path) |
New capability — no separate library |
| QR format only | 50+ formats via BarcodeEncoding.* |
New capability |
Common Migration Issues and Solutions
Issue 1: PayloadGenerator String Format Change
QRCoder: PayloadGenerator.WiFi, PayloadGenerator.ContactData, and other helpers produce formatted strings automatically. Code passes the helper object's .ToString() output to CreateQrCode.
Solution: Identify the string each PayloadGenerator type produces — its format is documented in the QR code specification and straightforward to reproduce. For WiFi: WIFI:T:WPA;S:{ssid};P:{password};;. For vCard: standard BEGIN:VCARD / END:VCARD blocks. Write static helper methods if many call sites use the same payload type:
public static string WifiPayload(string ssid, string password, string auth = "WPA")
=> $"WIFI:T:{auth};S:{ssid};P:{password};;";
public static string WifiPayload(string ssid, string password, string auth = "WPA")
=> $"WIFI:T:{auth};S:{ssid};P:{password};;";
Public Shared Function WifiPayload(ssid As String, password As String, Optional auth As String = "WPA") As String
Return $"WIFI:T:{auth};S:{ssid};P:{password};;"
End Function
Issue 2: ECCLevel Enum Mapping
QRCoder: QRCodeGenerator.ECCLevel is a nested enum with values L, M, Q, H. It is a required parameter on every CreateQrCode call.
Solution: Map each value to its QRCodeWriter.QrErrorCorrectionLevel equivalent when using the QRCodeWriter path. When using BarcodeWriter.CreateBarcode, the ECC level defaults to Medium automatically and requires no parameter. Update each call site:
// QRCoder ECCLevel.H → IronBarcode QrErrorCorrectionLevel.Highest
var qr = QRCodeWriter.CreateQrCode(data, 500, QRCodeWriter.QrErrorCorrectionLevel.Highest);
// QRCoder ECCLevel.M → IronBarcode default (no parameter needed)
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.QRCode);
// QRCoder ECCLevel.H → IronBarcode QrErrorCorrectionLevel.Highest
var qr = QRCodeWriter.CreateQrCode(data, 500, QRCodeWriter.QrErrorCorrectionLevel.Highest);
// QRCoder ECCLevel.M → IronBarcode default (no parameter needed)
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.QRCode);
' QRCoder ECCLevel.H → IronBarcode QrErrorCorrectionLevel.Highest
Dim qr = QRCodeWriter.CreateQrCode(data, 500, QRCodeWriter.QrErrorCorrectionLevel.Highest)
' QRCoder ECCLevel.M → IronBarcode default (no parameter needed)
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.QRCode)
Issue 3: Renderer Class Removal
QRCoder: Each output format requires its own renderer class instantiation — PngByteQRCode, SvgQRCode, AsciiQRCode, Base64QRCode, QRCode. These classes accept QRCodeData and expose GetGraphic with different return types.
Solution: Remove all renderer class instantiations. IronBarcode builds format output into the terminal methods of the fluent chain. Replace new PngByteQRCode(data).GetGraphic(n) with .ToPngBinaryData() after .ResizeTo(). Replace new SvgQRCode(data).GetGraphic(n) with .SaveAsImage(path) (passing an .svg extension). The QRCodeData intermediate object also disappears — it is not needed in IronBarcode.
Issue 4: PngByteQRCode Removal and Module-Based Sizing
QRCoder: PngByteQRCode.GetGraphic(int pixelsPerModule) sizes the output by the number of pixels per QR module. The resulting image dimensions depend on the number of modules, which varies with content length and ECC level.
Solution: Replace module-based sizing with ResizeTo(int width, int height) for absolute pixel dimensions. If your code calculated the expected output size dynamically from module count, switch to a fixed target size that meets your output requirements:
// Before: GetGraphic(20) — output size varies with content
var bytes = new PngByteQRCode(qrData).GetGraphic(20);
// After: fixed 400×400 regardless of content
byte[] bytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.QRCode)
.ResizeTo(400, 400)
.ToPngBinaryData();
// Before: GetGraphic(20) — output size varies with content
var bytes = new PngByteQRCode(qrData).GetGraphic(20);
// After: fixed 400×400 regardless of content
byte[] bytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.QRCode)
.ResizeTo(400, 400)
.ToPngBinaryData();
Imports System
' Before: GetGraphic(20) — output size varies with content
Dim bytes = New PngByteQRCode(qrData).GetGraphic(20)
' After: fixed 400×400 regardless of content
Dim bytes As Byte() = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.QRCode) _
.ResizeTo(400, 400) _
.ToPngBinaryData()
QRCoder Migration Checklist
Pre-Migration Tasks
Audit the codebase for all QRCoder usage before making any changes:
# Find all QRCoder namespace imports
grep -r "using QRCoder" --include="*.cs" .
# Find all generator and renderer instantiations
grep -r "QRCodeGenerator\|PngByteQRCode\|SvgQRCode\|AsciiQRCode\|QRCode\b" --include="*.cs" .
# Find all PayloadGenerator usages
grep -r "PayloadGenerator\." --include="*.cs" .
# Find ECCLevel references
grep -r "ECCLevel\." --include="*.cs" .
# Find ZXing.Net usage to remove at the same time
grep -r "using ZXing" --include="*.cs" .
# Find all QRCoder namespace imports
grep -r "using QRCoder" --include="*.cs" .
# Find all generator and renderer instantiations
grep -r "QRCodeGenerator\|PngByteQRCode\|SvgQRCode\|AsciiQRCode\|QRCode\b" --include="*.cs" .
# Find all PayloadGenerator usages
grep -r "PayloadGenerator\." --include="*.cs" .
# Find ECCLevel references
grep -r "ECCLevel\." --include="*.cs" .
# Find ZXing.Net usage to remove at the same time
grep -r "using ZXing" --include="*.cs" .
- Document all
PayloadGeneratortypes in use and note their string output formats - Note all ECC level values in use and their call sites
- Identify any ZXing.Net reading code that was paired with QRCoder for decoding — this can be replaced at the same time
- Obtain an IronBarcode licence key (trial keys are available without registration)
Code Update Tasks
- Run
dotnet remove package QRCoder - Run
dotnet remove package ZXing.Netif it was used only for reading alongside QRCoder - Run
dotnet add package IronBarcode - Add
IronBarCode.License.LicenseKey = "YOUR-KEY";to application startup - Replace all
using QRCoder;imports withusing IronBarCode; - Remove all
new QRCodeGenerator()instance declarations —BarcodeWriteris static - Replace all
generator.CreateQrCode(data, ECCLevel.X)+ renderer chain patterns withBarcodeWriter.CreateBarcode(data, BarcodeEncoding.QRCode)chains - Replace
.GetGraphic(n)calls with.ToPngBinaryData()and add.ResizeTo(w, h)before the terminal - Replace
File.WriteAllBytes(path, bytes)save patterns with.SaveAsPng(path)terminal methods - Replace
new SvgQRCode(data).GetGraphic(n)with.SaveAsImage(path)(pass an.svgextension) - Replace
PayloadGenerator.WiFi(...)and other helper instantiations with direct format strings - Map each
QRCodeGenerator.ECCLevelvalue to itsQRCodeWriter.QrErrorCorrectionLevelequivalent - Replace any ZXing.Net
BarcodeReaderGeneric.Decode(bitmap)calls withBarcodeReader.Read(path) - For logo embedding, replace
new QRCode(data).GetGraphic(n, ..., logoBitmap)withQRCodeWriter.CreateQrCodeWithLogo(data, logoPath, size)
Post-Migration Testing
- Scan all generated QR codes with at least two independent QR code scanner applications to verify readability
- Verify logo-embedded QR codes scan correctly — confirm error correction level is
Highest - Compare visual output of generated codes with pre-migration samples where appearance consistency is required
- Test all
PayloadGeneratorreplacements — confirm WiFi, vCard, and other payload strings decode correctly on target devices - If ZXing.Net was also removed, verify all barcode reading paths function through
BarcodeReader.Read - Run the application in a clean environment to confirm no residual QRCoder or ZXing.Net references cause binding failures
- Validate that the IronBarcode licence key is loaded correctly in production and staging environments
Key Benefits of Migrating to IronBarcode
Single API for All Barcode Operations: After migration, every barcode task — generation, reading, PDF stamping — uses the same IronBarCode namespace and the same entry points. Developers joining the project learn one API rather than three. Code review across the barcode subsystem becomes consistent. Documentation lookup is centralised.
Barcode Reading Without a Second Library: BarcodeReader.Read handles image files, PDF pages, streams, and in-memory bitmaps with automatic format detection. The reading capability that previously required ZXing.Net — with its format specification requirements and thread-safety considerations — is available immediately through a single method call. The barcode reading from images guide covers multi-barcode detection, image preprocessing, and PDF page scanning.
Format Expansion Without New Dependencies: Adding Code 128, EAN-13, DataMatrix, PDF417, or any other supported format after migration requires only a different BarcodeEncoding parameter value. There are no new packages to install, no new APIs to learn, and no version compatibility issues to manage. New format requirements become a one-line change rather than a new library integration.
Simplified QR Code Customisation: Logo embedding, colour changes, and quiet zone control are available as named methods on the QRCodeWriter result. The System.Drawing.Bitmap dependency that QRCoder requires for logo embedding is replaced by a simple file path string. The QR code style customisation guide documents all available customisation options.
PDF Integration Built In: Barcodes can be read from incoming PDF documents and stamped into existing PDF files without adding a PDF library. Document-processing workflows that required a separate PDF dependency now have barcode and PDF functionality consolidated.
Reduced Long-Term Maintenance Overhead: Moving from three or four independent packages to one eliminates the compounding overhead of tracking multiple release cycles, resolving inter-library version conflicts, and updating multiple test suites when .NET versions advance. The maintenance cost of the barcode subsystem reduces to a single package dependency.
Frequently Asked Questions
Why should I migrate from QRCoder.NET to IronBarcode?
Common reasons include simplifying licensing (removing SDK + runtime key complexity), eliminating throughput limits, gaining native PDF support, improving Docker/CI/CD deployment, and reducing API boilerplate in production code.
How do I replace QRCoder API calls with IronBarcode?
Replace instance creation and licensing boilerplate with IronBarCode.License.LicenseKey = "key". Replace reader calls with BarcodeReader.Read(path) and writer calls with BarcodeWriter.CreateBarcode(data, encoding). Static methods require no instance management.
How much code changes when migrating from QRCoder.NET to IronBarcode?
Most migrations result in fewer lines of code. Licensing boilerplate, instance constructors, and explicit format configuration are removed. Core read/write operations map to shorter IronBarcode equivalents with cleaner result objects.
Do I need to keep both QRCoder.NET and IronBarcode installed during migration?
No. Most migrations are direct replacements rather than parallel operation. Migrate one service class at a time, replace the NuGet reference, and update the instantiation and API call patterns before moving to the next class.
What is the NuGet package name for IronBarcode?
The package is 'IronBarCode' (with capital B and C). Install it with 'Install-Package IronBarCode' or 'dotnet add package IronBarCode'. The using directive in code is 'using IronBarCode;'.
How does IronBarcode simplify Docker deployment compared to QRCoder.NET?
IronBarcode is a NuGet package with no external SDK files or mounted license configuration. In Docker, set the IRONBARCODE_LICENSE_KEY environment variable and the package handles license validation at startup.
Does IronBarcode detect all barcode formats automatically after migrating from QRCoder?
Yes. IronBarcode auto-detects symbology across all supported formats. Explicit BarcodeTypes enumeration is not required. If format is already known and performance matters, BarcodeReaderOptions allows restricting the search space as an optimization.
Can IronBarcode read barcodes from PDFs without a separate library?
Yes. BarcodeReader.Read("document.pdf") processes PDF files natively. Results include PageNumber, Format, Value, and Confidence for each barcode found. No external PDF rendering step is required.
How does IronBarcode handle parallel barcode processing?
IronBarcode's static methods are stateless and thread-safe. Use Parallel.ForEach directly over file lists without per-thread instance management. BarcodeReaderOptions.MaxParallelThreads controls the internal thread budget.
What result properties change when migrating from QRCoder.NET to IronBarcode?
Common renames: BarcodeValue becomes Value, BarcodeType becomes Format. IronBarcode results also add Confidence and PageNumber. A solution-wide search-and-replace handles the renames in existing result-processing code.
How do I set up IronBarcode licensing in a CI/CD pipeline?
Store IRONBARCODE_LICENSE_KEY as a pipeline secret and assign IronBarCode.License.LicenseKey in application startup code. One secret covers all environments including development, test, staging, and production.
Does IronBarcode support QR code generation with custom styling?
Yes. QRCodeWriter.CreateQrCode() supports custom colors via ChangeBarCodeColor(), logo embedding via AddBrandLogo(), configurable error correction levels, and multiple output formats including PNG, JPG, PDF, and stream.

