Skip to content

Postal 4-state formats

Sythos Barcode Universal includes a small, dependency-free postal family. These symbols are not one interchangeable barcode: every postal operator chose its own bar-state alphabet, framing rules and payload envelope. The SDK keeps those boundaries explicit while sharing one strict height-coded raster reader.

Supported formats

Format Runtime id Write Read Payload contract
USPS POSTNET postnet 5, 9 or 11 body digits; a Mod-10 check digit is generated and verified.
USPS PLANET planet 11 or 13 body digits; a Mod-10 check digit is generated and verified.
Royal Mail 4-State Customer Code rm4scc Upper-case letters and digits; a Royal Mail check character is generated and verified.
KIX kix Dutch postal alphabet (0–9, A–Z); no check character is added.
Australia Post 4-State auspost Two-digit FCC + eight-digit DPID + optional customer data, with RS(4) parity.
Japan Post 4-State japanpost Digits, upper-case letters and -; the fixed symbol carries padding and a Mod-19 check.
USPS Intelligent Mail Barcode imb The four legal 20-, 25-, 29- and 31-digit routing/ZIP payload lengths.

All seven entries are reported as canWrite: true and canRead: true by listFormats(). The reader returns the canonical id shown above even when an alias was requested.

Writing

The family is available from the oned subpath and through the root encode() dispatcher:

import {
  encodeAustraliaPost,
  encodeIMB,
  encodeJapanPost,
  encodeKIX,
  encodePlanet,
  encodePostnet,
  encodeRM4SCC,
} from '@sythos/js_barcode_universal/oned';

const postnet = encodePostnet('12345');
const planet = encodePlanet('12345678901');
const royalMail = encodeRM4SCC('HELLO1');
const kix = encodeKIX('123ABC');
const japan = encodeJapanPost('12ABC-9');
const australia = encodeAustraliaPost('5956439111ABC');
const intelligentMail = encodeIMB('01234567094987654321');

The root dispatcher accepts the same ids:

import { encode, toImageData } from '@sythos/js_barcode_universal';

const matrix = encode('12345', { format: 'postnet' });
const image = toImageData(matrix, {
  scale: 3,
  margin: 24,
  barHeight: 72,
});

Linear encoders return a compact BitMatrix; the renderer supplies the print height and quiet zone. A postal matrix uses one light module between adjacent bars so a raster reader can measure the state transitions without relying on a particular device pixel size.

POSTNET and PLANET

POSTNET accepts a five-, nine- or eleven-digit body. PLANET accepts an eleven- or thirteen-digit body. The writer appends the operator's Mod-10 check bar automatically. To supply a complete value that already includes the check bar, pass checkDigit: true; the final digit is then verified before it is reused:

const checked = encode('123455', {
  format: 'postnet',
  checkDigit: true,
});

The decoder validates the check bar and returns only the body (12345 in the example), with checkDigit: true in the result metadata. Half-height POSTNET and PLANET bars are aligned to the lower edge of the eight-module postal profile, as required by their physical grammar.

RM4SCC

RM4SCC accepts upper-case letters and digits. A check character is generated from the row and column sums of the payload. Most callers pass the body and let the writer append it:

const code = encodeRM4SCC('SW1A1AA');

When a complete body plus check character is supplied, checkDigit: true requires that character to match. Lower-case input and punctuation are rejected at the API boundary instead of becoming an accidental bar pattern.

KIX

KIX uses the Dutch 4-state alphabet for digits and upper-case letters. It has no check character, so checkDigit is false in a decoded result. KIX is still structurally strict: every four-state glyph must be complete and the image must not be truncated.

const kix = encodeKIX('1234ABCD');

Japan Post

Japan Post accepts digits, upper-case letters and a dash. Letters are expanded into the format's two-group representation, unused groups are padded, and a Mod-19 check group is added:

const japan = encodeJapanPost('123-ABC');

The decoder removes padding and reconstructs the original text. It rejects a wrong check group, an invalid alphabet value, a missing two-module start/stop frame or a partially captured 67-state symbol.

Australia Post

Australia Post starts with a two-digit Format Control Code (FCC) followed by the eight-digit DPID. The FCC selects the legal symbol length. Remaining capacity is customer data, protected by the format's GF(64) Reed–Solomon parity.

Customer data can be encoded as the public character alphabet (the default) or as compact numeric pairs:

const characterData = encodeAustraliaPost('5956439111ABC', {
  customerEncoding: 'character',
});

const numericData = encodeAustraliaPost('595643911112345', {
  customerEncoding: 'numeric',
});

custinfoenc is accepted as a compatibility alias. On decode, the reader tries both public alphabets when no preference is supplied. Applications that know the producer's mode should pass customerEncoding: 'character' or 'numeric'; this avoids treating an ambiguous clean raster as a different customer-data spelling.

The decoded text includes the FCC and DPID, followed by the recovered customer data. Unsupported FCC values, over-capacity customer data, invalid characters and parity failures produce no result.

USPS Intelligent Mail (IMb / OneCode)

IMb carries 20, 25, 29 or 31 decimal digits. The writer validates the exact length, computes the 11-bit frame check sequence and maps the resulting codewords to the 65 four-state bars. onecode and usps-onecode are aliases for the canonical imb id:

const imb = encode('01234567094987654321', { format: 'onecode' });

The reader reconstructs the codeword envelope, verifies the frame check sequence and returns the original digit string. It does not return a partial ZIP/routing fragment when one or more bars are missing. The 31-digit profile is decoded only when its routing envelope and frame check are self-consistent.

Reading images

All postal readers are available through the normal RGBA image boundary:

import { decode, toImageData } from '@sythos/js_barcode_universal';

const image = toImageData(encode('HELLO1', { format: 'rm4scc' }), {
  scale: 4,
  margin: 32,
  barHeight: 96,
});

const [result] = decode(image, { formats: ['rm4scc'] });
console.log(result?.format, result?.text, result?.checkDigit);
// rm4scc HELLO1 true

The image path first classifies the four bar heights, then validates the exact start/stop frame, glyph alphabet and format-specific checksum. A symbol that is clipped, ambiguous, damaged or not one of the requested formats returns an empty array. The same rule applies when the image contains convincing-looking noise: plausible text is not promoted to application data without structural proof.

For camera capture, opt into the stricter profile:

const hits = decode(cameraFrame, {
  formats: ['postnet', 'imb'],
  profile: 'camera',
  tryHarder: true,
});

The camera profile requires a measurable quiet zone on both sides of the bars and a complete, coherent symbol. Postal decoding uses the supported fixed orientation retry policy; it does not promise arbitrary projective distortion, curved media, severe glare or multiple overlapping symbols.

Aliases and result ids

Alias Canonical result id
usps-postnet postnet
usps-planet planet
royalmail, royal-mail rm4scc
australia-post, australiapost auspost
japan-post japanpost
onecode, usps-onecode imb

The aliases are convenience selectors, not new symbologies. A result's format is always the canonical id so applications can use a stable switch.

Verification and licensing boundary

The implementation is original Sythos TypeScript with generated JavaScript and no runtime dependency. Public format descriptions were used to implement the state alphabets, checks and geometry. BWIPP/bwip-js output was invoked only as an independent black-box validation oracle; no third-party source, lookup table or runtime package is copied into or shipped by the SDK. The exact provenance, patent and trademark review boundary is recorded in licenses/postal.license and NOTICE.md. Format names remain descriptive and do not claim postal-operator certification.