qrc

QR code encoder for MoonBit - port of dbuenzli/qrc

qr-code
encoder
barcode
moon add bobzhang/qrc@0.1.1
Download zip
Author
Version
0.1.1
License
ISC
Last updated
3 months ago
Downloads
32
README

#qrc — QR code encoder for MoonBit

Qrc encodes your data into QR codes. It has built-in QR matrix renderers for SVG, ANSI terminal and text.

This is a MoonBit port of the original OCaml qrc library by Daniel Bünzli.

#Features

  • ✅ QR code encoding with multiple data modes (numeric, alphanumeric, byte)
  • ✅ Automatic mode detection
  • ✅ Multiple output formats: SVG, ANSI terminal, plain text, compact text
  • ✅ Reed-Solomon error correction with Galois Field arithmetic
  • ✅ No external dependencies
  • ✅ WebAssembly compatible
  • ⚠️ Kanji mode (treated as byte mode)

#Installation

moon install bobzhang/qrc

#Usage

#Basic Usage

///|
test {
// Generate a QR code with default settings
let qr = @bobzhang/qrc.encode("Hello, MoonBit!")

// Print QR code information
println(@bobzhang/qrc/render.info(qr))

// Render as text
println(@bobzhang/qrc/render.to_text(qr))

// Render as compact text (using Unicode block characters)
println(@bobzhang/qrc/render.to_compact_text(qr))

// Render as SVG
let svg = @bobzhang/qrc/render.to_svg(qr)
println(svg)

// Render as ANSI terminal output (with colors)
println(@bobzhang/qrc/render.to_ansi(qr))
}

#Advanced Usage

///|
test {
// Generate QR code with specific error correction level
let qr = @qrc.encode_with_ec("Important data", H)

// Manual mode detection
let mode = @qrc.detect_mode("12345") // Returns Mode::Numeric
let mode2 = @qrc.detect_mode("HELLO WORLD") // Returns Mode::Alphanumeric
let mode3 = @qrc.detect_mode("Hello, World!")
// Returns Mode::Byte
}

#Data Modes

The library automatically detects the best encoding mode:

  • Numeric: Only digits 0-9 (most efficient for numbers)
  • Alphanumeric: Digits, uppercase letters A-Z, and symbols $%*+-./:
  • Byte: Any data (UTF-8 encoded)
  • Kanji: Japanese characters (currently treated as byte mode)

#Error Correction Levels

  • L: ~7% correction capability
  • M: ~15% correction capability (default)
  • Q: ~25% correction capability
  • H: ~30% correction capability

#Example Output

QR Code Information: Version: 1 Size: 21x21 Mode: Byte Error Correction: M (~15%) Data: "Hello, MoonBit!" Text representation: ██████████████ ████ ██████████████ ██ ██ ████ ██ ██ ██ ██████ ██ ████ ██ ██████ ██ ██ ██████ ██ ████ ██ ██████ ██ ██ ██████ ██ ████ ██ ██████ ██ ██ ██ ████ ██ ██ ██████████████ ████ ██████████████ ████ ████████████████████████████████████ ...

#API Reference

#Core Functions

  • encode(data: String) -> QRCode - Generate QR code with default error correction
  • encode_with_ec(data: String, ec: ErrorCorrectionLevel) -> QRCode - Generate QR code with specific error correction
  • detect_mode(data: String) -> Mode - Detect the best encoding mode for data

#Rendering Functions

  • @render.to_text(qr: QRCode) -> String - Plain text representation
  • @render.to_compact_text(qr: QRCode) -> String - Compact Unicode representation
  • @render.to_svg(qr: QRCode) -> String - SVG format
  • @render.to_ansi(qr: QRCode) -> String - ANSI terminal with colors
  • @render.info(qr: QRCode) -> String - QR code information

#Running the Example

# Clone the repository git clone <repository-url> cd qrc # Run tests moon test # Run the example moon run src

#Limitations

This is a functional implementation demonstrating MoonBit capabilities:

  • ✅ Full Reed-Solomon error correction with proper Galois Field arithmetic
  • ✅ Supports all error correction levels (L, M, Q, H)
  • ✅ Proper data formatting with mode indicators and padding
  • ✅ QR version 1 (21x21 modules) with finder patterns and timing patterns
  • ⚠️ Kanji mode is treated as byte mode
  • ⚠️ No format information or version information encoding
  • ⚠️ No masking patterns applied

The Reed-Solomon implementation includes:
  • Complete GF(256) Galois Field arithmetic
  • Generator polynomial computation
  • Proper error correction codeword generation
  • Data capacity management for different error correction levels

