204 lines
7.8 KiB
Markdown
204 lines
7.8 KiB
Markdown
---
|
||
title: "Barcode Encoding Algorithms: EAN-13 & Code 128 Checksum Math from Scratch in JavaScript"
|
||
description: "A deep computer science exploration of 1D barcode encoding algorithms, covering Modulo 10 and Modulo 103 checksum calculations, building a free barcode generator and a code 128 barcode generator in TypeScript."
|
||
tags: javascript, typescript, algorithms, computer-science
|
||
keywords: free barcode generator, ean code generator, code 128 barcode generator, qr barcode, barcode code generator, free barcode, print barcode
|
||
canonical_url: https://www.qrmaster.net/blog/barcode-generator-tool
|
||
---
|
||
|
||
# Barcode Encoding Algorithms: EAN-13 & Code 128 Checksum Math from Scratch in JavaScript
|
||
|
||
Long before 2D QR codes dominated digital marketing, one-dimensional (1D) linear barcodes—such as **EAN-13** in retail products and **Code 128** in logistics and shipping—revolutionized inventory automation.
|
||
|
||
Building a **free barcode generator** or an **ean code generator** requires understanding that barcode scanner guns and camera libraries do not "guess" numbers from images; they decode precise binary bit patterns (bars and spaces) and verify mathematical **checksums** (Modulo 10 for EAN-13; Modulo 103 for Code 128).
|
||
|
||
In this deep computer science guide, we will examine the bit pattern structures of EAN-13 and Code 128, derive their checksum formulas, and implement a pure TypeScript **barcode code generator** without any external npm dependencies.
|
||
|
||
---
|
||
|
||
## 1. Deconstructing EAN-13 Retail Barcode Encoding
|
||
|
||
An **EAN-13** (European Article Number) barcode produced by an **ean code generator** encodes exactly 13 numeric digits:
|
||
- **First 2–3 digits**: Country Prefix (e.g., `400–440` for Germany, `000–019` for US/Canada).
|
||
- **Next 4–5 digits**: Manufacturer Identification Code.
|
||
- **Next 4–5 digits**: Unique Item / Product Code.
|
||
- **13th Digit**: Mathematical **Modulo 10 Checksum Digit**.
|
||
|
||
```
|
||
Country Manufacturer Product Check
|
||
┌──┴──┐ ┌────┴────┐ ┌───┴───┐ ┌┴┐
|
||
4 0 0 1 2 3 4 5 6 7 8 9 5
|
||
```
|
||
|
||
### The EAN-13 Modulo 10 Checksum Formula
|
||
To compute the 13th check digit for a 12-digit input in an **ean code generator**:
|
||
|
||
1. Sum all digits in **odd-numbered positions** (1st, 3rd, 5th, 7th, 9th, 11th).
|
||
2. Sum all digits in **even-numbered positions** (2nd, 4th, 6th, 8th, 10th, 12th) and multiply by 3.
|
||
3. Add the two sums together.
|
||
4. The check digit is the number required to reach the next multiple of 10:
|
||
|
||
$$\text{Check Digit} = (10 - (\text{Total Sum} \pmod{10})) \pmod{10}$$
|
||
|
||
### Checksum Example Calculation:
|
||
Take the 12-digit string `400123456789`:
|
||
- Odd sum: $4 + 0 + 2 + 4 + 6 + 8 = 24$
|
||
- Even sum: $(0 + 1 + 3 + 5 + 7 + 9) \times 3 = 25 \times 3 = 75$
|
||
- Total: $24 + 75 = 99$
|
||
- Check digit: $(10 - (99 \pmod{10})) \pmod{10} = (10 - 9) \pmod{10} = 1$
|
||
- Final 13-digit EAN-13 code: `4001234567891`
|
||
|
||
---
|
||
|
||
## 2. Deconstructing Code 128 High-Density Barcodes
|
||
|
||
While EAN-13 is strictly numeric, a **code 128 barcode generator** creates high-density alphanumeric barcode formats capable of encoding all 128 ASCII characters (uppercase/lowercase letters, digits, punctuation, and control codes).
|
||
|
||
### Code 128 Structure
|
||
A Code 128 **qr barcode** structure consists of:
|
||
1. **Start Character**: `Start A` (103), `Start B` (104), or `Start C` (105).
|
||
2. **Data Symbol Characters**: Each character is represented by 11 modules composed of 3 bars and 3 spaces.
|
||
3. **Check Character**: Modulo 103 checksum value.
|
||
4. **Stop Character**: 13-module pattern (`1100011101011`).
|
||
|
||
### The Code 128 Modulo 103 Checksum Formula
|
||
|
||
$$\text{Checksum Value} = \left( \text{Start Value} + \sum_{i=1}^{N} (i \times \text{Symbol Value}_i) \right) \pmod{103}$$
|
||
|
||
---
|
||
|
||
## 3. Pure TypeScript Barcode Engine (No External Dependencies)
|
||
|
||
Let's build a standalone TypeScript module (`src/services/barcodeEngine.ts`) for a **free barcode generator** that computes EAN-13 checksums and renders a vector SVG **print barcode**.
|
||
|
||
### `src/services/barcodeEngine.ts`
|
||
|
||
```typescript
|
||
export class BarcodeEngine {
|
||
/**
|
||
* Computes the Modulo 10 Checksum digit for a 12-digit EAN string in an ean code generator.
|
||
*/
|
||
public static calculateEAN13Checksum(digits12: string): number {
|
||
if (!/^\d{12}$/.test(digits12)) {
|
||
throw new Error('EAN-13 input must be exactly 12 numeric digits.');
|
||
}
|
||
|
||
let oddSum = 0;
|
||
let evenSum = 0;
|
||
|
||
for (let i = 0; i < 12; i++) {
|
||
const digit = parseInt(digits12[i], 10);
|
||
if (i % 2 === 0) {
|
||
oddSum += digit;
|
||
} else {
|
||
evenSum += digit;
|
||
}
|
||
}
|
||
|
||
const totalSum = oddSum + evenSum * 3;
|
||
const remainder = totalSum % 10;
|
||
return remainder === 0 ? 0 : 10 - remainder;
|
||
}
|
||
|
||
/**
|
||
* EAN-13 Binary Bit Patterns for L, G, and R encodings.
|
||
*/
|
||
private static L_PATTERNS = [
|
||
'0001101', '0011001', '0010011', '0111101', '0100011',
|
||
'0110001', '0101111', '0111011', '0110111', '0001011'
|
||
];
|
||
|
||
private static R_PATTERNS = [
|
||
'1110010', '1100110', '1101100', '1000010', '1011100',
|
||
'1001110', '1010000', '1000100', '1001000', '1110100'
|
||
];
|
||
|
||
/**
|
||
* Generates a crisp vector SVG string for an EAN-13 barcode.
|
||
*/
|
||
public static generateEAN13SVG(digits12: string): string {
|
||
const checkDigit = this.calculateEAN13Checksum(digits12);
|
||
const fullEan13 = digits12 + checkDigit.toString();
|
||
|
||
// Structural guard and center patterns
|
||
const GUARD_START = '101';
|
||
const GUARD_CENTER = '01010';
|
||
const GUARD_END = '101';
|
||
|
||
let bitPattern = GUARD_START;
|
||
|
||
// Encode Left 6 Digits (using L-Patterns for simplicity)
|
||
for (let i = 1; i <= 6; i++) {
|
||
const digit = parseInt(fullEan13[i], 10);
|
||
bitPattern += this.L_PATTERNS[digit];
|
||
}
|
||
|
||
bitPattern += GUARD_CENTER;
|
||
|
||
// Encode Right 6 Digits (using R-Patterns)
|
||
for (let i = 7; i <= 12; i++) {
|
||
const digit = parseInt(fullEan13[i], 10);
|
||
bitPattern += this.R_PATTERNS[digit];
|
||
}
|
||
|
||
bitPattern += GUARD_END;
|
||
|
||
// Render SVG
|
||
const moduleWidthPx = 3;
|
||
const heightPx = 120;
|
||
const totalWidthPx = bitPattern.length * moduleWidthPx + 40; // 40px margin
|
||
|
||
let svgPaths = '';
|
||
for (let i = 0; i < bitPattern.length; i++) {
|
||
if (bitPattern[i] === '1') {
|
||
const x = 20 + i * moduleWidthPx;
|
||
svgPaths += `<rect x="${x}" y="10" width="${moduleWidthPx}" height="${heightPx - 30}" fill="#000000" />`;
|
||
}
|
||
}
|
||
|
||
// Add human-readable numbers text below bars
|
||
const textSvg = `<text x="${totalWidthPx / 2}" y="${heightPx - 5}" font-family="monospace" font-size="16" text-anchor="middle">${fullEan13}</text>`;
|
||
|
||
return `
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${totalWidthPx} ${heightPx}" width="${totalWidthPx}" height="${heightPx}">
|
||
<rect width="100%" height="100%" fill="#FFFFFF" />
|
||
${svgPaths}
|
||
${textSvg}
|
||
</svg>`.trim();
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Verification & Testing
|
||
|
||
Let's write a unit test to verify checksum calculation and SVG rendering output.
|
||
|
||
```typescript
|
||
import { BarcodeEngine } from '../src/services/barcodeEngine';
|
||
|
||
describe('BarcodeEngine', () => {
|
||
test('should correctly compute EAN-13 Modulo 10 Checksum', () => {
|
||
// 400123456789 -> Check digit should be 1
|
||
const check = BarcodeEngine.calculateEAN13Checksum('400123456789');
|
||
expect(check).toBe(1);
|
||
});
|
||
|
||
test('should generate valid vector SVG string', () => {
|
||
const svg = BarcodeEngine.generateEAN13SVG('400123456789');
|
||
expect(svg).toContain('<svg');
|
||
expect(svg).toContain('4001234567891'); // Includes computed check digit
|
||
expect(svg).toContain('</svg>');
|
||
});
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
## Conclusion
|
||
|
||
Understanding the binary bit patterns and mathematical checksum algorithms behind 1D barcodes allows developers to build a fast **free barcode generator** without relying on heavy external dependencies.
|
||
|
||
To generate free high-resolution EAN-13, UPC-A, and Code 128 barcodes online, check out [QR Master Free Barcode Generator](https://www.qrmaster.net/blog/barcode-generator-tool).
|