Como ler e escanear códigos de barras em C# usando .NET MAUI
Migrando de Biblioteca de código de barras para IronBarcode
Este guia fornece um caminho completo de migração do Biblioteca de código de barras para o IronBarcode para desenvolvedores .NET . Este guia aborda os motivos pelos quais as equipes fazem essa transição, a substituição passo a passo de pacotes, exemplos de migração de código para cada padrão comum do BarcodeLib, uma referência completa de mapeamento de API e uma lista de verificação estruturada para gerenciar a migração em toda a base de código.
Por que migrar do BarcodeLib?
Equipes que migraram do Biblioteca de código de barras para o IronBarcode relatam os seguintes problemas:
Sem API de leitura: O Biblioteca de código de barras nunca incluiu uma funcionalidade de leitura ou decodificação. Quando um projeto que gerava imagens de código de barras recebe um novo requisito para também digitalizar códigos de barras — seja a partir de imagens carregadas, scanners de armazém ou documentos de fornecedores — o Biblioteca de código de barras não consegue atendê-lo. A única opção é adicionar uma segunda biblioteca, como o ZXing .NET, o que introduz um segundo grafo de dependências e uma segunda superfície de API para manter juntamente com o BarcodeLib.
Conflito de Versão do SkiaSharp: Biblioteca de código de barras 3.x introduziu o SkiaSharp como um backend gráfico para substituir System.Drawing.Common. A biblioteca está vinculada a um intervalo de versões específico do SkiaSharp. Em projetos MAUI, projetos Blazor e qualquer projeto onde outra dependência também utilize o SkiaSharp, a versão resolvida frequentemente fica fora do intervalo esperado pelo BarcodeLib. Isso gera avisos NU1608 durante a restauração e, nos piores casos, falhas de vinculação de assembly em tempo de execução no dispositivo.
Sem suporte para PDF: Aplicativos que geram documentos PDF com códigos de barras incorporados — faturas, ordens de serviço, manifestos de remessa — às vezes precisam ler esses códigos de barras novamente durante o processamento subsequente. O Biblioteca de código de barras gera imagens de código de barras, mas não oferece suporte a PDF em nenhuma das extremidades. A extração de códigos de barras de um PDF com o Biblioteca de código de barras requer a renderização das páginas do PDF em imagens com uma biblioteca PDF separada e, em seguida, a passagem dessas imagens para uma biblioteca de leitura separada.
Etapa de Codificação de Fluxo para Saída de Array de Bytes: Biblioteca de código de barras 3.x retorna SKImage, que requer uma etapa de codificação SkiaSharp em um MemoryStream para produzir a saída byte[] que respostas HTTP, colunas de BLOBs de banco de dados e a maioria dos consumidores downstream realmente precisam.IronBarcode fornece .ToPngBinaryData() diretamente na cadeia de geração.
O problema fundamental
A arquitetura de geração exclusiva do Biblioteca de código de barras significa que adicionar qualquer capacidade de leitura força a inclusão de uma segunda biblioteca na pilha:
// 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.
// 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.
Imports BarcodeStandard
Imports SkiaSharp
Dim b = New Barcode()
Dim img As SKImage = b.Encode(Type.Code128, "PRODUCT-12345", 300, 100)
Using stream = File.OpenWrite("barcode.png")
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream)
End Using
IronBarcode lida com ambos no mesmo pacote com a mesma declaração using:
// 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: 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"
Imports IronBarCode
' Generate
BarcodeWriter.CreateBarcode("PRODUCT-12345", BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.SaveAsPng("barcode.png")
' Read back — same package, same namespace
Dim result = BarcodeReader.Read("barcode.png").First().Value
Console.WriteLine(result) ' "PRODUCT-12345"
IronBarcode vs BarcodeLib: Comparação de Recursos
| Recurso | Biblioteca de código de barras | IronBarcode |
|---|---|---|
| Geração de código de barras | Sim | Sim |
| Leitura/escaneamento de código de barras | Não | Sim (BarcodeReader.Read()) |
| Geração de código QR | Não (somente 1D) | Sim (avançado, com incorporação de logotipo) |
| Leitura de código de barras em PDF | Não | Sim (nativo, sem biblioteca extra) |
| Saída de geração de código de barras em PDF | Não | Sim |
| Dependência do SkiaSharp | Sim (risco de conflito de versões) | Não |
| Compatibilidade do projeto MAUI | Risco de conflito (NU1608) | Sem conflito |
| API encadeável fluente | Não | Sim |
byte[] saída diretamente |
Manual (via MemoryStream) |
.ToPngBinaryData() |
| Detecção de múltiplos códigos de barras | Não | Sim (ExpectMultipleBarcodes) |
| Ajuste da velocidade de leitura | N / D | Sim (ReadingSpeed enumeração) |
| Suporte para Linux/MacOS | Parcial (dependente de SkiaSharp) | Completo |
| Suporte a Docker/containers | Configuração necessária | Sim |
| Manutenção ativa | Sim (comunidade) | Sim (comercial) |
| Suporte comercial / SLA | Não | Sim |
| Licença | Apache 2.0 (gratuito) | $999–$5,999 perpétuo |
Guia rápido: Migração do Biblioteca de código de barras para o IronBarcode
A migração pode começar imediatamente com esses passos fundamentais.
Passo 1: Substitua o pacote NuGet
Remova o pacote Biblioteca de código de barras primeiro:
dotnet remove package BarcodeLib
dotnet remove package BarcodeLib
Se você não tiver certeza de como ele é referenciado, verifique o arquivo .csproj:
grep -n "BarcodeLib" YourProject.csproj
grep -n "BarcodeLib" YourProject.csproj
Remova todas as entradas relacionadas ao Biblioteca de código de barras <PackageReference>. Se você adicionou substituições <PackageReference Include="SkiaSharp"> explícitas para contornar os avisos NU1608 do BarcodeLib, remova-os também — após instalar o IronBarcode, avalie se o SkiaSharp ainda é necessário por outros motivos. Em seguida, instale o IronBarcode:
dotnet add package IronBarcode
dotnet add package IronBarcode
Etapa 2: Atualizar Namespaces
Substitua as diretivas using do Biblioteca de código de barras em cada arquivo que as referenciou:
// Before
using BarcodeStandard;
using SkiaSharp;
// After
using IronBarCode;
// Before
using BarcodeStandard;
using SkiaSharp;
// After
using IronBarCode;
Imports IronBarCode
Imports SkiaSharp
Etapa 3: Inicializar a licença
Adicionar inicialização de licença na inicialização do aplicativo:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
Para aplicativos ASP.NET Core, coloque isso em Program.cs antes de builder.Build(). Para aplicativos de console, coloque-o no topo de Main(). Para bibliotecas de classes chamadas por outros aplicativos, inicialize-as no mesmo local onde o aplicativo host é iniciado.
Exemplos de migração de código
Geração de código básico 128
O padrão mais comum do BarcodeLib: crie uma instância, defina propriedades, chame Encode().
Abordagem BarcodeLib:
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);
}
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);
}
Imports BarcodeStandard
Imports SkiaSharp
Public Sub GenerateShippingLabel(trackingNumber As String, outputPath As String)
Dim b As New Barcode()
b.IncludeLabel = True
Dim img As SKImage = b.Encode(Type.Code128, trackingNumber, 400, 120)
Using stream = File.OpenWrite(outputPath)
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream)
End Using
End Sub
Abordagem do IronBarcode:
// 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);
}
// 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);
}
Imports IronBarCode
Public Sub GenerateShippingLabel(trackingNumber As String, outputPath As String)
BarcodeWriter.CreateBarcode(trackingNumber, BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.AddAnnotationTextBelowBarcode(trackingNumber) _
.SaveAsPng(outputPath)
End Sub
O bloco de configuração de propriedades se transforma em uma cadeia fluente. .AddAnnotationTextBelowBarcode() substitui b.IncludeLabel = true — ele aceita a string do rótulo explicitamente para que você controle qual texto aparece abaixo das barras. .ResizeTo() substitui os argumentos de largura/altura. Para opções avançadas de geração, consulte a documentação de geração de código de barras do IronBarcode .
Retornando byte[] — o padrão comum da API Web
BarcodeLib 3.x retorna um SKImage. Extrair bytes requer codificação através do SkiaSharp em um MemoryStream.IronBarcode fornece .ToPngBinaryData() diretamente.
Abordagem BarcodeLib:
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();
}
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();
}
Imports BarcodeStandard
Imports SkiaSharp
Imports System.IO
Public Function GetBarcodeBytes(data As String) As Byte()
Dim b As New Barcode()
Dim img As SKImage = b.Encode(Type.Code128, data, 300, 100)
Using ms As New MemoryStream()
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms)
Return ms.ToArray()
End Using
End Function
Abordagem do IronBarcode:
using IronBarCode;
public byte[] GetBarcodeBytes(string data)
{
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
}
using IronBarCode;
public byte[] GetBarcodeBytes(string data)
{
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
}
Imports IronBarCode
Public Function GetBarcodeBytes(data As String) As Byte()
Return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.ToPngBinaryData()
End Function
A etapa intermediária MemoryStream desapareceu. .ToPngBinaryData() retorna o byte[] diretamente, que é o que os corpos de resposta HTTP, colunas de BLOBs de banco de dados e escritores de arquivos realmente querem.
Ação do controlador da API Web
Abordagem BarcodeLib:
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");
}
}
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");
}
}
Imports BarcodeStandard
Imports SkiaSharp
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
<ApiController>
<Route("api/labels")>
Public Class LabelsController
Inherits ControllerBase
<HttpGet("{sku}")>
Public Function GetLabel(sku As String) As IActionResult
Dim b As New Barcode()
Dim img As SKImage = b.Encode(Type.Code128, sku, 400, 120)
Using ms As New MemoryStream()
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms)
Return File(ms.ToArray(), "image/png")
End Using
End Function
End Class
Abordagem do IronBarcode:
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");
}
}
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");
}
}
Imports IronBarCode
Imports Microsoft.AspNetCore.Mvc
<ApiController>
<Route("api/labels")>
Public Class LabelsController
Inherits ControllerBase
<HttpGet("{sku}")>
Public Function GetLabel(sku As String) As IActionResult
Dim pngBytes As Byte() = BarcodeWriter.CreateBarcode(sku, BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.ToPngBinaryData()
Return File(pngBytes, "image/png")
End Function
End Class
A ação do controlador encolhe ao remover o bloco MemoryStream e a etapa de codificação SkiaSharp. O array de bytes flui diretamente de .ToPngBinaryData() em File().
Geração de código QR
BarcodeLib 3.x não gera códigos QR — a enumeração BarcodeStandard.Type não contém entradas 2D. Projetos que precisavam de QR junto com Biblioteca de código de barras tipicamente adicionaram uma segunda biblioteca como QRCoder.IronBarcode usa uma classe QRCodeWriter dedicada com opções adicionais para incorporação de logotipo e estilização.
Abordagem BarcodeLib:
// Biblioteca de código de barras has no QR Code (or any 2D) support.
// Generating a QR code from a Biblioteca de código de barras 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.
// Biblioteca de código de barras has no QR Code (or any 2D) support.
// Generating a QR code from a Biblioteca de código de barras 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.
' Biblioteca de código de barras has no QR Code (or any 2D) support.
' Generating a QR code from a Biblioteca de código de barras project required adding a
' second library such as QRCoder:
'
' Imports QRCoder
' Dim qrGen As New QRCodeGenerator()
' Dim data = qrGen.CreateQrCode("https://example.com/product/42", QRCodeGenerator.ECCLevel.Q)
' ' ... separate API, separate dependency to maintain.
Abordagem do IronBarcode:
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");
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");
Imports 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() considera a string de dados e o tamanho do pixel como parâmetros. A incorporação de logotipos, a personalização de cores e o nível de correção de erros estão disponíveis por meio de métodos encadeados. Para opções de estilo de código QR, consulte a documentação de código QR do IronBarcode .
EAN-13 e UPC-A
Esses são comuns em sistemas de controle de estoque no varejo. Os nomes das enumerações mudam, mas os valores são diretamente equivalentes.
Abordagem BarcodeLib:
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);
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);
Imports BarcodeStandard
Imports SkiaSharp
Imports System.IO
' EAN-13 product barcode
Dim b As New Barcode()
Dim ean As SKImage = b.Encode(Type.Ean13, "5901234123457", 250, 100)
Using s = File.OpenWrite("product-ean.png")
ean.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s)
End Using
' UPC-A for US retail
Dim upc As SKImage = b.Encode(Type.UpcA, "012345678905", 250, 100)
Using s = File.OpenWrite("product-upc.png")
upc.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s)
End Using
Abordagem do IronBarcode:
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");
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");
Imports 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")
Adicionando leitura de código de barras (Nova funcionalidade)
BarcodeLib não possui uma API de leitura. Se a sua migração for motivada por uma nova necessidade de leitura de códigos de barras — seja de imagens carregadas, leitores de código de barras de armazém ou documentos PDF digitalizados — adicione isso sem uma segunda biblioteca:
Abordagem BarcodeLib:
// Biblioteca de código de barras — 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
// Biblioteca de código de barras — 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
' Biblioteca de código de barras — no reading API exists
' Adding reading requires a separate library such as ZXing.Net:
' dotnet add package ZXing.Net
' Imports ZXing
' Dim reader As New BarcodeReader()
' ... separate API, separate dependency graph to manage
Abordagem do IronBarcode:
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);
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);
Imports IronBarCode
' Read a barcode from an image file
Dim results = BarcodeReader.Read("incoming-label.png")
For Each result In results
Console.WriteLine($"Value: {result.Value}")
Console.WriteLine($"Format: {result.Format}")
Next
' Read all barcodes from a multi-page PDF — no PDF library required
Dim pdfResults = BarcodeReader.Read("supplier-invoice.pdf")
For Each result In pdfResults
Console.WriteLine($"Page {result.PageNumber}: {result.Value}")
Next
' Configure for high-volume scanning with multiple barcodes per image
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True
}
Dim warehouseResults = BarcodeReader.Read("dock-scan.png", options)
BarcodeReader.Read() aceita arquivos de imagem, arquivos PDF, fluxos e objetos System.Drawing.Bitmap. A enumeração ReadingSpeed permite que você troque a minúcia pelo desempenho ao digitalizar em volume. Para opções de configuração de leitura, consulte a documentação de leitura do IronBarcode .
Resolvendo o conflito SkiaSharp
Se a sua migração for motivada por avisos NU1608, verifique se o conflito foi resolvido após a troca de pacotes. Após executar dotnet remove package BarcodeLib e dotnet add package IronBarcode, reconstrua e verifique a saída:
dotnet build 2>&1 | grep -i "NU1608\|SkiaSharp"
dotnet build 2>&1 | grep -i "NU1608\|SkiaSharp"
Se nenhuma saída for exibida, o conflito está resolvido. Se os avisos do SkiaSharp persistirem, eles estão vindo de um pacote diferente no seu grafo de dependências — o IronBarcode não é a origem.
Abordagem BarcodeLib:
<ItemGroup>
<PackageReference Include="BarcodeLib" Version="3.1.5" />
<PackageReference Include="SkiaSharp" Version="3.116.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BarcodeLib" Version="3.1.5" />
<PackageReference Include="SkiaSharp" Version="3.116.1" />
</ItemGroup>
Abordagem do IronBarcode:
<ItemGroup>
<PackageReference Include="IronBarcode" Version="*" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="3.116.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="IronBarcode" Version="*" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="3.116.1" />
</ItemGroup>
Referência de mapeamento da API Biblioteca de código de barras para IronBarcode
| Biblioteca de código de barras | IronBarcode |
|---|---|
new Barcode() |
API estática — nenhuma instância necessária |
b.Encode(Type.Code128, "data", w, h) |
BarcodeWriter.CreateBarcode("data", BarcodeEncoding.Code128) |
b.IncludeLabel = true |
.AddAnnotationTextBelowBarcode("text") |
Largura/altura passada para Encode() |
.ResizeTo(width, height) |
Retorna SKImage |
.SaveAsPng(path) / .ToPngBinaryData() |
Type.Code128 |
BarcodeEncoding.Code128 |
Type.Code39 |
BarcodeEncoding.Code39 |
Type.Ean13 |
BarcodeEncoding.EAN13 |
Type.UpcA |
BarcodeEncoding.UPCA |
| Sem suporte para QR (somente 1D) | BarcodeEncoding.QRCode (também QRCodeWriter) |
Type.Itf14 |
BarcodeEncoding.ITF14 |
Type.Codabar |
BarcodeEncoding.Codabar |
| Sem API de leitura | BarcodeReader.Read(path) |
| Conflito de versão do SkiaSharp no MAUI | Sem dependências conflitantes |
img.Encode(...).SaveTo(stream) |
.SaveAsPng(path) |
MemoryStream + codificação SkiaSharp |
.ToPngBinaryData() |
Problemas e soluções comuns em migrações
Problema 1: Mudança no Namespace do Enum do Tipo
BarcodeLib 3.x: Uses BarcodeStandard.Type.Code128 (PascalCase, in the BarcodeStandard namespace). O código 2.x mais antigo pode usar BarcodeLib.TYPE.CODE128 (constantes em maiúsculas, namespace BarcodeLib) — ambas as formas aparecem em bases de código reais em meio à migração.
Solução: Substitua por BarcodeEncoding.Code128. Um grep em arquivos .cs identifica todas as ocorrências:
grep -rn "Type\.\|TYPE\." --include="*.cs" .
grep -rn "Type\.\|TYPE\." --include="*.cs" .
Substituições comuns: Type.Code128 / TYPE.CODE128 → BarcodeEncoding.Code128, Type.Ean13 / TYPE.EAN13 → BarcodeEncoding.EAN13, Type.UpcA / TYPE.UPCA → BarcodeEncoding.UPCA, Type.Itf14 / TYPE.ITF14 → BarcodeEncoding.ITF14, Type.Codabar / TYPE.CO/DABAR → BarcodeEncoding.Codabar. Biblioteca de código de barras não tem entrada QR; qualquer TYPE.QR_Code é código morto de uma versão 2.x ou um fork — substitua por BarcodeEncoding.QRCode (ou use QRCodeWriter para saída estilizada).
Problema 2: Tipo de Retorno SKImage / Imagem
BarcodeLib: b.Encode() returns SKImage in 3.x and System.Drawing.Image in 2.x. Qualquer tipo não compilará contra IronBarcode.
Solução: Remova a variável de imagem intermediária e substitua a lógica de salvamento pelo método terminal apropriado na cadeia fluente:
// 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();
// 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();
Imports System.IO
' Before (BarcodeLib 3.x)
Dim img As SKImage = b.Encode(Type.Code128, data, 300, 100)
Using ms As New MemoryStream()
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms)
Return ms.ToArray()
End Using
' After
Return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.ToPngBinaryData()
Procure por padrões SKImage img = b.Encode e Image img = b.Encode para encontrar todos os locais afetados.
Problema 3: Parâmetros de Largura e Altura
BarcodeLib: Largura e altura são argumentos posicionais em Encode(Type, string, int, int) em 3.x e atribuições de propriedade b.Width / b.Height separados em código 2.x mais antigo. Qualquer forma precisa de portage das rotinas.
Solução: A largura/altura se torna uma única chamada .ResizeTo(width, height) encadeada após CreateBarcode(). Encontre os locais de chamada:
# Find Encode() calls and any Width/Height property assignments
grep -n "\.Encode(\|\.Width = \|\.Height = " --include="*.cs" -r .
# Find Encode() calls and any Width/Height property assignments
grep -n "\.Encode(\|\.Width = \|\.Height = " --include="*.cs" -r .
Em seguida, substitua os argumentos de tamanho ou o par de propriedades por uma chamada encadeada .ResizeTo(width, height) única.
Problema 4: Alternância booleana do IncludeLabel
BarcodeLib: b.IncludeLabel = true é um booleano que renderiza automaticamente a string de dados codificada como o texto visível abaixo das barras.
Solução: Use .AddAnnotationTextBelowBarcode("text"), que aceita a string do rótulo explicitamente. Na maioria dos casos, passe a mesma sequência de dados que foi codificada no código de barras. Se o código original usou IncludeLabel = true e confiou no Biblioteca de código de barras para auto-renderizar os dados como o rótulo, passe explicitamente essa mesma string de dados:
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.AddAnnotationTextBelowBarcode(data) // pass the same string
.SaveAsPng(outputPath);
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.AddAnnotationTextBelowBarcode(data) // pass the same string
.SaveAsPng(outputPath);
Dim barcodeWriter = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
barcodeWriter.AddAnnotationTextBelowBarcode(data) ' pass the same string
barcodeWriter.SaveAsPng(outputPath)
Problema 5: Referências ao SkiaSharp permanecem após a remoção do BarcodeLib
BarcodeLib: Os projetos frequentemente acumulavam entradas <PackageReference Include="SkiaSharp"> explícitas especificamente para substituir a restrição de versão do BarcodeLib. Esses arquivos ficam órfãos após a remoção do BarcodeLib.
Solução: Após migrar para o IronBarcode, verifique se o SkiaSharp ainda é necessário para algum outro pacote antes de remover a referência explícita:
# Check if SkiaSharp is still referenced by anything other than the explicit override
dotnet list package --include-transitive 2>&1 | grep -i skia
# Check if SkiaSharp is still referenced by anything other than the explicit override
dotnet list package --include-transitive 2>&1 | grep -i skia
Se o SkiaSharp aparecer apenas devido à entrada explícita <PackageReference> agora removida, remova essa entrada. Se ainda estiver sendo incluído pelo MAUI ou outra dependência, deixe como está — o IronBarcode não entrará em conflito com ele.
Lista de verificação para migração do BarcodeLib
Tarefas pré-migração
Antes de começar a entender a dimensão das mudanças necessárias, faça estas buscas:
# Find all Biblioteca de código de barras 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" .
# Find all Biblioteca de código de barras 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" .
Documente todos os arquivos afetados por cada pesquisa. Observe quais projetos fazem referência direta à Biblioteca de código de barras e quais a herdam transitivamente. Identifique quaisquer alterações explícitas na versão do SkiaSharp adicionadas apenas para resolver conflitos com o BarcodeLib.
Tarefas de atualização de código
- Execute
dotnet remove package BarcodeLibpara cada projeto - Remova quaisquer referências explícitas de substituição de versão do SkiaSharp adicionadas apenas para corrigir conflitos com o BarcodeLib.
- Execute
dotnet add package IronBarcodepara cada projeto - Adicione
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";à inicialização do aplicativo em cada projeto - Substitua
using BarcodeStandard;(ouusing BarcodeLib;em código mais antigo) eusing SkiaSharp;porusing IronBarCode;em todos os arquivos.cs - Remova as importações
using System.Drawing.Imaging;sobrando do usoImageFormat.Pngda versão 2.x - Substitua chamadas
new Barcode()+Encode()por cadeias fluentesBarcodeWriter.CreateBarcode() - Substitua
Type.Code128/TYPE.CODE128→BarcodeEncoding.Code128e todos os outros valores de enumeração - Substitua os argumentos de largura/altura (ou 2.x
b.Width = N; b.Height = M;) with.ResizeTo(N, M)chamadas encadeadas - Substitua
b.IncludeLabel = true;por.AddAnnotationTextBelowBarcode(data) - Substitua
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(...)por.SaveAsPng(path)ou.ToPngBinaryData() - Remova variáveis intermediárias
SKImage/Imagee blocosMemoryStreamonde.ToPngBinaryData()os substitui - Adicione código de leitura de código de barras onde necessário (
BarcodeReader.Read())
Testes pós-migração
- Compile o projeto e confirme se não restam avisos NU1608 na saída da restauração.
- Execute
dotnet build 2>&1 | grep -i "NU1608\|SkiaSharp"para verificar se o conflito do SkiaSharp foi totalmente resolvido - Compare a saída visual dos códigos de barras gerados com amostras de boa qualidade do BarcodeLib.
- Verifique se os códigos QR decodificam corretamente usando um scanner móvel ou o método
BarcodeReader.Read() - Testar os códigos de barras EAN-13 e UPC-A em leitores de código de barras de lojas, se aplicável.
- Verificar se as imagens são exibidas corretamente em todos os destinos de saída: sistema de arquivos, resposta HTTP, armazenamento em banco de dados.
- Teste qualquer cenário de leitura de código de barras em PDF usando
BarcodeReader.Read("file.pdf")em documentos reais - Confirme se as compilações multiplataforma foram bem-sucedidas caso o projeto tenha como alvo Linux ou macOS.
- Verificar se as compilações do MAUI são concluídas sem erros de vinculação do SkiaSharp em dispositivos Android e iOS.
Principais benefícios da migração para o IronBarcode
Leitura de código de barras sem uma segunda biblioteca: O ganho mais imediato para as equipes que precisam de capacidade de leitura é a eliminação da dependência de uma segunda biblioteca. BarcodeReader.Read() está no mesmo pacote, usa a mesma declaração using IronBarCode; e não requer instalações adicionais do NuGet. O ZXing .NET e seu próprio grafo de dependências não fazem mais parte do projeto.
Sem conflito de versão do SkiaSharp: o IronBarcode não compartilha o grafo de dependências do SkiaSharp com o código do aplicativo. Projetos MAUI, projetos Blazor e qualquer projeto onde vários pacotes convergem para o SkiaSharp podem instalar o IronBarcode sem avisos NU1608 ou falhas de vinculação em tempo de execução. A negociação de versões introduzida pelo Biblioteca de código de barras foi removida.
Saída Direta de Array de Bytes: .ToPngBinaryData() retorna byte[] no final da cadeia fluente. O intermediário MemoryStream que Biblioteca de código de barras exigia para a saída de array de bytes é eliminado de cada ação de controlador, método de serviço e manipulador API que gera códigos de barras.
Processamento de Códigos de Barras em PDF: BarcodeReader.Read() aceita arquivos PDF de forma nativa. Aplicativos que geram documentos PDF com códigos de barras incorporados podem ler esses códigos de barras sem a necessidade de uma biblioteca de renderização de PDF separada. Todo o processo — geração, incorporação em PDF e leitura — é gerenciado dentro do IronBarcode.
Suporte Comercial e SLA:IronBarcode é apoiado pelo modelo de suporte comercial da Iron Software com uma cadência de atualização definida. Quando novas versões do .NET são lançadas ou alterações disruptivas aparecem no ecossistema .NET,IronBarcode publica atualizações de compatibilidade em uma linha do tempo vinculada ao SLA comercial em vez de disponibilidade comunitária.
Geração de Código QR Sem uma Segunda Biblioteca: QRCodeWriter suporta incorporação de logotipo, personalização de cores e configuração de nível de correção de erros através de métodos encadeados. Biblioteca de código de barras 3.x gera apenas simbologias 1D — projetos que precisavam de QR junto com Biblioteca de código de barras anteriormente adicionavam uma segunda biblioteca como QRCoder. Equipes cujos requisitos de código QR foram ampliados ganham esses recursos dentro do mesmo pacote, sem alterar seu fluxo de trabalho de geração.
Perguntas frequentes
Por que devo migrar do BarcodeLib para o IronBarcode?
Entre os motivos comuns estão a simplificação do licenciamento (removendo a complexidade do SDK e da chave de tempo de execução), a eliminação dos limites de taxa de transferência, a obtenção de suporte nativo para PDF, a melhoria da implantação em Docker/CI/CD e a redução do código repetitivo da API em produção.
Como faço para substituir as chamadas da API BarcodeLib pelo IronBarcode?
Substitua o código padrão de criação de instâncias e licenciamento por `IronBarCode.License.LicenseKey = "key"`. Substitua as chamadas de leitura por `BarcodeReader.Read(path)` e as chamadas de gravação por `BarcodeWriter.CreateBarcode(data, encoding)`. Os métodos estáticos não exigem gerenciamento de instâncias.
Quanta alteração de código ocorre ao migrar do BarcodeLib para o IronBarcode?
A maioria das migrações resulta em menos linhas de código. O código repetitivo de licenciamento, os construtores de instância e a configuração explícita de formato são removidos. As operações principais de leitura/gravação são mapeadas para equivalentes mais curtos em IronBarcode, com objetos de resultado mais limpos.
Preciso manter o BarcodeLib e o IronBarcode instalados durante a migração?
Não. A maioria das migrações são substituições diretas, e não operações paralelas. Migre uma classe de serviço por vez, substitua a referência do NuGet e atualize os padrões de instanciação e chamada de API antes de passar para a próxima classe.
Qual é o nome do pacote NuGet para IronBarcode?
O pacote é 'IronBarCode' (com B e C maiúsculos). Instale-o com 'Install-Package IronBarCode' ou 'dotnet add package IronBarCode'. A diretiva using no código é 'using IronBarCode;'.
Como o IronBarcode simplifica a implantação do Docker em comparação com o BarcodeLib?
IronBarcode é um pacote NuGet sem arquivos SDK externos ou configuração de licença montada. No Docker, defina a variável de ambiente IRONBARCODE_LICENSE_KEY e o pacote cuidará da validação da licença na inicialização.
O IronBarcode detecta automaticamente todos os formatos de código de barras após a migração do BarcodeLib?
Sim. O IronBarcode detecta automaticamente a simbologia em todos os formatos suportados. A enumeração explícita de BarcodeTypes não é necessária. Se o formato já for conhecido e o desempenho for importante, o BarcodeReaderOptions permite restringir o espaço de busca como uma otimização.
O IronBarcode consegue ler códigos de barras de PDFs sem uma biblioteca separada?
Sim. O método `BarcodeReader.Read("document.pdf")` processa arquivos PDF nativamente. Os resultados incluem o número da página, o formato, o valor e a confiança de cada código de barras encontrado. Não é necessária nenhuma etapa externa de renderização de PDF.
Como o IronBarcode lida com o processamento paralelo de códigos de barras?
Os métodos estáticos do IronBarcode são sem estado e thread-safe. Use Parallel.ForEach diretamente em listas de arquivos sem gerenciamento de instâncias por thread. BarcodeReaderOptions.MaxParallelThreads controla o orçamento interno de threads.
Quais propriedades de resultado são alteradas ao migrar do BarcodeLib para o IronBarcode?
Renomeações comuns: BarcodeValue torna-se Value, BarcodeType torna-se Format. Os resultados do IronBarcode também incluem Confidence e PageNumber. Uma função de busca e substituição em toda a solução lida com as renomeações no código de processamento de resultados existente.
Como configuro o licenciamento do IronBarcode em um pipeline de CI/CD?
Armazene IRONBARCODE_LICENSE_KEY como um segredo de pipeline e atribua IronBarCode.License.LicenseKey no código de inicialização do aplicativo. Um único segredo abrange todos os ambientes, incluindo desenvolvimento, teste, homologação e produção.
O IronBarcode suporta a geração de códigos QR com estilos personalizados?
Sim. O método QRCodeWriter.CreateQrCode() suporta cores personalizadas através do método ChangeBarCodeColor(), incorporação de logotipo através do método AddBrandLogo(), níveis configuráveis de correção de erros e múltiplos formatos de saída, incluindo PNG, JPG, PDF e fluxo de dados.