For production use with higher versions and advanced features, consider extending this implementation.

#Contributing

This project demonstrates porting OCaml code to MoonBit. Contributions to improve the implementation are welcome!

#License

ISC License - same as the original OCaml library.

#Acknowledgments

  • Original OCaml qrc library by Daniel Bünzli
  • MoonBit language team for the excellent tooling and documentation

#
Version

type Version = Int

#
ErrorCorrectionLevel

pub(all) enum ErrorCorrectionLevel {
L
M
Q
H
} derive(Eq)

#
MaskPattern

pub enum MaskPattern {
Pattern0
Pattern1
Pattern2
Pattern3
Pattern4
Pattern5
Pattern6
Pattern7
} derive(Eq)

#
Matrix

pub struct Matrix {
size : Int
modules : Array[Array[Module]]
}

#
Mode

pub enum Mode {
Numeric
Alphanumeric
Byte
Kanji
} derive(Eq)

#
Module

pub enum Module {
Light
Dark
} derive(Eq)

#
QRCode

pub struct QRCode {
version : Int
error_correction : ErrorCorrectionLevel
mode : Mode
data : String
matrix : Matrix
}

#
apply_error_correction

fn apply_error_correction(data : Array[Int], mode : Mode, version : Int, ec_level : ErrorCorrectionLevel) -> Array[Int]

#
apply_mask

fn apply_mask(matrix : Matrix, pattern : MaskPattern) -> Unit

#
choose_best_mask

fn choose_best_mask(matrix : Matrix, ec_level : ErrorCorrectionLevel) -> MaskPattern

#
detect_mode

fn detect_mode(data : String) -> Mode

#
encode

fn encode(data : String) -> QRCode

#
encode_alphanumeric

fn encode_alphanumeric(data : String) -> Array[Int]

#
encode_byte

fn encode_byte(data : String) -> Array[Int]

#
encode_data

fn encode_data(data : String, mode : Mode) -> Array[Int]

#
encode_kanji

fn encode_kanji(data : String) -> Array[Int]

#
encode_numeric

fn encode_numeric(data : String) -> Array[Int]

#
encode_version_info

fn encode_version_info(version : Int) -> Int

#
encode_with_ec

fn encode_with_ec(data : String, ec : ErrorCorrectionLevel) -> QRCode

#
encode_with_mode_and_ec

fn encode_with_mode_and_ec(data : String, mode : Mode, version : Int, ec : ErrorCorrectionLevel) -> QRCode

#
evaluate_mask_penalty

fn evaluate_mask_penalty(matrix : Matrix) -> Int

#
find_minimum_version

fn find_minimum_version(data : String, mode : Mode, ec_level : ErrorCorrectionLevel) -> Int

#
generate_qr

fn generate_qr(data : String, error_correction : ErrorCorrectionLevel) -> QRCode

#
generate_qr_with_mask

fn generate_qr_with_mask(data : String, error_correction : ErrorCorrectionLevel) -> QRCode

#
get_alignment_positions

fn get_alignment_positions(version : Int) -> Array[Int]

#
get_data_capacity

fn get_data_capacity(version : Int, ec_level : ErrorCorrectionLevel) -> Int

#
get_error_correction_codewords

fn get_error_correction_codewords(version : Int, ec_level : ErrorCorrectionLevel) -> Int

#
get_module

fn get_module(matrix : Matrix, x : Int, y : Int) -> Module

#
gf_div

fn gf_div(a : Int, b : Int) -> Int

#
gf_mul

fn gf_mul(a : Int, b : Int) -> Int

#
init_matrix

fn init_matrix(version : Int) -> Matrix

#
is_data_position

fn is_data_position(matrix : Matrix, x : Int, y : Int) -> Bool

#
is_kanji_character

fn is_kanji_character(c : Int) -> Bool

#
make_byte_mode

fn make_byte_mode() -> Mode

#
make_ec_level_h

fn make_ec_level_h() -> ErrorCorrectionLevel

#
make_ec_level_l

fn make_ec_level_l() -> ErrorCorrectionLevel

#
make_ec_level_m

fn make_ec_level_m() -> ErrorCorrectionLevel

#
make_ec_level_q

fn make_ec_level_q() -> ErrorCorrectionLevel

#
make_kanji_mode

fn make_kanji_mode() -> Mode

#
make_mask_pattern_0

fn make_mask_pattern_0() -> MaskPattern

#
new_matrix

fn new_matrix(size : Int) -> Matrix

#
set_module

fn set_module(matrix : Matrix, x : Int, y : Int, mod : Module) -> Unit

#
version_to_size

fn version_to_size(version : Int) -> Int

Source Files