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
- func BitLLRs(costs []float64, dst []float64) []float64
- func DecodeData(bits []byte) []byte
- func DecodeDataVariant(bits []byte, variant wire.Variant) ([]byte, bool)
- func DecodeModuleHD(matrix *core.Bitmap, palette []byte, colorNumber int, ...) byte
- func DecodeModuleNC(rgb []byte) byte
- func DecodePrimary(matrix *core.Bitmap, symbol *core.DecodedSymbol) int
- func DecodePrimaryMetadataPartI(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, ...) (ret int, syndromeOK bool)
- func DecodePrimaryMetadataPartII(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, ...) (ret int, syndromeOK bool)
- func DecodePrimaryOnDevice(device core.PrimaryDevice, matrix *core.Bitmap, symbol *core.DecodedSymbol) (ret int, handled bool)
- func DecodePrimaryResult(result core.PrimaryDeviceResult, matrix *core.Bitmap, ...) (ret int, handled bool)
- func DecodeSecondary(matrix *core.Bitmap, symbol *core.DecodedSymbol) int
- func DecodeSecondaryTraced(matrix *core.Bitmap, symbol *core.DecodedSymbol, ...) int
- func DecodeSymbol(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, ...) int
- func DecodeSymbolTraced(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, ...) int
- func LoadDefaultPrimaryMetadata(matrix *core.Bitmap, symbol *core.DecodedSymbol)
- func NormalizeColorPalette(symbol *core.DecodedSymbol, normPalette []float64, colorNumber int)
- func PaletteThreshold(palette []byte, colorNumber int) [3]float64
- func ReadColorPaletteInPrimary(matrix *core.Bitmap, symbol *core.DecodedSymbol, dataMap []byte, ...) int
- type Message
- type MessageControl
- type MessageControlKind
- type ModuleClassificationTrace
- type ModuleEvidenceCache
- type ObservationSnapshot
- type PrimaryObservation
- func ObservePrimary(matrix *core.Bitmap, symbol *core.DecodedSymbol) (*PrimaryObservation, int)
- func ObservePrimaryOnDevice(device core.MetadataDevice, matrix *core.Bitmap, symbol *core.DecodedSymbol, ...) (obs *PrimaryObservation, ret int, handled bool)
- func ObservePrimaryTraced(matrix *core.Bitmap, symbol *core.DecodedSymbol, trace *PrimaryTrace) (*PrimaryObservation, int)
- func (obs *PrimaryObservation) AdmitPayloadCorrection() bool
- func (obs *PrimaryObservation) CorrectPayload() int
- func (obs *PrimaryObservation) CorrectPayloadMergedPalette() int
- func (obs *PrimaryObservation) CorrectPayloadWithCache(cache *ModuleEvidenceCache) int
- func (obs *PrimaryObservation) FixedPatternAgreement() (agree, checked int)
- func (obs *PrimaryObservation) MetadataModules() int
- func (obs *PrimaryObservation) ModuleCosts(x, y int, dst []float64) []float64
- func (obs *PrimaryObservation) PaletteCoherence() (disagreement, separation float64)
- func (obs *PrimaryObservation) Snapshot() *ObservationSnapshot
- func (obs *PrimaryObservation) UseDevice(device core.PayloadDevice)
- func (obs *PrimaryObservation) UseGrid(grid core.GridDevice)
- type PrimaryTrace
Constants ¶
const MetadataFailed = -1
Decoder status/constant values.
Variables ¶
This section is empty.
Functions ¶
func BitLLRs ¶
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 ¶
DecodeData interprets the corrected bit stream into the decoded message, following the mode/latch/shift state machine.
func DecodeDataVariant ¶
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 ¶
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 ¶
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.
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.