# How to Validate Barcode Checksums and Use Format-Aware Reading in C#
Barcode checksums help detect substitution errors. For example, a single transposed digit in an EAN-13 label can send a package to the wrong warehouse. Format-aware reading provides an additional validation layer by restricting the decoder to expected symbologies. This approach reduces false positives from background noise and shortens scan time by skipping unnecessary format detectors.
IronBarcode performs checksum verification automatically during decoding. Each symbology's check-digit algorithm runs by default, and barcodes that fail are discarded before results are returned. The `BarcodeReaderOptions.ExpectBarcodeTypes` property limits reads to specific formats, while `RemoveFalsePositive` adds a secondary scan for ambiguous reads.
This guide explains how to validate barcode checksums, constrain reads to expected formats, and combine both techniques into a layered quality gate using `BarcodeReaderOptions`.
*as-heading:2(Quickstart: Validate Barcodes with Checksum and Format Constraints)*
Configure `BarcodeReaderOptions` with `ExpectBarcodeTypes` and `RemoveFalsePositive` to constrain reads to expected symbologies with automatic checksum verification.
```cs
using IronBarCode;
// Format-constrained read with false-positive removal.
// Limit the decoder to EAN-13 and Code128; checksums are
// validated automatically and failures are silently discarded.
var options = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.EAN13 | BarcodeEncoding.Code128,
RemoveFalsePositive = true,
Speed = ReadingSpeed.Balanced
};
BarcodeResults results = BarcodeReader.Read("label.png", options);
```
<div class="hsg-featured-snippet">
<h3>Minimal Workflow (5 steps)</h3>
<ol>
<li><a class="js-modal-open" data-modal-id="trial-license-after-download" href="https://nuget.org/packages/BarCode/">Download the IronBarcode library from NuGet</a></li>
<li>Create a <code>BarcodeReaderOptions</code> instance</li>
<li>Set <code>ExpectBarcodeTypes</code> to the symbologies present in the pipeline</li>
<li>Enable <code>RemoveFalsePositive</code> for secondary verification</li>
<li>Call <code>BarcodeReader.Read</code> to decode, checksums are validated automatically during decode</li>
</ol>
</div>
## How to Validate Barcode Checksums?
IronBarcode validates checksums during decoding according to each symbology's specification. For example, when reading an EAN-13 barcode, the Mod10 check digit is calculated from the first 12 digits and compared to the 13th. If the digits do not match, the barcode is silently rejected and does not appear in the `BarcodeResults` collection. This approach applies to all formats with a mandatory check digit, including UPC-A, UPC-E, EAN-8, Code128, ITF, and others.
This implicit model differs from libraries that expose an explicit toggle. The table below compares the two approaches:
<div class="content__data-table" data-content-table>
<table>
<caption>Checksum Validation Model Comparison: IronBarcode vs. Aspose.BarCode</caption>
<thead>
<tr><th>Aspect</th><th>IronBarcode</th><th>Aspose.BarCode</th></tr>
</thead>
<tbody>
<tr><td>Validation trigger</td><td>Automatic; runs during every decode</td><td>Explicit: <code>ChecksumValidation.On</code> / <code>Off</code> / <code>Default</code></td></tr>
<tr><td>Developer action required</td><td>None; invalid barcodes are excluded from results</td><td>Set <code>BarcodeSettings.ChecksumValidation</code> before reading</td></tr>
<tr><td>Checksum disable</td><td>Not exposed; checksums are always enforced for mandatory formats</td><td>Yes; <code>ChecksumValidation.Off</code> skips verification</td></tr>
<tr><td>Optional-checksum formats (Code39)</td><td>Uses <code>Confidence</code> + <code>RemoveFalsePositive</code> to filter low-quality reads</td><td>Explicitly enable with <code>EnableChecksum.Yes</code></td></tr>
<tr><td>Failure behavior</td><td>Barcode silently omitted from results</td><td>Barcode may appear with a separate checksum value for manual inspection</td></tr>
</tbody>
</table>
</div>
For symbologies with optional checksums, such as Code39, the library uses confidence scoring and `RemoveFalsePositive` instead of a checksum toggle.
### Input
A Code128 warehouse rack label (success path) and a blank image with no barcode (failure path).
<div style="display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap;">
<div class="content-img-align-center" style="width: 45%;">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/input-warehouse-rack.png"
alt="Code128 barcode encoding RACK-A1-LOT-7382 used as the warehouse rack scan input"
class="img-responsive add-shadow" />
<p style="color: #181818; font-style: italic; text-align: center;">warehouse-rack.png (success path)</p>
</div>
</div>
<div class="content-img-align-center" style="width: 45%;">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/input-blank-no-barcode.png"
alt="Blank white image with no barcode to trigger the empty result path"
class="img-responsive add-shadow" />
<p style="color: #181818; font-style: italic; text-align: center;">blank-no-barcode.png (failure path - no barcode present)</p>
</div>
</div>
</div>
```cs
using IronBarCode;
// Constrain reads to 1D formats and enable secondary verification.
// ConfidenceThreshold rejects decodes where the ML detector falls below 85%,
// acting as a quality gate for optional-checksum symbologies like Code39.
var options = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional,
RemoveFalsePositive = true,
ConfidenceThreshold = 0.85,
Speed = ReadingSpeed.Detailed
};
BarcodeResults results = BarcodeReader.Read("warehouse-rack.png", options);
foreach (BarcodeResult result in results)
{
// Each result has passed checksum validation (mandatory formats)
// and the 85% confidence threshold, so no additional filtering is needed.
Console.WriteLine($"[{result.BarcodeType}] {result.Value} page={result.PageNumber}");
}
if (results.Count == 0)
{
Console.Error.WriteLine("No valid barcodes found. Possible causes:");
Console.Error.WriteLine(" - Check digit mismatch (barcode silently rejected)");
Console.Error.WriteLine(" - Confidence below 85% threshold");
Console.Error.WriteLine(" - Format not in ExpectBarcodeTypes");
}
```
### Output
#### Success Path
<div class="content-img-align-center">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/output-checksum-validation-success.webp"
alt="Console output showing Code128 RACK-A1-LOT-7382 decoded above the confidence threshold"
class="img-responsive add-shadow" />
</div>
</div>
The warehouse rack barcode came back as `RACK-A1-LOT-7382` on page 0. It cleared the 85% confidence threshold and passed checksum validation, so it shows up in `BarcodeResults`.
#### Failure Path
<div class="content-img-align-center">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/output-checksum-validation-failure.webp"
alt="Console output showing WARN no valid barcodes found for the blank image input"
class="img-responsive add-shadow" />
</div>
</div>
Raising `ConfidenceThreshold` above its 0.7 default tightens this gate further for optional-checksum symbologies such as Code39.
With checksum validation covered, the next step is restricting the reader to the barcode formats your pipeline expects.
---
## How to Use Format-Aware Barcode Reading?
The `BarcodeEncoding` enum is a flags type, allowing multiple formats to be combined using the bitwise OR operator. Setting `ExpectBarcodeTypes` limits the reader to those formats and skips detection for others.
<div class="content__data-table" data-content-table>
<table>
<caption>Common BarcodeEncoding Values</caption>
<thead>
<tr><th>Value</th><th>Category</th><th>Description</th><th>Checksum</th></tr>
</thead>
<tbody>
<tr><td><code>BarcodeEncoding.All</code></td><td>Meta</td><td>All supported formats (default behavior)</td><td>Per-format</td></tr>
<tr><td><code>BarcodeEncoding.AllOneDimensional</code></td><td>Meta</td><td>All linear (1D) formats including stacked</td><td>Per-format</td></tr>
<tr><td><code>BarcodeEncoding.AllTwoDimensional</code></td><td>Meta</td><td>All matrix/grid (2D) formats</td><td>Per-format</td></tr>
<tr><td><code>BarcodeEncoding.Code128</code></td><td>1D</td><td>High-density alphanumeric (logistics, shipping)</td><td>Mandatory (weighted Mod103)</td></tr>
<tr><td><code>BarcodeEncoding.EAN13</code></td><td>1D</td><td>Retail product identification, 13 digits</td><td>Mandatory (Mod10)</td></tr>
<tr><td><code>BarcodeEncoding.QRCode</code></td><td>2D</td><td>High-capacity matrix (URLs, structured data)</td><td>Reed-Solomon ECC</td></tr>
<tr><td><code>BarcodeEncoding.Code39</code></td><td>1D</td><td>Alphanumeric (defense, automotive)</td><td>Optional (Mod43)</td></tr>
<tr><td><code>BarcodeEncoding.UPCA</code></td><td>1D</td><td>North American retail, 12 digits</td><td>Mandatory (Mod10)</td></tr>
<tr><td><code>BarcodeEncoding.DataMatrix</code></td><td>2D</td><td>Compact matrix (electronics, pharma)</td><td>Reed-Solomon ECC</td></tr>
<tr><td><code>BarcodeEncoding.PDF417</code></td><td>2D</td><td>Stacked (ID cards, transport)</td><td>Reed-Solomon ECC</td></tr>
</tbody>
</table>
</div>
Beyond speed, constraining the format set acts as a validation gate: barcodes of any unlisted symbology are excluded from results even if physically present in the image.
### Input
A Code128 shipping label (success path) and a QR code that does not match the Code128-only constraint (failure path).
<div style="display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap;">
<div class="content-img-align-center" style="width: 45%;">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/input-shipping-label.png"
alt="Code128 barcode encoding SHIP-2024-00438 used as the shipping label input"
class="img-responsive add-shadow" />
<p style="color: #181818; font-style: italic; text-align: center;">shipping-label.png (success path - Code128 matches constraint)</p>
</div>
</div>
<div class="content-img-align-center" style="width: 45%;">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/input-qr-format-mismatch.png"
alt="QR code used as the format-mismatch failure path for the Code128-only constrained read"
class="img-responsive add-shadow" />
<p style="color: #181818; font-style: italic; text-align: center;">qr-format-mismatch.png (failure path - QR rejected by Code128-only filter)</p>
</div>
</div>
</div>
```cs
using IronBarCode;
// Constrained read: only Code128 barcodes are returned.
// Faster because the reader skips all other format detectors.
var constrainedOptions = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.Code128,
Speed = ReadingSpeed.Faster,
ExpectMultipleBarcodes = false
};
// Broad read: all supported formats are scanned.
// Useful for verification or when the image format is unknown.
var broadOptions = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.All,
Speed = ReadingSpeed.Detailed,
ExpectMultipleBarcodes = true
};
string imagePath = "shipping-label.png";
BarcodeResults constrained = BarcodeReader.Read(imagePath, constrainedOptions);
Console.WriteLine($"Constrained: {constrained.Count} Code128 barcode(s) found");
BarcodeResults broad = BarcodeReader.Read(imagePath, broadOptions);
Console.WriteLine($"Broad: {broad.Count} barcode(s) found across all formats");
foreach (BarcodeResult result in broad)
{
Console.WriteLine($" [{result.BarcodeType}] {result.Value}");
}
```
### Output
#### Success Path
<div class="content-img-align-center">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/output-format-aware-success.webp"
alt="Console output showing constrained read finding 1 Code128 barcode and broad read confirming it"
class="img-responsive add-shadow" />
</div>
</div>
The shipping label has a value of `SHIP-2024-00438`. The constrained read picks it up straight away since Code128 is what the filter expects, and the broad read confirms the same result across all formats.
#### Failure Path
<div class="content-img-align-center">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/output-format-aware-failure.webp"
alt="Console output showing constrained read returning 0 results for a QR code image"
class="img-responsive add-shadow" />
</div>
</div>
Empty results from a constrained read are a validation signal, not an error; log the discrepancy for review.
For pipelines that mix barcode types (e.g., a packing slip with both an EAN-13 product code and a Code128 tracking number), combine the expected formats:
```cs
using IronBarCode;
// Combine multiple format flags with | to scan for more than one symbology
// in a single pass. Each BarcodeResult.BarcodeType identifies which format
// was decoded, enabling downstream routing logic per symbology.
var options = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.EAN13 | BarcodeEncoding.Code128,
ExpectMultipleBarcodes = true
};
```
Each returned `BarcodeResult.BarcodeType` identifies which format was decoded, enabling downstream routing.
### Which Symbologies Support Checksum Validation?
Not all barcode formats use checksums in the same way. The following table maps common symbologies to their error-detection characteristics, which informs how aggressively to set `ConfidenceThreshold` and `RemoveFalsePositive` for each format:
<div class="content__data-table" data-content-table>
<table>
<caption>Checksum Characteristics by Symbology</caption>
<thead>
<tr><th>Symbology</th><th>Checksum Type</th><th>Mandatory?</th><th>Recommendation</th></tr>
</thead>
<tbody>
<tr><td>EAN-13 / EAN-8</td><td>Mod10</td><td>Yes</td><td>Default settings sufficient; checksum always enforced</td></tr>
<tr><td>UPC-A / UPC-E</td><td>Mod10</td><td>Yes</td><td>Default settings sufficient; check digit auto-corrected on write</td></tr>
<tr><td>Code128</td><td>Weighted Mod103</td><td>Yes</td><td>Default settings sufficient; mandatory per specification</td></tr>
<tr><td>Code39</td><td>Mod43</td><td>Optional</td><td>Raise <code>ConfidenceThreshold</code> to 0.8+ and enable <code>RemoveFalsePositive</code></td></tr>
<tr><td>Codabar</td><td>Mod16</td><td>Optional</td><td>Same as Code39; use confidence as the quality gate</td></tr>
<tr><td>ITF</td><td>Mod10</td><td>Optional</td><td>Enable <code>RemoveFalsePositive</code> for interleaved formats</td></tr>
<tr><td>QRCode / DataMatrix</td><td>Reed-Solomon ECC</td><td>Always</td><td>Structural error correction; no additional configuration needed</td></tr>
<tr><td>PDF417</td><td>Reed-Solomon ECC</td><td>Always</td><td>Same as QR/DataMatrix; error correction is inherent</td></tr>
</tbody>
</table>
</div>
For 2D symbologies such as QR, DataMatrix, and PDF417, error correction is integrated into the encoding structure. These formats can recover from partial damage without depending on a simple check digit. The `ConfidenceThreshold` still applies during the ML detection phase, while the decode step benefits from the symbology's built-in redundancy.
Now that both techniques are understood, let's combine them into a single production-ready validation pattern.
---
## How to Combine Checksums with Format Constraints?
The production-ready pattern sets `ExpectBarcodeTypes`, `RemoveFalsePositive`, `ConfidenceThreshold`, and `Speed` in a single `BarcodeReaderOptions` object. Together they form a layered gate: format constraints narrow the search space, checksum validation ensures data integrity, confidence thresholding filters marginal decodes, and false-positive removal adds a secondary verification pass.
### Input
Three POS scan barcodes from the `pos-scans/` directory used as the success path: two EAN-13 and one UPC-A. A Code128 warehouse rack label is used as the failure path - the EAN-13/UPC-A constraint rejects it and logs a `REJECT` line.
<div style="display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap;">
<div class="content-img-align-center" style="width: 22%;">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/input-pos-scan-1.png"
alt="EAN-13 barcode encoding 5901234123471 used as POS scan input 1"
class="img-responsive add-shadow" />
<p style="color: #181818; font-style: italic; text-align: center;">pos-scan-1.png (success)</p>
</div>
</div>
<div class="content-img-align-center" style="width: 22%;">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/input-pos-scan-2.png"
alt="EAN-13 barcode encoding 4006381333931 used as POS scan input 2"
class="img-responsive add-shadow" />
<p style="color: #181818; font-style: italic; text-align: center;">pos-scan-2.png (success)</p>
</div>
</div>
<div class="content-img-align-center" style="width: 22%;">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/input-pos-scan-3.png"
alt="UPC-A barcode encoding 012345678905 used as POS scan input 3"
class="img-responsive add-shadow" />
<p style="color: #181818; font-style: italic; text-align: center;">pos-scan-3.png (success)</p>
</div>
</div>
<div class="content-img-align-center" style="width: 22%;">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/input-warehouse-rack.png"
alt="Code128 barcode encoding RACK-A1-LOT-7382 used as the combined-validation failure path input"
class="img-responsive add-shadow" />
<p style="color: #181818; font-style: italic; text-align: center;">warehouse-rack.png (failure - Code128 rejected)</p>
</div>
</div>
</div>
```cs
using IronBarCode;
// Layered validation for retail POS: EAN-13, UPC-A, and UPC-E only.
// Each property adds a distinct filter to the read pipeline.
var options = new BarcodeReaderOptions
{
// Layer 1: format constraint, accept only retail symbologies
ExpectBarcodeTypes = BarcodeEncoding.EAN13 | BarcodeEncoding.UPCA | BarcodeEncoding.UPCE,
// Layer 2: confidence threshold, reject decodes below 80%
ConfidenceThreshold = 0.8,
// Layer 3: false-positive removal, runs a secondary verification pass
RemoveFalsePositive = true,
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = false,
// Require 3 agreeing scan lines to reduce phantom reads from noisy images
MinScanLines = 3
};
string[] scanFiles = Directory.GetFiles("pos-scans/", "*.png");
foreach (string file in scanFiles)
{
BarcodeResults results = BarcodeReader.Read(file, options);
if (results.Count == 0)
{
// No barcode passed all validation layers
Console.Error.WriteLine($"REJECT {Path.GetFileName(file)}: "
+ "no valid EAN-13/UPC barcode (checksum, confidence, or format mismatch)");
continue;
}
BarcodeResult primary = results.First();
// Post-read assertion: verify the decoded format matches expectations.
// ExpectBarcodeTypes already constrains the reader; this check documents
// intent and surfaces unexpected results during future changes.
if (primary.BarcodeType != BarcodeEncoding.EAN13
&& primary.BarcodeType != BarcodeEncoding.UPCA
&& primary.BarcodeType != BarcodeEncoding.UPCE)
{
Console.Error.WriteLine($"UNEXPECTED FORMAT {Path.GetFileName(file)}: "
+ $"got {primary.BarcodeType}, expected EAN-13/UPC");
continue;
}
Console.WriteLine($"OK {Path.GetFileName(file)}: [{primary.BarcodeType}] {primary.Value}");
}
```
### Output
#### Success Path
<div class="content-img-align-center">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/output-combined-validation-success.webp"
alt="Console output showing all 3 POS scan barcodes accepted with OK status and decoded values"
class="img-responsive add-shadow" />
</div>
</div>
All three POS scan images made it through. The reader returned values of `5901234123471`, `4006381333931`, and `012345678905`. Each one matched the `EAN13 | UPCA | UPCE` filter, had a valid Mod10 checksum, and confidence was above 0.8.
#### Failure Path
<div class="content-img-align-center">
<div class="center-image-wrapper">
<img src="/static-assets/barcode/how-to/checksum-and-format-validation/output-combined-validation-failure.webp"
alt="Console output showing warehouse-rack Code128 barcode rejected by the EAN-13/UPC-A filter"
class="img-responsive add-shadow" />
</div>
</div>
Setting `MinScanLines` to 3 increases the minimum number of agreeing scan lines required for a 1D barcode to be valid; the default is 2. Raising this value lowers the risk of phantom reads from noisy scan lines but may cause thin or partially damaged barcodes to be missed. In retail POS environments with clean printed labels, a value of 3 is a conservative choice that strengthens validation without affecting throughput.
The post-read `BarcodeType` assertion is defense-in-depth: `ExpectBarcodeTypes` already filters, but the explicit check documents intent and catches configuration drift without runtime cost. For speed tuning, `ReadingSpeed.Faster` suits clean machine-printed labels; `Detailed` and `ExtremeDetail` recover damaged or poorly lit barcodes at the cost of longer scan times.
---
## What Are My Next Steps?
This article covered IronBarcode's implicit checksum validation model, the `BarcodeEncoding` flags enum for format-constrained reads, and a combined validation pattern using `ExpectBarcodeTypes`, `ConfidenceThreshold`, `RemoveFalsePositive`, and `MinScanLines` as layered quality gates.
For further reading, explore these resources:
- [IronBarcode Tutorials - Reading Barcodes](https://ironsoftware.com/csharp/barcode/tutorials/reading-barcodes/) for end-to-end reading walkthroughs.
- [False Positive Prevention](https://ironsoftware.com/csharp/barcode/troubleshooting/false-positives/) for the `RemoveFalsePositive` mechanism in detail.
- [Confidence Threshold Examples](https://ironsoftware.com/csharp/barcode/examples/confidence-threshold/) for ML-based detection tuning.
- [Output Data Formats](https://ironsoftware.com/csharp/barcode/how-to/output-data-formats/) for `BarcodeResult` property reference.
- [Image Correction How-To](https://ironsoftware.com/csharp/barcode/how-to/image-correction/) for filters that improve decode accuracy.
- [BarcodeReaderOptions API Reference](https://ironsoftware.com/csharp/barcode/object-reference/api/IronBarCode.BarcodeReaderOptions.html) for complete configuration documentation.
- [BarcodeEncoding API Reference](https://ironsoftware.com/csharp/barcode/object-reference/api/IronBarCode.BarcodeEncoding.html) for the full list of supported symbologies.
[Get a free trial license](https://ironsoftware.com/csharp/barcode/#trial-license) to test every feature in a live environment, or [view licensing options](https://ironsoftware.com/csharp/barcode/licensing/) when the pipeline is ready for production.
Barcode checksums help detect substitution errors. For example, a single transposed digit in an EAN-13 label can send a package to the wrong warehouse. Format-aware reading provides an additional validation layer by restricting the decoder to expected symbologies. This approach reduces false positives from background noise and shortens scan time by skipping unnecessary format detectors.
IronBarcode performs checksum verification automatically during decoding. Each symbology's check-digit algorithm runs by default, and barcodes that fail are discarded before results are returned. The BarcodeReaderOptions.ExpectBarcodeTypes property limits reads to specific formats, while RemoveFalsePositive adds a secondary scan for ambiguous reads.
This guide explains how to validate barcode checksums, constrain reads to expected formats, and combine both techniques into a layered quality gate using BarcodeReaderOptions.
Quickstart: Validate Barcodes with Checksum and Format Constraints
Configure BarcodeReaderOptions with ExpectBarcodeTypes and RemoveFalsePositive to constrain reads to expected symbologies with automatic checksum verification.
using IronBarCode;// Format-constrained read with false-positive removal.// Limit the decoder to EAN-13 and Code128; checksums are// validated automatically and failures are silently discarded.var options = new BarcodeReaderOptions{ExpectBarcodeTypes = BarcodeEncoding.EAN13 | BarcodeEncoding.Code128,RemoveFalsePositive = true,Speed = ReadingSpeed.Balanced};BarcodeResults results = BarcodeReader.Read("label.png", options);
using IronBarCode;
// Format-constrained read with false-positive removal.
// Limit the decoder to EAN-13 and Code128; checksums are
// validated automatically and failures are silently discarded.
var options = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.EAN13 | BarcodeEncoding.Code128,
RemoveFalsePositive = true,
Speed = ReadingSpeed.Balanced
};
BarcodeResults results = BarcodeReader.Read("label.png", options);
ImportsIronBarCode' Format-constrained read with false-positive removal.' Limit the decoder to EAN-13 and Code128; checksums are' validated automatically and failures are silently discarded.Dim options As New BarcodeReaderOptionsWith { .ExpectBarcodeTypes = BarcodeEncoding.EAN13OrBarcodeEncoding.Code128, .RemoveFalsePositive = True, .Speed = ReadingSpeed.Balanced}Dim results AsBarcodeResults = BarcodeReader.Read("label.png", options)
Imports IronBarCode
' Format-constrained read with false-positive removal.
' Limit the decoder to EAN-13 and Code128; checksums are
' validated automatically and failures are silently discarded.
Dim options As New BarcodeReaderOptions With {
.ExpectBarcodeTypes = BarcodeEncoding.EAN13 Or BarcodeEncoding.Code128,
.RemoveFalsePositive = True,
.Speed = ReadingSpeed.Balanced
}
Dim results As BarcodeResults = BarcodeReader.Read("label.png", options)
Set ExpectBarcodeTypes to the symbologies present in the pipeline
Enable RemoveFalsePositive for secondary verification
Call BarcodeReader.Read to decode, checksums are validated automatically during decode
How to Validate Barcode Checksums?
IronBarcode validates checksums during decoding according to each symbology's specification. For example, when reading an EAN-13 barcode, the Mod10 check digit is calculated from the first 12 digits and compared to the 13th. If the digits do not match, the barcode is silently rejected and does not appear in the BarcodeResults collection. This approach applies to all formats with a mandatory check digit, including UPC-A, UPC-E, EAN-8, Code128, ITF, and others.
This implicit model differs from libraries that expose an explicit toggle. The table below compares the two approaches:
Checksum Validation Model Comparison: IronBarcode vs. Aspose.BarCode
Aspect
IronBarcode
Aspose.BarCode
Validation trigger
Automatic; runs during every decode
Explicit: ChecksumValidation.On / Off / Default
Developer action required
None; invalid barcodes are excluded from results
Set BarcodeSettings.ChecksumValidation before reading
Checksum disable
Not exposed; checksums are always enforced for mandatory formats
Yes; ChecksumValidation.Off skips verification
Optional-checksum formats (Code39)
Uses Confidence + RemoveFalsePositive to filter low-quality reads
Explicitly enable with EnableChecksum.Yes
Failure behavior
Barcode silently omitted from results
Barcode may appear with a separate checksum value for manual inspection
For symbologies with optional checksums, such as Code39, the library uses confidence scoring and RemoveFalsePositive instead of a checksum toggle.
Input
A Code128 warehouse rack label (success path) and a blank image with no barcode (failure path).
warehouse-rack.png (success path)
blank-no-barcode.png (failure path - no barcode present)
using IronBarCode;// Constrain reads to 1D formats and enable secondary verification.// ConfidenceThreshold rejects decodes where the ML detector falls below 85%,// acting as a quality gate for optional-checksum symbologies like Code39.var options = new BarcodeReaderOptions{ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional,RemoveFalsePositive = true,ConfidenceThreshold = 0.85,Speed = ReadingSpeed.Detailed};BarcodeResults results = BarcodeReader.Read("warehouse-rack.png", options);foreach (BarcodeResult result in results){ // Each result has passed checksum validation (mandatory formats) // and the 85% confidence threshold, so no additional filtering is needed.Console.WriteLine($"[{result.BarcodeType}] {result.Value} page={result.PageNumber}");}if (results.Count == 0){Console.Error.WriteLine("No valid barcodes found. Possible causes:");Console.Error.WriteLine(" - Check digit mismatch (barcode silently rejected)");Console.Error.WriteLine(" - Confidence below 85% threshold");Console.Error.WriteLine(" - Format not in ExpectBarcodeTypes");}
using IronBarCode;
// Constrain reads to 1D formats and enable secondary verification.
// ConfidenceThreshold rejects decodes where the ML detector falls below 85%,
// acting as a quality gate for optional-checksum symbologies like Code39.
var options = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional,
RemoveFalsePositive = true,
ConfidenceThreshold = 0.85,
Speed = ReadingSpeed.Detailed
};
BarcodeResults results = BarcodeReader.Read("warehouse-rack.png", options);
foreach (BarcodeResult result in results)
{
// Each result has passed checksum validation (mandatory formats)
// and the 85% confidence threshold, so no additional filtering is needed.
Console.WriteLine($"[{result.BarcodeType}] {result.Value} page={result.PageNumber}");
}
if (results.Count == 0)
{
Console.Error.WriteLine("No valid barcodes found. Possible causes:");
Console.Error.WriteLine(" - Check digit mismatch (barcode silently rejected)");
Console.Error.WriteLine(" - Confidence below 85% threshold");
Console.Error.WriteLine(" - Format not in ExpectBarcodeTypes");
}
ImportsIronBarCode' Constrain reads to 1D formats and enable secondary verification.' ConfidenceThreshold rejects decodes where the ML detector falls below 85%,' acting as a quality gate for optional-checksum symbologies like Code39.Dim options As New BarcodeReaderOptionsWith { .ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional, .RemoveFalsePositive = True, .ConfidenceThreshold = 0.85, .Speed = ReadingSpeed.Detailed}Dim results AsBarcodeResults = BarcodeReader.Read("warehouse-rack.png", options)For Each result AsBarcodeResultIn results ' Each result has passed checksum validation (mandatory formats) ' and the 85% confidence threshold, so no additional filtering is needed.Console.WriteLine($"[{result.BarcodeType}] {result.Value} page={result.PageNumber}")NextIf results.Count = 0 ThenConsole.Error.WriteLine("No valid barcodes found. Possible causes:")Console.Error.WriteLine(" - Check digit mismatch (barcode silently rejected)")Console.Error.WriteLine(" - Confidence below 85% threshold")Console.Error.WriteLine(" - Format not in ExpectBarcodeTypes")End If
Imports IronBarCode
' Constrain reads to 1D formats and enable secondary verification.
' ConfidenceThreshold rejects decodes where the ML detector falls below 85%,
' acting as a quality gate for optional-checksum symbologies like Code39.
Dim options As New BarcodeReaderOptions With {
.ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional,
.RemoveFalsePositive = True,
.ConfidenceThreshold = 0.85,
.Speed = ReadingSpeed.Detailed
}
Dim results As BarcodeResults = BarcodeReader.Read("warehouse-rack.png", options)
For Each result As BarcodeResult In results
' Each result has passed checksum validation (mandatory formats)
' and the 85% confidence threshold, so no additional filtering is needed.
Console.WriteLine($"[{result.BarcodeType}] {result.Value} page={result.PageNumber}")
Next
If results.Count = 0 Then
Console.Error.WriteLine("No valid barcodes found. Possible causes:")
Console.Error.WriteLine(" - Check digit mismatch (barcode silently rejected)")
Console.Error.WriteLine(" - Confidence below 85% threshold")
Console.Error.WriteLine(" - Format not in ExpectBarcodeTypes")
End If
Output
Success Path
The warehouse rack barcode came back as RACK-A1-LOT-7382 on page 0. It cleared the 85% confidence threshold and passed checksum validation, so it shows up in BarcodeResults.
Failure Path
Raising ConfidenceThreshold above its 0.7 default tightens this gate further for optional-checksum symbologies such as Code39.
With checksum validation covered, the next step is restricting the reader to the barcode formats your pipeline expects.
How to Use Format-Aware Barcode Reading?
The BarcodeEncoding enum is a flags type, allowing multiple formats to be combined using the bitwise OR operator. Setting ExpectBarcodeTypes limits the reader to those formats and skips detection for others.
Common BarcodeEncoding Values
Value
Category
Description
Checksum
BarcodeEncoding.All
Meta
All supported formats (default behavior)
Per-format
BarcodeEncoding.AllOneDimensional
Meta
All linear (1D) formats including stacked
Per-format
BarcodeEncoding.AllTwoDimensional
Meta
All matrix/grid (2D) formats
Per-format
BarcodeEncoding.Code128
1D
High-density alphanumeric (logistics, shipping)
Mandatory (weighted Mod103)
BarcodeEncoding.EAN13
1D
Retail product identification, 13 digits
Mandatory (Mod10)
BarcodeEncoding.QRCode
2D
High-capacity matrix (URLs, structured data)
Reed-Solomon ECC
BarcodeEncoding.Code39
1D
Alphanumeric (defense, automotive)
Optional (Mod43)
BarcodeEncoding.UPCA
1D
North American retail, 12 digits
Mandatory (Mod10)
BarcodeEncoding.DataMatrix
2D
Compact matrix (electronics, pharma)
Reed-Solomon ECC
BarcodeEncoding.PDF417
2D
Stacked (ID cards, transport)
Reed-Solomon ECC
Beyond speed, constraining the format set acts as a validation gate: barcodes of any unlisted symbology are excluded from results even if physically present in the image.
Input
A Code128 shipping label (success path) and a QR code that does not match the Code128-only constraint (failure path).
qr-format-mismatch.png (failure path - QR rejected by Code128-only filter)
using IronBarCode;// Constrained read: only Code128 barcodes are returned.// Faster because the reader skips all other format detectors.var constrainedOptions = new BarcodeReaderOptions{ExpectBarcodeTypes = BarcodeEncoding.Code128,Speed = ReadingSpeed.Faster,ExpectMultipleBarcodes = false};// Broad read: all supported formats are scanned.// Useful for verification or when the image format is unknown.var broadOptions = new BarcodeReaderOptions{ExpectBarcodeTypes = BarcodeEncoding.All,Speed = ReadingSpeed.Detailed,ExpectMultipleBarcodes = true};string imagePath = "shipping-label.png";BarcodeResults constrained = BarcodeReader.Read(imagePath, constrainedOptions);Console.WriteLine($"Constrained: {constrained.Count} Code128 barcode(s) found");BarcodeResults broad = BarcodeReader.Read(imagePath, broadOptions);Console.WriteLine($"Broad: {broad.Count} barcode(s) found across all formats");foreach (BarcodeResult result in broad){Console.WriteLine($" [{result.BarcodeType}] {result.Value}");}
using IronBarCode;
// Constrained read: only Code128 barcodes are returned.
// Faster because the reader skips all other format detectors.
var constrainedOptions = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.Code128,
Speed = ReadingSpeed.Faster,
ExpectMultipleBarcodes = false
};
// Broad read: all supported formats are scanned.
// Useful for verification or when the image format is unknown.
var broadOptions = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.All,
Speed = ReadingSpeed.Detailed,
ExpectMultipleBarcodes = true
};
string imagePath = "shipping-label.png";
BarcodeResults constrained = BarcodeReader.Read(imagePath, constrainedOptions);
Console.WriteLine($"Constrained: {constrained.Count} Code128 barcode(s) found");
BarcodeResults broad = BarcodeReader.Read(imagePath, broadOptions);
Console.WriteLine($"Broad: {broad.Count} barcode(s) found across all formats");
foreach (BarcodeResult result in broad)
{
Console.WriteLine($" [{result.BarcodeType}] {result.Value}");
}
ImportsIronBarCode' Constrained read: only Code128 barcodes are returned.' Faster because the reader skips all other format detectors.Dim constrainedOptions As New BarcodeReaderOptionsWith { .ExpectBarcodeTypes = BarcodeEncoding.Code128, .Speed = ReadingSpeed.Faster, .ExpectMultipleBarcodes = False}' Broad read: all supported formats are scanned.' Useful for verification or when the image format is unknown.Dim broadOptions As New BarcodeReaderOptionsWith { .ExpectBarcodeTypes = BarcodeEncoding.All, .Speed = ReadingSpeed.Detailed, .ExpectMultipleBarcodes = True}Dim imagePath AsString = "shipping-label.png"Dim constrained AsBarcodeResults = BarcodeReader.Read(imagePath, constrainedOptions)Console.WriteLine($"Constrained: {constrained.Count} Code128 barcode(s) found")Dim broad AsBarcodeResults = BarcodeReader.Read(imagePath, broadOptions)Console.WriteLine($"Broad: {broad.Count} barcode(s) found across all formats")For Each result AsBarcodeResultIn broadConsole.WriteLine($" [{result.BarcodeType}] {result.Value}")Next
Imports IronBarCode
' Constrained read: only Code128 barcodes are returned.
' Faster because the reader skips all other format detectors.
Dim constrainedOptions As New BarcodeReaderOptions With {
.ExpectBarcodeTypes = BarcodeEncoding.Code128,
.Speed = ReadingSpeed.Faster,
.ExpectMultipleBarcodes = False
}
' Broad read: all supported formats are scanned.
' Useful for verification or when the image format is unknown.
Dim broadOptions As New BarcodeReaderOptions With {
.ExpectBarcodeTypes = BarcodeEncoding.All,
.Speed = ReadingSpeed.Detailed,
.ExpectMultipleBarcodes = True
}
Dim imagePath As String = "shipping-label.png"
Dim constrained As BarcodeResults = BarcodeReader.Read(imagePath, constrainedOptions)
Console.WriteLine($"Constrained: {constrained.Count} Code128 barcode(s) found")
Dim broad As BarcodeResults = BarcodeReader.Read(imagePath, broadOptions)
Console.WriteLine($"Broad: {broad.Count} barcode(s) found across all formats")
For Each result As BarcodeResult In broad
Console.WriteLine($" [{result.BarcodeType}] {result.Value}")
Next
Output
Success Path
The shipping label has a value of SHIP-2024-00438. The constrained read picks it up straight away since Code128 is what the filter expects, and the broad read confirms the same result across all formats.
Failure Path
Empty results from a constrained read are a validation signal, not an error; log the discrepancy for review.
For pipelines that mix barcode types (e.g., a packing slip with both an EAN-13 product code and a Code128 tracking number), combine the expected formats:
using IronBarCode;// Combine multiple format flags with | to scan for more than one symbology// in a single pass. Each BarcodeResult.BarcodeType identifies which format// was decoded, enabling downstream routing logic per symbology.var options = new BarcodeReaderOptions{ExpectBarcodeTypes = BarcodeEncoding.EAN13 | BarcodeEncoding.Code128,ExpectMultipleBarcodes = true};
using IronBarCode;
// Combine multiple format flags with | to scan for more than one symbology
// in a single pass. Each BarcodeResult.BarcodeType identifies which format
// was decoded, enabling downstream routing logic per symbology.
var options = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.EAN13 | BarcodeEncoding.Code128,
ExpectMultipleBarcodes = true
};
ImportsIronBarCode' Combine multiple format flags with Or to scan for more than one symbology' in a single pass. Each BarcodeResult.BarcodeType identifies which format' was decoded, enabling downstream routing logic per symbology.Dim options As New BarcodeReaderOptionsWith { .ExpectBarcodeTypes = BarcodeEncoding.EAN13OrBarcodeEncoding.Code128, .ExpectMultipleBarcodes = True}
Imports IronBarCode
' Combine multiple format flags with Or to scan for more than one symbology
' in a single pass. Each BarcodeResult.BarcodeType identifies which format
' was decoded, enabling downstream routing logic per symbology.
Dim options As New BarcodeReaderOptions With {
.ExpectBarcodeTypes = BarcodeEncoding.EAN13 Or BarcodeEncoding.Code128,
.ExpectMultipleBarcodes = True
}
Each returned BarcodeResult.BarcodeType identifies which format was decoded, enabling downstream routing.
Which Symbologies Support Checksum Validation?
Not all barcode formats use checksums in the same way. The following table maps common symbologies to their error-detection characteristics, which informs how aggressively to set ConfidenceThreshold and RemoveFalsePositive for each format:
Default settings sufficient; check digit auto-corrected on write
Code128
Weighted Mod103
Yes
Default settings sufficient; mandatory per specification
Code39
Mod43
Optional
Raise ConfidenceThreshold to 0.8+ and enable RemoveFalsePositive
Codabar
Mod16
Optional
Same as Code39; use confidence as the quality gate
ITF
Mod10
Optional
Enable RemoveFalsePositive for interleaved formats
QRCode / DataMatrix
Reed-Solomon ECC
Always
Structural error correction; no additional configuration needed
PDF417
Reed-Solomon ECC
Always
Same as QR/DataMatrix; error correction is inherent
For 2D symbologies such as QR, DataMatrix, and PDF417, error correction is integrated into the encoding structure. These formats can recover from partial damage without depending on a simple check digit. The ConfidenceThreshold still applies during the ML detection phase, while the decode step benefits from the symbology's built-in redundancy.
Now that both techniques are understood, let's combine them into a single production-ready validation pattern.
How to Combine Checksums with Format Constraints?
The production-ready pattern sets ExpectBarcodeTypes, RemoveFalsePositive, ConfidenceThreshold, and Speed in a single BarcodeReaderOptions object. Together they form a layered gate: format constraints narrow the search space, checksum validation ensures data integrity, confidence thresholding filters marginal decodes, and false-positive removal adds a secondary verification pass.
Input
Three POS scan barcodes from the pos-scans/ directory used as the success path: two EAN-13 and one UPC-A. A Code128 warehouse rack label is used as the failure path - the EAN-13/UPC-A constraint rejects it and logs a REJECT line.
pos-scan-1.png (success)
pos-scan-2.png (success)
pos-scan-3.png (success)
warehouse-rack.png (failure - Code128 rejected)
using IronBarCode;// Layered validation for retail POS: EAN-13, UPC-A, and UPC-E only.// Each property adds a distinct filter to the read pipeline.var options = new BarcodeReaderOptions{ // Layer 1: format constraint, accept only retail symbologiesExpectBarcodeTypes = BarcodeEncoding.EAN13 | BarcodeEncoding.UPCA | BarcodeEncoding.UPCE, // Layer 2: confidence threshold, reject decodes below 80%ConfidenceThreshold = 0.8, // Layer 3: false-positive removal, runs a secondary verification passRemoveFalsePositive = true,Speed = ReadingSpeed.Balanced,ExpectMultipleBarcodes = false, // Require 3 agreeing scan lines to reduce phantom reads from noisy imagesMinScanLines = 3};string[] scanFiles = Directory.GetFiles("pos-scans/", "*.png");foreach (string file in scanFiles){ BarcodeResults results = BarcodeReader.Read(file, options); if (results.Count == 0) { // No barcode passed all validation layersConsole.Error.WriteLine($"REJECT {Path.GetFileName(file)}: " + "no valid EAN-13/UPC barcode (checksum, confidence, or format mismatch)"); continue; } BarcodeResult primary = results.First(); // Post-read assertion: verify the decoded format matches expectations. // ExpectBarcodeTypes already constrains the reader; this check documents // intent and surfaces unexpected results during future changes. if (primary.BarcodeType != BarcodeEncoding.EAN13 && primary.BarcodeType != BarcodeEncoding.UPCA && primary.BarcodeType != BarcodeEncoding.UPCE) {Console.Error.WriteLine($"UNEXPECTED FORMAT {Path.GetFileName(file)}: " + $"got {primary.BarcodeType}, expected EAN-13/UPC"); continue; }Console.WriteLine($"OK {Path.GetFileName(file)}: [{primary.BarcodeType}] {primary.Value}");}
using IronBarCode;
// Layered validation for retail POS: EAN-13, UPC-A, and UPC-E only.
// Each property adds a distinct filter to the read pipeline.
var options = new BarcodeReaderOptions
{
// Layer 1: format constraint, accept only retail symbologies
ExpectBarcodeTypes = BarcodeEncoding.EAN13 | BarcodeEncoding.UPCA | BarcodeEncoding.UPCE,
// Layer 2: confidence threshold, reject decodes below 80%
ConfidenceThreshold = 0.8,
// Layer 3: false-positive removal, runs a secondary verification pass
RemoveFalsePositive = true,
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = false,
// Require 3 agreeing scan lines to reduce phantom reads from noisy images
MinScanLines = 3
};
string[] scanFiles = Directory.GetFiles("pos-scans/", "*.png");
foreach (string file in scanFiles)
{
BarcodeResults results = BarcodeReader.Read(file, options);
if (results.Count == 0)
{
// No barcode passed all validation layers
Console.Error.WriteLine($"REJECT {Path.GetFileName(file)}: "
+ "no valid EAN-13/UPC barcode (checksum, confidence, or format mismatch)");
continue;
}
BarcodeResult primary = results.First();
// Post-read assertion: verify the decoded format matches expectations.
// ExpectBarcodeTypes already constrains the reader; this check documents
// intent and surfaces unexpected results during future changes.
if (primary.BarcodeType != BarcodeEncoding.EAN13
&& primary.BarcodeType != BarcodeEncoding.UPCA
&& primary.BarcodeType != BarcodeEncoding.UPCE)
{
Console.Error.WriteLine($"UNEXPECTED FORMAT {Path.GetFileName(file)}: "
+ $"got {primary.BarcodeType}, expected EAN-13/UPC");
continue;
}
Console.WriteLine($"OK {Path.GetFileName(file)}: [{primary.BarcodeType}] {primary.Value}");
}
ImportsIronBarCodeImportsSystem.IO' Layered validation for retail POS: EAN-13, UPC-A, and UPC-E only.' Each property adds a distinct filter to the read pipeline.Dim options As New BarcodeReaderOptionsWith { ' Layer 1: format constraint, accept only retail symbologies .ExpectBarcodeTypes = BarcodeEncoding.EAN13OrBarcodeEncoding.UPCAOrBarcodeEncoding.UPCE, ' Layer 2: confidence threshold, reject decodes below 80% .ConfidenceThreshold = 0.8, ' Layer 3: false-positive removal, runs a secondary verification pass .RemoveFalsePositive = True, .Speed = ReadingSpeed.Balanced, .ExpectMultipleBarcodes = False, ' Require 3 agreeing scan lines to reduce phantom reads from noisy images .MinScanLines = 3}Dim scanFiles AsString() = Directory.GetFiles("pos-scans/", "*.png")For Each file AsStringIn scanFiles Dim results AsBarcodeResults = BarcodeReader.Read(file, options) If results.Count = 0 Then ' No barcode passed all validation layersConsole.Error.WriteLine($"REJECT {Path.GetFileName(file)}: " & "no valid EAN-13/UPC barcode (checksum, confidence, or format mismatch)") Continue For End If Dim primary AsBarcodeResult = results.First() ' Post-read assertion: verify the decoded format matches expectations. ' ExpectBarcodeTypes already constrains the reader; this check documents ' intent and surfaces unexpected results during future changes. If primary.BarcodeType <> BarcodeEncoding.EAN13AndAlso primary.BarcodeType <> BarcodeEncoding.UPCAAndAlso primary.BarcodeType <> BarcodeEncoding.UPCEThenConsole.Error.WriteLine($"UNEXPECTED FORMAT {Path.GetFileName(file)}: " & $"got {primary.BarcodeType}, expected EAN-13/UPC") Continue For End IfConsole.WriteLine($"OK {Path.GetFileName(file)}: [{primary.BarcodeType}] {primary.Value}")Next
Imports IronBarCode
Imports System.IO
' Layered validation for retail POS: EAN-13, UPC-A, and UPC-E only.
' Each property adds a distinct filter to the read pipeline.
Dim options As New BarcodeReaderOptions With {
' Layer 1: format constraint, accept only retail symbologies
.ExpectBarcodeTypes = BarcodeEncoding.EAN13 Or BarcodeEncoding.UPCA Or BarcodeEncoding.UPCE,
' Layer 2: confidence threshold, reject decodes below 80%
.ConfidenceThreshold = 0.8,
' Layer 3: false-positive removal, runs a secondary verification pass
.RemoveFalsePositive = True,
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = False,
' Require 3 agreeing scan lines to reduce phantom reads from noisy images
.MinScanLines = 3
}
Dim scanFiles As String() = Directory.GetFiles("pos-scans/", "*.png")
For Each file As String In scanFiles
Dim results As BarcodeResults = BarcodeReader.Read(file, options)
If results.Count = 0 Then
' No barcode passed all validation layers
Console.Error.WriteLine($"REJECT {Path.GetFileName(file)}: " &
"no valid EAN-13/UPC barcode (checksum, confidence, or format mismatch)")
Continue For
End If
Dim primary As BarcodeResult = results.First()
' Post-read assertion: verify the decoded format matches expectations.
' ExpectBarcodeTypes already constrains the reader; this check documents
' intent and surfaces unexpected results during future changes.
If primary.BarcodeType <> BarcodeEncoding.EAN13 AndAlso
primary.BarcodeType <> BarcodeEncoding.UPCA AndAlso
primary.BarcodeType <> BarcodeEncoding.UPCE Then
Console.Error.WriteLine($"UNEXPECTED FORMAT {Path.GetFileName(file)}: " &
$"got {primary.BarcodeType}, expected EAN-13/UPC")
Continue For
End If
Console.WriteLine($"OK {Path.GetFileName(file)}: [{primary.BarcodeType}] {primary.Value}")
Next
Output
Success Path
All three POS scan images made it through. The reader returned values of 5901234123471, 4006381333931, and 012345678905. Each one matched the EAN13 | UPCA | UPCE filter, had a valid Mod10 checksum, and confidence was above 0.8.
Failure Path
Setting MinScanLines to 3 increases the minimum number of agreeing scan lines required for a 1D barcode to be valid; the default is 2. Raising this value lowers the risk of phantom reads from noisy scan lines but may cause thin or partially damaged barcodes to be missed. In retail POS environments with clean printed labels, a value of 3 is a conservative choice that strengthens validation without affecting throughput.
The post-read BarcodeType assertion is defense-in-depth: ExpectBarcodeTypes already filters, but the explicit check documents intent and catches configuration drift without runtime cost. For speed tuning, ReadingSpeed.Faster suits clean machine-printed labels; Detailed and ExtremeDetail recover damaged or poorly lit barcodes at the cost of longer scan times.
What Are My Next Steps?
This article covered IronBarcode's implicit checksum validation model, the BarcodeEncoding flags enum for format-constrained reads, and a combined validation pattern using ExpectBarcodeTypes, ConfidenceThreshold, RemoveFalsePositive, and MinScanLines as layered quality gates.
What is the purpose of validating barcode checksums?
Validating barcode checksums ensures that data is not corrupted during barcode scanning. IronBarcode automatically performs checksum verification for each symbology's check-digit algorithm during decoding.
How does IronBarcode handle format-aware reading?
IronBarcode uses the `BarcodeReaderOptions.ExpectBarcodeTypes` property to restrict reads to specific barcode symbologies. This reduces false positives and improves scanning efficiency by limiting format detectors to only expected types.
Can IronBarcode perform automatic checksum verification?
Yes, IronBarcode performs automatic checksum verification during the decoding process. Barcodes that fail this verification are discarded before results are returned.
What is the use of the `RemoveFalsePositive` feature in IronBarcode?
The `RemoveFalsePositive` feature in IronBarcode adds a secondary scan verification to help eliminate ambiguous reads, ensuring higher accuracy in barcode detection.
Which symbologies support mandatory checksum validation in IronBarcode?
Symbologies such as EAN-13, UPC-A, Code128, and others support mandatory checksum validation. IronBarcode automatically enforces checksum checks for these formats.
How can you set constraints on barcode reading formats with IronBarcode?
You can set constraints on barcode reading formats in IronBarcode using the `ExpectBarcodeTypes` property. It allows you to specify and limit the barcode types IronBarcode should decode.
What are the benefits of using format constraints in barcode reading?
Format constraints help in reducing scanning errors by limiting the search to specific symbologies, thus avoiding unnecessary noise, and enhancing the scanning speed.
How does IronBarcode handle barcodes with optional checksum formats like Code39?
For optional checksum formats like Code39, IronBarcode uses a combination of confidence scoring and the `RemoveFalsePositive` feature to filter out low-quality reads.
What does the ConfidenceThreshold property do in IronBarcode?
The `ConfidenceThreshold` property in IronBarcode sets a quality gate for decoding, rejecting barcodes where the machine learning detector's confidence falls below a specified percentage.
How can IronBarcode combine checksum validation with format constraints?
IronBarcode combines checksum validation with format constraints using `BarcodeReaderOptions`. By setting properties like `ExpectBarcodeTypes`, `ConfidenceThreshold`, and `RemoveFalsePositive`, it creates a layered validation approach.
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.