IRONSOFTWAREHOME
MIGRATION GUIDES

Migrating from BarcodeLib to IronBarcode

Curtis Chau
Curtis Chau
Updated: August 1, 2026

This guide provides a complete migration path from BarcodeLib to IronBarcode for .NET developers. It covers the reasons teams make this transition, step-by-step package replacement, code migration examples for every common BarcodeLib pattern, a full API mapping reference, and a structured checklist for managing the migration across a codebase.

Why Migrate from BarcodeLib

Teams migrating from BarcodeLib to IronBarcode report these triggers:

No Reading API: BarcodeLib has never included a reading or decoding capability. When a project that was generating barcode images receives a new requirement to also scan barcodes - from uploaded images, warehouse scanners, or supplier documents - BarcodeLib cannot fulfill it. The only option is adding a second library such as ZXing.Net, which introduces a second dependency graph and second API surface to maintain alongside BarcodeLib.

SkiaSharp Version Conflict: BarcodeLib 3.x introduced SkiaSharp as a graphics backend to replace System.Drawing.Common. The library pins to a specific SkiaSharp version range. In MAUI projects, Blazor projects, and any project where another dependency also pulls in SkiaSharp, the resolved version frequently falls outside BarcodeLib's expected range. This produces NU1608 warnings during restore and, in the worst cases, runtime assembly binding failures on device.

No PDF Support: Applications that generate PDF documents with embedded barcodes - invoices, work orders, shipping manifests - sometimes need to read those barcodes back during downstream processing. BarcodeLib generates barcode images but has no PDF support on either end. Extracting barcodes from a PDF with BarcodeLib requires rendering the PDF pages to images with a separate PDF library and then passing those images to a separate reading library.

Stream-Encoding Step for Byte Array Output: BarcodeLib 3.x returns SKImage, which requires a SkiaSharp encode step into a MemoryStream to produce the byte[] output that HTTP responses, database BLOB columns, and most downstream consumers actually need. IronBarcode provides .ToPngBinaryData() directly on the generation chain.

The Fundamental Problem

BarcodeLib's generation-only architecture means that adding any scan capability forces a second library into the stack:

// BarcodeLib: generation only — reading requires a completely separate library
using BarcodeStandard;
using SkiaSharp;

var b = new Barcode();
SKImage img = b.Encode(Type.Code128, "PRODUCT-12345", 300, 100);
using var stream = File.OpenWrite("barcode.png");
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);

// To read it back, a separate scanning library such as ZXing.Net is required —
// separate API, separate dependency graph to maintain alongside BarcodeLib.

IronBarcode handles both in the same package with the same using statement:

// IronBarcode: generation and reading — no second library needed
using IronBarCode;

// Generate
BarcodeWriter.CreateBarcode("PRODUCT-12345", BarcodeEncoding.Code128)
    .ResizeTo(300, 100)
    .SaveAsPng("barcode.png");

// Read back — same package, same namespace
var result = BarcodeReader.Read("barcode.png").First().Value;
Console.WriteLine(result);  // "PRODUCT-12345"

IronBarcode vs BarcodeLib: Feature Comparison

FeatureBarcodeLibIronBarcode
Barcode generationYesYes
Barcode reading / scanningNoYes (BarcodeReader.Read())
QR code generationNo (1D only)Yes (advanced, with logo embedding)
PDF barcode readingNoYes (native, no extra library)
PDF barcode generation outputNoYes
SkiaSharp dependencyYes (version conflict risk)No
MAUI project compatibilityConflict risk (NU1608)No conflict
Fluent chainable APINoYes
byte[] output directlyManual (via MemoryStream).ToPngBinaryData()
Multi-barcode detectionNoYes (ExpectMultipleBarcodes)
Reading speed tuningN/AYes (ReadingSpeed enum)
Linux / macOS supportPartial (SkiaSharp-dependent)Full
Docker / container supportConfiguration requiredYes
Active maintenanceYes (community)Yes (commercial)
Commercial support / SLANoYes
LicenseApache 2.0 (free)$999-$4,799 perpetual

Quick Start: BarcodeLib to IronBarcode Migration

The migration can begin immediately with these foundational steps.

Step 1: Replace NuGet Package

Remove the BarcodeLib package first:

dotnet remove package BarcodeLib
SHELL

If you are not sure how it is referenced, check the .csproj file:

grep -n "BarcodeLib" YourProject.csproj
SHELL

Remove all BarcodeLib-related <PackageReference> entries. If you added explicit <PackageReference Include="SkiaSharp"> overrides to work around NU1608 warnings from BarcodeLib, remove those too - after installing IronBarcode, evaluate whether SkiaSharp is still needed for other reasons. Then install IronBarcode:

dotnet add package IronBarcode
SHELL

Step 2: Update Namespaces

Replace the BarcodeLib using directives in each file that referenced them:

// Before
using BarcodeStandard;
using SkiaSharp;

// After
using IronBarCode;

Step 3: Initialize License

Add license initialization at application startup:

IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";

For ASP.NET Core applications, put this in Program.cs before builder.Build(). For console applications, put it at the top of Main(). For class libraries called from other apps, initialize it wherever the host application starts.

Code Migration Examples

Basic Code128 Generation

The most common BarcodeLib pattern: create an instance, set properties, call Encode().

BarcodeLib Approach:

using BarcodeStandard;
using SkiaSharp;

public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
    var b = new Barcode();
    b.IncludeLabel = true;
    SKImage img = b.Encode(Type.Code128, trackingNumber, 400, 120);
    using var stream = File.OpenWrite(outputPath);
    img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);
}

IronBarcode Approach:

// NuGet: dotnet add package IronBarcode
using IronBarCode;

public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
    BarcodeWriter.CreateBarcode(trackingNumber, BarcodeEncoding.Code128)
        .ResizeTo(400, 120)
        .AddAnnotationTextBelowBarcode(trackingNumber)
        .SaveAsPng(outputPath);
}

The property-setter block collapses into a fluent chain. .AddAnnotationTextBelowBarcode() replaces b.IncludeLabel = true - it accepts the label string explicitly so you control what text appears below the bars. .ResizeTo() replaces the width/height arguments. For advanced generation options, see the IronBarcode barcode generation documentation.

Returning byte[] - the Common Web API Pattern

BarcodeLib 3.x returns an SKImage. Getting bytes out of it requires encoding through SkiaSharp into a MemoryStream. IronBarcode provides .ToPngBinaryData() directly.

BarcodeLib Approach:

using BarcodeStandard;
using SkiaSharp;
using System.IO;

public byte[] GetBarcodeBytes(string data)
{
    var b = new Barcode();
    SKImage img = b.Encode(Type.Code128, data, 300, 100);

    using var ms = new MemoryStream();
    img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
    return ms.ToArray();
}

IronBarcode Approach:

using IronBarCode;

public byte[] GetBarcodeBytes(string data)
{
    return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
        .ResizeTo(300, 100)
        .ToPngBinaryData();
}

The MemoryStream intermediate step is gone. .ToPngBinaryData() returns the byte[] directly, which is what HTTP response bodies, database BLOB columns, and file writers actually want.

Web API Controller Action

BarcodeLib Approach:

using BarcodeStandard;
using SkiaSharp;
using Microsoft.AspNetCore.Mvc;
using System.IO;

[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
    [HttpGet("{sku}")]
    public IActionResult GetLabel(string sku)
    {
        var b = new Barcode();
        SKImage img = b.Encode(Type.Code128, sku, 400, 120);

        using var ms = new MemoryStream();
        img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
        return File(ms.ToArray(), "image/png");
    }
}

IronBarcode Approach:

using IronBarCode;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
    [HttpGet("{sku}")]
    public IActionResult GetLabel(string sku)
    {
        byte[] pngBytes = BarcodeWriter.CreateBarcode(sku, BarcodeEncoding.Code128)
            .ResizeTo(400, 120)
            .ToPngBinaryData();

        return File(pngBytes, "image/png");
    }
}

The controller action shrinks by removing the MemoryStream block and the SkiaSharp encode step. The byte array flows directly from .ToPngBinaryData() into File().

QR Code Generation

BarcodeLib 3.x does not generate QR codes - the BarcodeStandard.Type enum contains no 2D entries. Projects that needed QR alongside BarcodeLib typically added a second library such as QRCoder. IronBarcode uses a dedicated QRCodeWriter class with additional options for logo embedding and styling.

BarcodeLib Approach:

// BarcodeLib has no QR Code (or any 2D) support.
// Generating a QR code from a BarcodeLib project required adding a
// second library such as QRCoder:
//
// using QRCoder;
// var qrGen = new QRCodeGenerator();
// var data = qrGen.CreateQrCode("https://example.com/product/42", QRCodeGenerator.ECCLevel.Q);
// // ... separate API, separate dependency to maintain.

IronBarcode Approach:

using IronBarCode;

// Basic QR code
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
    .SaveAsPng("qr.png");

// QR code with embedded brand logo (not possible with BarcodeLib)
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
    .AddBrandLogo("logo.png")
    .SaveAsPng("qr-branded.png");

QRCodeWriter.CreateQrCode() takes the data string and pixel size as parameters. Logo embedding, color customization, and error correction level are all available through chained methods. For QR code styling options, see the IronBarcode QR code documentation.

EAN-13 and UPC-A

These are common in retail inventory systems. The enum names change but the values are direct equivalents.

BarcodeLib Approach:

using BarcodeStandard;
using SkiaSharp;

// EAN-13 product barcode
var b = new Barcode();
SKImage ean = b.Encode(Type.Ean13, "5901234123457", 250, 100);
using (var s = File.OpenWrite("product-ean.png"))
    ean.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);

// UPC-A for US retail
SKImage upc = b.Encode(Type.UpcA, "012345678905", 250, 100);
using (var s = File.OpenWrite("product-upc.png"))
    upc.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);

IronBarcode Approach:

using IronBarCode;

// EAN-13 product barcode
BarcodeWriter.CreateBarcode("5901234123457", BarcodeEncoding.EAN13)
    .ResizeTo(250, 100)
    .SaveAsPng("product-ean.png");

// UPC-A for US retail
BarcodeWriter.CreateBarcode("012345678905", BarcodeEncoding.UPCA)
    .ResizeTo(250, 100)
    .SaveAsPng("product-upc.png");

Adding Barcode Reading (Net-New Capability)

BarcodeLib has no reading API. If your migration is driven by a new requirement to scan barcodes - from uploaded images, warehouse scanners, or scanned PDF documents - add this without a second library:

BarcodeLib Approach:

// BarcodeLib — no reading API exists
// Adding reading requires a separate library such as ZXing.Net:
// dotnet add package ZXing.Net
// using ZXing;
// var reader = new BarcodeReader();
// // ... separate API, separate dependency graph to manage

IronBarcode Approach:

using IronBarCode;

// Read a barcode from an image file
var results = BarcodeReader.Read("incoming-label.png");
foreach (var result in results)
{
    Console.WriteLine($"Value: {result.Value}");
    Console.WriteLine($"Format: {result.Format}");
}

// Read all barcodes from a multi-page PDF — no PDF library required
var pdfResults = BarcodeReader.Read("supplier-invoice.pdf");
foreach (var result in pdfResults)
{
    Console.WriteLine($"Page {result.PageNumber}: {result.Value}");
}

// Configure for high-volume scanning with multiple barcodes per image
var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true
};
var warehouseResults = BarcodeReader.Read("dock-scan.png", options);

