A pure Swift library for generating Aztec 2D barcodes. This library implements the ISO/IEC 24778 standard for Aztec Code symbology.
- Encode strings, byte arrays, and
Dataobjects into Aztec symbols - Automatic mode selection for optimal encoding (Upper, Lower, Digit, Punct, Mixed, Byte)
- Configurable error correction levels
- Support for both compact and full-range symbols
- Thread-safe: all types conform to
Sendable - No unsafe memory operations
- Swift 5.9+
- iOS 15.0+ / macOS 12.0+ / tvOS 15.0+ / watchOS 8.0+ / visionOS 1.0+
Add AztecLib to your Package.swift dependencies:
dependencies: [
.package(url: "https://github.com/ts95/AztecLibSwift.git", from: "1.0.1")
]Then add it to your target dependencies:
.target(
name: "YourApp",
dependencies: ["AztecLib"]
)- File → Add Package Dependencies
- Enter the repository URL
- Select latest version
import AztecLib
// Encode a string
let symbol = try AztecEncoder.encode("Hello, World!")
// Access the symbol data
print("Symbol size: \(symbol.size)x\(symbol.size) modules")
print("Bytes per row: \(symbol.rowStride)")
// Check individual modules (pixels)
let isDark = symbol[x: 0, y: 0] // true = dark module, false = lightAztecLib includes SwiftUI views for easy barcode display:
import AztecLib
import SwiftUI
struct ContentView: View {
var body: some View {
// Simple usage - encode and display in one step
AztecCodeView("Hello, World!")
.frame(width: 200, height: 200)
// Or use a pre-encoded symbol
let symbol = try! AztecEncoder.encode("Hello")
AztecSymbolView(symbol: symbol)
.frame(width: 200, height: 200)
}
}The main entry point for encoding data into Aztec symbols.
// Simple encoding with defaults
let symbol = try AztecEncoder.encode("Your text here")
// With custom options
let options = AztecEncoder.Options(
errorCorrectionPercentage: 33, // 33% error correction
preferCompact: true, // Prefer smaller symbols
exportMSBFirst: false // LSB-first bit ordering
)
let symbol = try AztecEncoder.encode("Your text here", options: options)// Encode a byte array
let bytes: [UInt8] = [0x48, 0x65, 0x6C, 0x6C, 0x6F]
let symbol = try AztecEncoder.encode(bytes)
// Encode Foundation Data
let data = Data([0x01, 0x02, 0x03])
let symbol = try AztecEncoder.encode(data)// Get both the symbol and configuration details
let result = try AztecEncoder.encodeWithDetails("Hello")
print("Compact symbol: \(result.configuration.isCompact)")
print("Layers: \(result.configuration.layerCount)")
print("Data codewords: \(result.configuration.dataCodewordCount)")
print("Parity codewords: \(result.configuration.parityCodewordCount)")Configuration options for encoding.
| Property | Type | Default | Description |
|---|---|---|---|
errorCorrectionPercentage |
UInt |
23 | Percentage of codewords dedicated to error correction (higher = more resilient, larger symbol) |
preferCompact |
Bool |
true | Prefer compact symbols over full symbols when both would fit |
exportMSBFirst |
Bool |
false | Bit ordering: false = LSB-first, true = MSB-first (for PNG compatibility) |
The output of encoding, representing the 2D barcode matrix.
let symbol = try AztecEncoder.encode("Test")
// Properties
symbol.size // Int: side length in modules (e.g., 15 for 15x15)
symbol.rowStride // Int: bytes per row in the packed data
symbol.bytes // Data: the packed bitmap data
// Subscript access to individual modules
let isDark = symbol[x: 5, y: 5] // Returns BoolThe bytes property contains row-major packed bitmap data. Each row is rowStride bytes long, with modules packed into bits.
LSB-first (default): Bit 0 of each byte is the leftmost module.
// Example: Render to a simple ASCII representation
func renderASCII(_ symbol: AztecSymbol) -> String {
var result = ""
for y in 0..<symbol.size {
for x in 0..<symbol.size {
result += symbol[x: x, y: y] ? "██" : " "
}
result += "\n"
}
return result
}MSB-first (PNG compatible): Use exportMSBFirst: true when the renderer expects bit 7 to be the leftmost pixel.
Returned by encodeWithDetails(), contains the selected symbol parameters.
| Property | Type | Description |
|---|---|---|
isCompact |
Bool |
true for compact symbols (1-4 layers), false for full |
layerCount |
Int |
Number of data layers (1-4 compact, 4-32 full) |
wordSizeInBits |
Int |
Codeword size: 6, 8, 10, or 12 bits |
totalCodewordCount |
Int |
Total codewords in the symbol |
dataCodewordCount |
Int |
Codewords available for data |
parityCodewordCount |
Int |
Codewords used for error correction |
do {
let symbol = try AztecEncoder.encode(veryLongString)
} catch AztecEncoder.EncodingError.payloadTooLarge(let bitCount) {
print("Data too large: \(bitCount) bits exceeds maximum capacity")
} catch {
print("Encoding failed: \(error)")
}| Layers | Size | Max Data Bits |
|---|---|---|
| 1 | 15×15 | ~50 |
| 2 | 19×19 | ~170 |
| 3 | 23×23 | ~300 |
| 4 | 27×27 | ~470 |
Full symbols range from 31×31 (layer 4) to 151×151 (layer 32), supporting up to ~12,000 bits of data.
All types in AztecLib conform to Sendable and can be safely used from any thread:
Task.detached {
let symbol = try AztecEncoder.encode("Background encoding")
// Safe to use symbol here
}For advanced use cases, you can access the encoding pipeline components directly:
import AztecLib
// Step 1: Encode data to bits
let dataBits = AztecDataEncoder.encode("Hello")
// Step 2: Select configuration
let config = try pickConfiguration(
forPayloadBitCount: dataBits.bitCount,
errorCorrectionPercentage: 23,
preferCompact: true
)
// Step 3: Pack into codewords
let codewords = dataBits.makeCodewords(codewordBitWidth: config.wordSizeInBits)
// Step 4: Add Reed-Solomon parity
let gf = GaloisField(
wordSizeInBits: config.wordSizeInBits,
primitivePolynomial: config.primitivePolynomial
)
let rs = ReedSolomonEncoder(field: gf, startExponent: config.rsStartExponent)
let allCodewords = rs.appendingParity(
to: codewords,
parityCodewordCount: config.parityCodewordCount
)
// Step 5: Build the matrix
let builder = AztecMatrixBuilder(configuration: config)
let modeMessage = builder.encodeModeMessage()
let matrix = builder.buildMatrix(dataCodewords: allCodewords, modeMessageBits: modeMessage)
// Step 6: Export
let symbol = matrix.makeSymbolExport(
matrixSize: builder.symbolSize,
rowOrderMostSignificantBitFirst: false
)For detailed explanations of the algorithms and mathematics used in this library, see the AztecLib/Docs/ directory:
- Overview - What Aztec codes are and how they work
- Encoding Pipeline - How data becomes a barcode
- Mode Encoding - Text compression using modes
- Galois Fields - The math behind error correction
- Reed-Solomon - How error correction works
- Symbol Layout - Structure of an Aztec barcode
This library was primarily developed with the assistance of Claude Code (Claude Opus 4.5), Anthropic's AI coding assistant. The implementation draws inspiration from ZXing ("Zebra Crossing"), the open-source barcode processing library.
MIT License
- ISO/IEC 24778:2008 - Information technology — Automatic identification and data capture techniques — Aztec Code bar code symbology specification