decode

package
v0.0.0-...-cba4c60 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package decode turns a sampled symbol matrix into message bits: metadata and palette decoding, module colour classification, and the LDPC/demask/deinterleave message decode, for primary and docked secondary symbols. Detection lives in the sibling detect package; the read package coordinates the two, and the public Decode API in the parent jabcode package wraps read.Decode.

Index

Constants

View Source
const MetadataFailed = -1

Decoder status/constant values.

Variables

This section is empty.

Functions

func BitLLRs

func BitLLRs(costs []float64, dst []float64) []float64

BitLLRs converts one module's candidate costs to signed max-log bit evidence, most significant bit first, appended to dst. The tested sign convention: an LLR is the minimum cost among candidates whose index has the bit SET minus the minimum among those with it CLEAR, so POSITIVE evidence favors bit zero and agreeing observations add.

func DecodeData

func DecodeData(bits []byte) []byte

DecodeData interprets the corrected bit stream into the decoded message, following the mode/latch/shift state machine.

func DecodeDataVariant

func DecodeDataVariant(bits []byte, variant wire.Variant) ([]byte, bool)

DecodeDataVariant interprets a corrected bit stream under the selected wire variant. ok is false when an ISO stream is truncated, uses a reserved switch, or violates an ISO/IEC 15434 or FNC1 start/end protocol. C-reference mode preserves the reference decoder's partial-message behavior.

func DecodeModuleHD

func DecodeModuleHD(matrix *core.Bitmap, palette []byte, colorNumber int, normPalette, palThs []float64, x, y int) byte

DecodeModuleHD maps the sampled RGB of module (x,y) to its palette index by nearest normalized color, with a black check and a black/white tie-break.

func DecodeModuleNC

func DecodeModuleNC(rgb []byte) byte

DecodeModuleNC decodes a primary-metadata Part I module color into its 3-bit value.

func DecodePrimary

func DecodePrimary(matrix *core.Bitmap, symbol *core.DecodedSymbol) int

DecodePrimary decodes a primary symbol from its sampled matrix: the metadata observation followed immediately by payload correction.

func DecodePrimaryMetadataPartI

func DecodePrimaryMetadataPartI(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, moduleCount, x, y *int) (ret int, syndromeOK bool)

DecodePrimaryMetadataPartI decodes Nc from the four Part I metadata modules. Returns Success, Failure, or MetadataFailed (the latter triggers the default-metadata fallback, which is what happens for default-mode symbols). syndromeOK reports whether the hard-decoded part satisfied its LDPC parity checks - recorded for the caller's observation, not enforced here.