BarcodeReader.Read() accepts image files, PDF files, streams, and System.Drawing.Bitmap objects. The ReadingSpeed enum lets you trade thoroughness for performance when scanning at volume. For reading configuration options, see the IronBarcode reading documentation.

Resolving the SkiaSharp Conflict

If your migration is driven by NU1608 warnings, verify the conflict is resolved after switching packages. After running dotnet remove package BarcodeLib and dotnet add package IronBarcode, rebuild and check the output:

dotnet build 2>&1 | grep -i "NU1608\|SkiaSharp"
SHELL

If no output appears, the conflict is resolved. If SkiaSharp warnings remain, they are coming from a different package in your dependency graph - IronBarcode is not the source.

BarcodeLib Approach:

<!-- Before — explicit overrides needed to pacify BarcodeLib -->
<ItemGroup>
  <PackageReference Include="BarcodeLib" Version="3.1.5" />
  <!-- Override required because MAUI converges on a newer SkiaSharp -->
  <PackageReference Include="SkiaSharp" Version="3.116.1" />
</ItemGroup>
XML

IronBarcode Approach:

<!-- After — clean, no conflict -->
<ItemGroup>
  <PackageReference Include="IronBarcode" Version="*" />
  <!-- SkiaSharp version is now only determined by MAUI's requirements -->
  <PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="3.116.1" />
</ItemGroup>
XML

BarcodeLib API to IronBarcode Mapping Reference

BarcodeLibIronBarcode
new Barcode()Static API - no instance required
b.Encode(Type.Code128, "data", w, h)BarcodeWriter.CreateBarcode("data", BarcodeEncoding.Code128)
b.IncludeLabel = true.AddAnnotationTextBelowBarcode("text")
Width/height passed to Encode().ResizeTo(width, height)
Returns SKImage.SaveAsPng(path) / .ToPngBinaryData()
Type.Code128BarcodeEncoding.Code128
Type.Code39BarcodeEncoding.Code39
Type.Ean13BarcodeEncoding.EAN13
Type.UpcABarcodeEncoding.UPCA
No QR support (1D only)BarcodeEncoding.QRCode (also QRCodeWriter)
Type.Itf14BarcodeEncoding.ITF14
Type.CodabarBarcodeEncoding.Codabar
No reading APIBarcodeReader.Read(path)
SkiaSharp version conflict in MAUINo conflicting dependencies
img.Encode(...).SaveTo(stream).SaveAsPng(path)
MemoryStream + SkiaSharp encode.ToPngBinaryData()

Common Migration Issues and Solutions

Issue 1: Type Enum Namespace Change

BarcodeLib 3.x: Uses BarcodeStandard.Type.Code128 (PascalCase, in the BarcodeStandard namespace). Older 2.x code may use BarcodeLib.TYPE.CODE128 (uppercase constants, BarcodeLib namespace) - both forms appear in real codebases mid-migration.

Solution: Replace with BarcodeEncoding.Code128. A grep across .cs files identifies all occurrences:

grep -rn "Type\.\|TYPE\." --include="*.cs" .
SHELL

Common replacements: Type.Code128 / TYPE.CODE128BarcodeEncoding.Code128, Type.Ean13 / TYPE.EAN13BarcodeEncoding.EAN13, Type.UpcA / TYPE.UPCABarcodeEncoding.UPCA, Type.Itf14 / TYPE.ITF14BarcodeEncoding.ITF14, Type.Codabar / TYPE.CODABARBarcodeEncoding.Codabar. BarcodeLib has no QR entry; any TYPE.QR_Code is dead code from a 2.x version or a fork - replace with BarcodeEncoding.QRCode (or use QRCodeWriter for styled output).

Issue 2: SKImage / Image Return Type

BarcodeLib: b.Encode() returns SKImage in 3.x and System.Drawing.Image in 2.x. Either type will not compile against IronBarcode.

Solution: Remove the intermediate image variable and replace the save logic with the appropriate terminal method on the fluent chain:

// Before (BarcodeLib 3.x)
SKImage img = b.Encode(Type.Code128, data, 300, 100);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return ms.ToArray();

// After
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
    .ResizeTo(300, 100)
    .ToPngBinaryData();

Search for SKImage img = b.Encode and Image img = b.Encode patterns to find all affected locations.

Issue 3: Width and Height Parameters

BarcodeLib: Width and height are positional arguments on Encode(Type, string, int, int) in 3.x, and separate b.Width / b.Height property assignments in older 2.x code. Either form needs porting.

Solution: The width/height become a single .ResizeTo(width, height) call chained after CreateBarcode(). Find the call sites:

# Find Encode() calls and any Width/Height property assignments
grep -n "\.Encode(\|\.Width = \|\.Height = " --include="*.cs" -r .
SHELL

Then replace the size arguments or property pair with a single .ResizeTo(width, height) chain call.

Issue 4: IncludeLabel Boolean Toggle

BarcodeLib: b.IncludeLabel = true is a boolean that automatically renders the encoded data string as the visible text below the bars.

Solution: Use .AddAnnotationTextBelowBarcode("text"), which takes the label string explicitly. In most cases, pass the same data string that was encoded into the barcode. If the original code used IncludeLabel = true and relied on BarcodeLib to auto-render the data as the label, pass that same data string explicitly:

BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
    .AddAnnotationTextBelowBarcode(data)  // pass the same string
    .SaveAsPng(outputPath);

Issue 5: SkiaSharp References Left After BarcodeLib Removal

BarcodeLib: Projects frequently accumulated explicit <PackageReference Include="SkiaSharp"> entries specifically to override BarcodeLib's version constraint. These become orphaned after BarcodeLib is removed.

Solution: After switching to IronBarcode, verify whether SkiaSharp is still needed by any other package before removing the explicit reference:

# Check if SkiaSharp is still referenced by anything other than the explicit override
dotnet list package --include-transitive 2>&1 | grep -i skia
SHELL

If SkiaSharp only appears due to the now-removed explicit <PackageReference>, remove that entry. If it is still pulled in by MAUI or another dependency, leave it - IronBarcode will not conflict with it.

BarcodeLib Migration Checklist

Pre-Migration Tasks

Run these searches before starting to understand the scope of changes needed:

# Find all BarcodeLib using directives (both 3.x BarcodeStandard and older BarcodeLib)
grep -rn "using BarcodeStandard\|using BarcodeLib" --include="*.cs" .

# Find Barcode object instantiation
grep -rn "new Barcode()" --include="*.cs" .

# Find Encode calls
grep -rn "\.Encode(" --include="*.cs" .

# Find Type enum usage (3.x PascalCase and 2.x uppercase)
grep -rn "Type\.Code128\|Type\.Ean13\|Type\.UpcA\|TYPE\.CODE128\|TYPE\.EAN13\|TYPE\.UPCA" --include="*.cs" .

# Find IncludeLabel usage
grep -rn "IncludeLabel" --include="*.cs" .

# Find the package references in project files
grep -rn "BarcodeLib" --include="*.csproj" .

# Find NU1608 evidence in lock files
grep -rn "NU1608" .
SHELL

Document all files affected by each search. Note which projects reference BarcodeLib directly and which inherit it transitively. Identify any explicit SkiaSharp version overrides added only to resolve BarcodeLib conflicts.

Code Update Tasks

  1. Run dotnet remove package BarcodeLib for each project
  2. Remove any explicit SkiaSharp version override references added only to fix BarcodeLib conflicts
  3. Run dotnet add package IronBarcode for each project
  4. Add IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"; to application startup in each project
  5. Replace using BarcodeStandard; (or using BarcodeLib; in older code) and using SkiaSharp; with using IronBarCode; across all .cs files
  6. Remove using System.Drawing.Imaging; imports left over from 2.x ImageFormat.Png usage
  7. Replace new Barcode() + Encode() calls with BarcodeWriter.CreateBarcode() fluent chains
  8. Replace Type.Code128 / TYPE.CODE128BarcodeEncoding.Code128 and all other enum values
  9. Replace width/height arguments (or 2.x b.Width = N; b.Height = M;) with .ResizeTo(N, M) chain calls
  10. Replace b.IncludeLabel = true; with .AddAnnotationTextBelowBarcode(data)
  11. Replace img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(...) with .SaveAsPng(path) or .ToPngBinaryData()
  12. Remove intermediate SKImage / Image variables and MemoryStream blocks where .ToPngBinaryData() replaces them
  13. Add barcode reading code where needed (BarcodeReader.Read())

Post-Migration Testing

  • Build the project and confirm zero NU1608 warnings remain in the restore output
  • Run dotnet build 2>&1 | grep -i "NU1608\|SkiaSharp" to verify the SkiaSharp conflict is fully resolved
  • Compare visual output of generated barcodes against known-good samples from BarcodeLib
  • Verify that QR codes decode correctly using a mobile scanner or the BarcodeReader.Read() method
  • Test EAN-13 and UPC-A barcodes against retail scanner hardware if applicable
  • Verify images display correctly in all output targets: file system, HTTP response, database storage
  • Test any PDF barcode reading scenarios using BarcodeReader.Read("file.pdf") on real documents
  • Confirm cross-platform builds succeed if the project targets Linux or macOS
  • Verify that MAUI builds complete without SkiaSharp binding errors on Android and iOS targets

Key Benefits of Migrating to IronBarcode

Barcode Reading Without a Second Library: The most immediate gain for teams that needed reading capability is eliminating the second-library dependency. BarcodeReader.Read() is in the same package, uses the same using IronBarCode; statement, and requires no additional NuGet installs. ZXing.Net and its own dependency graph are no longer part of the project.

No SkiaSharp Version Conflict: IronBarcode does not share the SkiaSharp dependency graph with application code. MAUI projects, Blazor projects, and any project where multiple packages converge on SkiaSharp can install IronBarcode without NU1608 warnings or runtime binding failures. The version negotiation that BarcodeLib introduced is gone.

Direct Byte Array Output: .ToPngBinaryData() returns byte[] at the end of the fluent chain. The MemoryStream intermediary that BarcodeLib required for byte array output is eliminated from every controller action, service method, and API handler that generates barcodes.

PDF Barcode Processing: BarcodeReader.Read() accepts PDF files natively. Applications that generate PDF documents with embedded barcodes can read those barcodes back without a separate PDF rendering library. The full chain - generation, PDF embedding, and reading - is handled within IronBarcode.

Commercial Support and SLA: IronBarcode is backed by Iron Software's commercial support model with a defined update cadence. When new .NET releases land or breaking changes appear in the .NET ecosystem, IronBarcode publishes compatibility updates on a timeline tied to the commercial SLA rather than community availability.

QR Code Generation Without a Second Library: QRCodeWriter supports logo embedding, color customization, and error correction level configuration through chained methods. BarcodeLib 3.x generates 1D symbologies only - projects that needed QR alongside BarcodeLib previously added a second library such as QRCoder. Teams whose QR code requirements have expanded gain these features inside the same package, without changing their generation workflow.

Curtis Chau
Technical Writer

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.

...
Read More

Related Articles

Key in blue circle

Get your free 30-day Trial Key instantly.

Your trial license will be sent to your email address

No limitations. 100% unlocked. No credit card.

bullet_checkedNo credit card or account creation requiredNo limitations. 100% unlocked. No credit card.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Book your free Live Demo
Booking Badge

Trusted by Millions of Engineers Worldwide

Iron Software's customer logos
Get Your No-Obligation Consult
Complete the form below or email sales@ironsoftware.com
Your details will always be kept confidential.
Trusted by Millions of Engineers Worldwide
Iron Software's customer logos
Get your free 30-day Trial Key instantly.
No credit card or account creation required