API reference
The whole public surface. Everything is nullable-annotated and documented in XML, so the same text appears in IntelliSense.
The component
<BbScanner> parameters
| Parameter | Type | Default | Purpose |
|---|---|---|---|
| Formats | BbBarcodeFormat | All | Symbologies to look for. A flags enum. |
| Region | BbScanRegion | Full | Normalized sub-rectangle to search. |
| Options | BbScannerOptions? | null | Advanced tuning applied under Formats and Region. |
| TargetFrameRate | int | 15 | Frames a second to decode. |
| RequestedWidth / Height | int | 1280 / 720 | Camera constraints; the browser may negotiate otherwise. |
| MaxProcessingSize | int | 640 | Longest edge of the image the decoder sees. |
| Facing | BbCameraFacing | Rear | Preferred camera when no device id is given. |
| DeviceId | string? | null | A specific camera to open. |
| AutoStart | bool | true | Open the camera as soon as the component is ready. |
| DuplicateSuppressionWindow | TimeSpan? | null (2s) | How long an identical value stays suppressed. Set, it overrides Options; unset, Options decides, else 2 s. |
| ShowControls | bool | true | Built-in control bar. |
| ShowStatusBar | bool | true | Built-in status bar. |
| ShowReticle | bool | true | Corner reticle over the scan region. |
| ShowMask | bool | true | Dim outside the scan region. |
| HighlightResults | bool | true | Outline a decoded symbol in place. |
| EnableFileScanning | bool | true | Offer still image scanning. |
| Fill | bool | false | Fill the parent instead of keeping the camera's aspect ratio. |
| AriaLabel | string | "Barcode scanner" | Accessible name for the region. |
| CssClass | string? | null | Extra classes on the root element. |
| Overlay | RenderFragment<BbScanner>? | null | Replaces the reticle; receives the scanner. |
| MessageTemplate | RenderFragment<string>? | null | Replaces status and error message rendering. |
| ControlsContent | RenderFragment? | null | Extra controls in the built-in bar. |
| ChildContent | RenderFragment? | null | Arbitrary content over the viewport. |
| @attributes | any | - | Any other attribute is applied to the root element. A class or style given this way is merged with the component's own rather than replacing it. |
<BbScanner> events
| Event | Payload | Raised when |
|---|---|---|
| OnScan | BbBarcodeResult | A symbol is decoded and passes duplicate suppression. |
| OnError | BbScannerException | The camera cannot start, or a frame fails. |
| OnStatusChanged | BbScannerStatus | The lifecycle state changes. |
| OnCameraChanged | BbCameraInfo | A camera opens, with what was negotiated. |
| OnDiagnostics | BbScanDiagnostics | At most twice a second, with frame timings. |
<BbScanner> methods and properties
Task StartAsync(string? deviceId = null) Task StopAsync() void Pause() void Resume() Task SwitchCameraAsync(string deviceId) Task<bool> SetTorchAsync(bool on) Task<bool> SetZoomAsync(double zoom) Task OpenFilePickerAsync() Task<IReadOnlyList<BbCameraDevice>> GetCamerasAsync() BbBarcodeResult? DecodeImage(ReadOnlySpan<byte> pixels, int width, int height, BbPixelFormat format) BbScannerStatus Status BbCameraInfo? Camera IReadOnlyList<BbCameraDevice> Cameras BbScanDiagnostics Diagnostics long FramesDecoded long FramesWithSymbol bool IsTorchOn double Zoom (int, int) ProcessingSize
StartAsync is safe to call at any time: a call that arrives while an earlier one
is still waiting for the permission prompt supersedes it, and the superseded request releases
its camera rather than leaving it running. The same holds for StopAsync and for
disposal, so navigating away mid-prompt never leaves the camera indicator lit.
The results and the options
BbBarcodeResult
| Member | Type | Meaning |
|---|---|---|
| Text | string | Decoded value after character set interpretation. |
| RawBytes | ReadOnlyMemory<byte> | Payload bytes before interpretation. |
| Format | BbBarcodeFormat | The symbology that produced the value. |
| Timestamp | DateTimeOffset | When the frame was decoded. |
| Corners | IReadOnlyList<BbScanPoint> | Locator points in frame pixels. |
| BoundingBox | BbScanRect | Axis aligned box around the corners. |
| FrameWidth / FrameHeight | int | Size of the frame the value came from. |
| Metadata | BbBarcodeResultMetadata? | Version, error correction level, corrections, ECI, GS1, structured append. |
BbScannerOptions
BbBarcodeFormat Formats = BbBarcodeFormat.All BbScanRegion Region = BbScanRegion.Full int MaxScanLines = 15 // lines per orientation int DownsampleFactor = 1 bool TryHarder = false // exhaustive detection, full rotation sweep bool AllowInverted = false // light on dark symbols bool TryReversedRows = true // linear symbols read right to left bool TryVerticalLines = true // columns and tilted lines, for rotated symbols IReadOnlyCollection<int> ItfLengths = 6..20 even bool Code39CheckDigit = false // require the modulo 43 check character bool Code39ExtendedMode = false // interpret Code 39 as full ASCII TimeSpan DuplicateSuppressionWindow = 2 seconds BbScannerOptions.ForStillImages() // 60 scan lines, TryHarder, AllowInverted, no suppression options.Clone() // take a copy before editing a running scanner's options options.Validate() // throws on an out of range value
ITF has no check character, so ItfLengths is the main defence against a
truncated symbol being reported as a shorter, structurally valid number. Narrow it to the
lengths your application actually uses.
The decoder
Headless use
The decoding pipeline has no dependency on Blazor or on a browser. It runs anywhere .NET runs, which is what makes it testable and benchmarkable.
using var decoder = new BbBarcodeDecoder(new BbScannerOptions { Formats = BbBarcodeFormat.QrCode | BbBarcodeFormat.DataMatrix, DuplicateSuppressionWindow = TimeSpan.Zero, }); var result = decoder.Decode(rgbaPixels, width, height, BbPixelFormat.Rgba32); if (result is not null) { Console.WriteLine($"{result.Format}: {result.Text}"); Console.WriteLine($"took {decoder.LastFrame.Total.TotalMilliseconds:0.00} ms"); }
Extending the decoder
A new symbology implements IBbRowDecoder for a linear code or
IBbMatrixDecoder for a two dimensional one. Both receive already binarised input,
so a new reader only has to contribute its own character table and structure.
public interface IBbRowDecoder { BbBarcodeFormat Formats { get; } BbSymbolDecodeResult? DecodeRow(int rowNumber, BbBitRow row, BbBarcodeFormat enabledFormats); } public interface IBbMatrixDecoder { BbBarcodeFormat Formats { get; } BbSymbolDecodeResult? Decode(BbBitMatrix image, BbMatrixDecodeOptions options); }
Binarisation is an extension point too: IBbBinarizer has one implementation tuned
for matrix codes and one for linear rows, and a replacement can be substituted for either.