The plain per-module classification decides from absolute channel values, which a display cast can defeat (a screen's black is bright enough in blue to fail the black test). When it produces an invalid Part I, the same four modules are re-classified against references derived from the symbol's own finder cores (partIColorRefs) before falling back to default metadata: a default-mode symbol has palette colours in these positions that still classify outside the Part I set, so the fallback semantics are preserved.

func DecodePrimaryMetadataPartII

func DecodePrimaryMetadataPartII(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, normPalette, palThs []float64, moduleCount, x, y *int) (ret int, syndromeOK bool)

DecodePrimaryMetadataPartII decodes the version, ECC level and mask reference from Part II of the primary metadata. syndromeOK reports whether the hard-decoded part satisfied its LDPC parity checks - recorded for the caller's observation, not enforced here.

func DecodePrimaryOnDevice

func DecodePrimaryOnDevice(
	device core.PrimaryDevice,
	matrix *core.Bitmap,
	symbol *core.DecodedSymbol,
) (ret int, handled bool)

DecodePrimaryOnDevice consumes the fused resident result. handled is false only when the device declined before owning the attempt; an answered payload failure remains handled so hard correction is never repeated on the host.

func DecodePrimaryResult

func DecodePrimaryResult(
	result core.PrimaryDeviceResult,
	matrix *core.Bitmap,
	symbol *core.DecodedSymbol,
) (ret int, handled bool)

DecodePrimaryResult applies and parses one already-downloaded resident result. Keeping this independent of the device call lets a fixed result batch cross once while every interpretation still uses the same admission path.

func DecodeSecondary

func DecodeSecondary(matrix *core.Bitmap, symbol *core.DecodedSymbol) int

DecodeSecondary decodes a secondary symbol from its sampled matrix.

func DecodeSecondaryTraced

func DecodeSecondaryTraced(matrix *core.Bitmap, symbol *core.DecodedSymbol, trace *ModuleClassificationTrace) int

DecodeSecondaryTraced is DecodeSecondary with the actual data-module hard classifications retained from the same execution.

func DecodeSymbol

func DecodeSymbol(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, normPalette, palThs []float64, typ int) int

DecodeSymbol reads, demasks, deinterleaves and error-corrects a symbol's data modules, storing the net payload in symbol.data.

func DecodeSymbolTraced

func DecodeSymbolTraced(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, normPalette, palThs []float64, typ int, trace *ModuleClassificationTrace) int

DecodeSymbolTraced is DecodeSymbol with the actual data-module hard classifications retained from the same execution.

func LoadDefaultPrimaryMetadata

func LoadDefaultPrimaryMetadata(matrix *core.Bitmap, symbol *core.DecodedSymbol)

LoadDefaultPrimaryMetadata sets the metadata used when a primary symbol carries no explicit metadata.

func NormalizeColorPalette

func NormalizeColorPalette(symbol *core.DecodedSymbol, normPalette []float64, colorNumber int)

NormalizeColorPalette precomputes per-color normalized RGB + luminance values for nearest-color matching. It covers every embedded palette copy (four for 4/8-color, two for the higher modes).

func PaletteThreshold

func PaletteThreshold(palette []byte, colorNumber int) [3]float64

PaletteThreshold returns the per-channel black thresholds, midway between the dark and light palette colors.

func ReadColorPaletteInPrimary

func ReadColorPaletteInPrimary(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, moduleCount, x, y *int) int

ReadColorPaletteInPrimary reconstructs the colour palettes embedded in the primary symbol (four copies for 4/8-color, two for the higher modes).

Types

type Message

type Message struct {
	Data               []byte
	ReaderTransmission []byte
	Controls           []MessageControl
	Variant            wire.Variant
}

Message contains the decoded application data and its standards-facing reader transmission. Controls remain separate from Data so ECI and structured message semantics are not confused with literal payload bytes.

func DecodeMessageVariant

func DecodeMessageVariant(bits []byte, variant wire.Variant) (Message, bool)

DecodeMessageVariant interprets a corrected bit stream and returns both raw data and reader transmission without reparsing one representation from the other.

type MessageControl

type MessageControl struct {
	Kind       MessageControlKind
	Offset     int
	Assignment int
}

MessageControl records a control at an offset in Message.Data. Assignment is set only for MessageControlECI.

type MessageControlKind

type MessageControlKind uint8

MessageControlKind identifies a non-data control encountered while decoding a message mode stream.

const (
	MessageControlECI MessageControlKind = iota + 1
	MessageControlFNC1Start
	MessageControlFNC1Separator
	MessageControlFNC1End
	MessageControlISO15434Start
	MessageControlISO15434End
)

type ModuleClassificationTrace

type ModuleClassificationTrace struct {
	Side           image.Point
	DataMap        []byte
	Colors         []byte
	ReusedEvidence bool
}

ModuleClassificationTrace records the actual hard classification of each data module. Reserved modules keep the unset value 255.

type ModuleEvidenceCache

type ModuleEvidenceCache struct {
	// contains filtered or unexported fields
}

ModuleEvidenceCache retains neutral payload-module classifications for one sampled primary matrix. It is deliberately fixed-size and map-free: the current physical family has at most two irreducible wire interpretations. Two entries retain the finder-grid sample and its first alignment fallback; a later unique fallback belongs to the final interpretation and has no subsequent consumer. Deterministic priority remains the caller's responsibility.

type ObservationSnapshot

type ObservationSnapshot struct {
	Side             image.Point   // sampled matrix dimensions, the layout hypothesis
	Meta             core.Metadata // interpreted metadata values (value copy)
	PartISyndromeOK  bool
	PartIISyndromeOK bool
	WireVariant      wire.Variant // wire rules that own masking, interleave, ECC and message interpretation
	Palette          []byte       // embedded palette as captured, deep copy
	Modules          []byte       // sampled module values, matrix pixel layout, deep copy
	Channels         int          // bytes per module in Modules
	DataMap          []byte       // complete reserved-module map (metadata, palette, finder, alignment), deep copy

	FixedAgree, FixedChecked               int
	PaletteDisagreement, PaletteSeparation float64
	Admitted                               bool
}

ObservationSnapshot is the deep-owned, immutable form of an observation that may outlive its read attempt. A live PrimaryObservation aliases a mutable DecodedSymbol (the alignment-pattern retry re-observes into the same symbol) and the decoders mutate their buffers in place, so retained evidence must be copied out before any further attempt runs: one failed correction must never corrupt what a later frame reuses. The snapshot carries the layout hypothesis, the interpreted metadata with its syndrome status, the captured palette, the sampled module values and the admission measurements - everything the cross-frame accumulator consumes. Finder geometry in frame coordinates lives with the caller's banked entry (the read layer owns coordinates); the snapshot describes the sampled grid.

func (*ObservationSnapshot) BitEvidence

func (s *ObservationSnapshot) BitEvidence() []float64

BitEvidence derives a snapshot's signed per-bit evidence in the decoder's gross-codeword coordinates: data modules column-major, bits most significant first, demasked (a set mask bit flips the sign - the same confidence votes for the flipped value), truncated to whole code blocks and deinterleaved - exactly the space the soft decoder consumes, so evidence from compatible frames aligns bit for bit. Only the accumulating colour scope derives evidence (up to eight colours); higher modes return nil until a measured extension opens them.

func (*ObservationSnapshot) CorrectEvidence

func (s *ObservationSnapshot) CorrectEvidence(llr []float64) (*core.DecodedSymbol, int)

CorrectEvidence decodes additive signed evidence belonging to this snapshot's trusted layout. The retained snapshot and evidence remain untouched: the LDPC decoder owns its work buffers and the returned symbol owns copies of metadata-dependent state. A caller may therefore retry after later frames add evidence without a failed attempt poisoning the group.

type PrimaryObservation

type PrimaryObservation struct {
	Matrix *core.Bitmap        // sampled module matrix
	Symbol *core.DecodedSymbol // metadata interpreted in place

	// PartISyndromeOK and PartIISyndromeOK record whether the hard-decoded
	// metadata parts satisfied their LDPC parity checks. They are recorded,
	// not enforced - metadata has fallback ladders of its own - and are
	// meaningful only when the parts actually decoded: a default-mode symbol
	// (Symbol.Meta.DefaultMode) decodes neither part.
	PartISyndromeOK  bool
	PartIISyndromeOK bool
	// contains filtered or unexported fields
}

PrimaryObservation is the observation half of a primary-symbol read: the sampled matrix with its metadata interpreted (part I with the default-metadata fallback, the embedded colour palette, part II) and every input the payload correction needs, before any data-module error correction has run. ObservePrimary produces it; CorrectPayload spends the correction. The split lets a caller hold a fully sampled and interpreted symbol, decide whether the expensive hard and soft LDPC chain is worth paying, and keep the observation for cross-frame use otherwise.

func ObservePrimary

func ObservePrimary(matrix *core.Bitmap, symbol *core.DecodedSymbol) (*PrimaryObservation, int)

ObservePrimary interprets a sampled primary matrix up to but excluding payload correction. It returns the prepared observation on core.Success; nil and core.Failure when a metadata stage failed (symbol.Meta then holds whatever was interpreted - notably a part II side version that a caller's alignment-pattern retry may still use); nil and core.FatalError on a nil matrix.

func ObservePrimaryOnDevice

func ObservePrimaryOnDevice(
	device core.MetadataDevice,
	matrix *core.Bitmap,
	symbol *core.DecodedSymbol,
	trace *PrimaryTrace,
) (obs *PrimaryObservation, ret int, handled bool)

ObservePrimaryOnDevice interprets a sampled primary matrix from metadata a device already walked, and reports whether it answered at all.

handled is false when the device declined - it does not own this sample, the colour mode is outside what it implements, or the symbol falls to the default metadata ladder, which reads the grid again from the start. The caller then runs ObservePrimary over the same matrix and nothing about the read changes.

What comes back from a device is deliberately narrow: the colour mode, the palette bytes and the declared shape. The normalized palette, its thresholds and the reserved-module map are all rederived here, from those fields and the walk length, so every host stage downstream sees values its own arithmetic produced. A device that shipped its own normalized palette would be handing the host fallbacks a narrower float than they have ever classified against.

func ObservePrimaryTraced

func ObservePrimaryTraced(matrix *core.Bitmap, symbol *core.DecodedSymbol, trace *PrimaryTrace) (*PrimaryObservation, int)

ObservePrimaryTraced is ObservePrimary with stage results captured from the same execution.

func (*PrimaryObservation) AdmitPayloadCorrection

func (obs *PrimaryObservation) AdmitPayloadCorrection() bool

AdmitPayloadCorrection reports whether the observation is plausibly a correctly sampled symbol worth spending payload correction on. A non-default symbol whose metadata parts both satisfied their LDPC parity checks is admitted outright - across the measured captures that condition occurred only on true grids. Anything else (default-mode symbols decode no explicit metadata; garbage samples fall back to default metadata) must look like a symbol: coherent, separable embedded palette copies and format-fixed modules classifying above chance.

func (*PrimaryObservation) CorrectPayload

func (obs *PrimaryObservation) CorrectPayload() int

CorrectPayload runs data-module error correction on the observed symbol - the expensive half of a primary read (demask, deinterleave, hard LDPC and the soft retry) - storing the net payload in the symbol's Data.

func (*PrimaryObservation) CorrectPayloadMergedPalette

func (obs *PrimaryObservation) CorrectPayloadMergedPalette() int

CorrectPayloadMergedPalette retries payload correction with every embedded palette copy replaced by the mean of the copies.

A symbol carries one palette copy per corner so that a capture's local illumination and colour cast can be corrected where each module actually sits, and that locality is what makes the per-corner copies the right primary read. Each entry is nonetheless read from a single module, so once blur or resampling mixes a palette module with its neighbours every copy is wrong on its own - while the four errors stay largely independent, which leaves their mean far closer to the true palette than any one copy. Averaging therefore buys noise rejection at the cost of the locality, a trade only worth making once the local read has already failed to decode. Hence a second hypothesis and never the first.

It reruns classification from the sampled matrix rather than reusing cached module evidence, which was classified under the per-corner palettes.

func (*PrimaryObservation) CorrectPayloadWithCache

func (obs *PrimaryObservation) CorrectPayloadWithCache(cache *ModuleEvidenceCache) int

CorrectPayloadWithCache runs payload correction while retaining neutral module classifications and soft reliabilities for another wire interpretation of the same sampled matrix.

func (*PrimaryObservation) FixedPatternAgreement

func (obs *PrimaryObservation) FixedPatternAgreement() (agree, checked int)

FixedPatternAgreement classifies the sampled modules whose colours the format fixes - the four finder-pattern cores and every interior alignment-pattern core and periphery - against their expected palette indices for the observed colour mode. agree/checked is the admission signal: a correctly gridded sample classifies almost all fixed modules correctly, a phantom or misgridded sample scores near chance (1/colours). The check spends a few dozen classifications and no error correction.

func (*PrimaryObservation) MetadataModules

func (obs *PrimaryObservation) MetadataModules() int

MetadataModules reports how many modules this observation's metadata walk consumed. A device stage derives its reserved map from geometry and this one number, so a comparison between the two maps has to be given the same value the observation used rather than one read off the symbol, which the primary walk does not fill.

func (*PrimaryObservation) ModuleCosts

func (obs *PrimaryObservation) ModuleCosts(x, y int, dst []float64) []float64

ModuleCosts appends module (x,y)'s per-colour candidate costs to dst, one per palette colour, in the classifiers' candidate order.

func (*PrimaryObservation) PaletteCoherence

func (obs *PrimaryObservation) PaletteCoherence() (disagreement, separation float64)

PaletteCoherence measures the embedded palette's internal consistency. disagreement is the mean RGB distance between corresponding colours across the embedded copies; separation is the minimum pairwise RGB distance among the per-colour mean values. A well-sampled symbol reads coherent copies (low disagreement) of a separable palette (separation well above zero); a misaligned or phantom sample reads incoherent copies or a collapsed palette. Both values are in raw RGB units, so callers compare them against each other, not against fixed constants.

func (*PrimaryObservation) Snapshot

func (obs *PrimaryObservation) Snapshot() *ObservationSnapshot

Snapshot freezes the observation into a deep-owned immutable copy, computing the admission measurements once. The receiver stays usable; the snapshot shares no memory with it.

It returns nil when the sampled modules cannot be produced. A snapshot is entirely for cross-frame evidence, and evidence without modules is not weaker evidence, it is none.

func (*PrimaryObservation) UseDevice

func (obs *PrimaryObservation) UseDevice(device core.PayloadDevice)

UseDevice offers payload correction a corrector that can interpret the sampled grid where it already lies. A nil corrector, or one that declines, leaves the host chain answering exactly as before.

func (*PrimaryObservation) UseGrid

func (obs *PrimaryObservation) UseGrid(grid core.GridDevice)

UseGrid offers the observation a way to fill its matrix's module data, for a sample that is still resident on a device. Without one the matrix has to carry its own pixels, which is what a host-sampled read gives it.

type PrimaryTrace

type PrimaryTrace struct {
	Matrix *core.Bitmap

	PartIAttempted   bool
	PartIResult      int
	PartISyndromeOK  bool
	PartIDataMap     []byte
	UsedDefault      bool
	PaletteAttempted bool
	PaletteResult    int
	PaletteDataMap   []byte
	PartIIAttempted  bool
	PartIIResult     int
	PartIISyndromeOK bool
	PartIIDataMap    []byte

	CorrectionAttempted bool
	CorrectionResult    int
	// MergedPaletteAttempted records that the per-corner palette read failed to
	// decode the payload and the averaged-copy retry ran; CorrectionResult then
	// holds that retry's result.
	MergedPaletteAttempted bool
	AdmissionChecked       bool
	Admitted               bool
	Classification         ModuleClassificationTrace
	Symbol                 core.DecodedSymbol
}

PrimaryTrace records the metadata, palette and payload-correction stages of one real primary observation. It is populated only by ObservePrimaryTraced.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL