moonqr

    Pure QR code encoder/decoder written in MoonBit

    qrcode
    qr
    Download zip
    Version
    0.2.0
    License
    Apache-2.0
    Last updated
    last month
    Downloads
    50

    #naoto24kawa/moonqr

    Pure QR code encoder/decoder written in MoonBit — no JavaScript dependencies, no WASM runtime coupling. This is the MoonBit-native module published to mooncakes.io; it is also the source compiled to JS and shipped as the npm packages @elchika-inc/moonqr and @elchika-inc/moonqr-scanner — see the repository README for the JS/TS side (if you're building a Node.js or browser app, you probably want the npm packages, not this module directly).

    #Packages

    PackageWhat it is
    naoto24kawa/moonqr/gf256GF(256) arithmetic + Reed–Solomon encode/decode, used by both encode and decode
    naoto24kawa/moonqr/encodeText → QR Matrix (module placement, masking, format/version info) + SVG rendering
    naoto24kawa/moonqr/decodeRGBA pixels → decoded text (binarization, finder-pattern location, perspective extraction, codeword decode); ported from jsQR

    preferred-target is js — see the root README's "Why MoonBit" section for the js vs wasm-gc benchmark that motivated this choice.

    The bench package (a Phase-1 backend-selection spike, not part of the public API) is excluded from the published artifact via moon.mod.json's exclude field.

    #Install

    moon add naoto24kawa/moonqr

    #Usage

    #Encode

    let matrix = @encode.encode("HELLO WORLD", @encode.EcLevel::M, None)
    match matrix {
    Some(m) => {
    // m.size x m.size module grid; m.get(x, y) : Bool (true = dark module)
    let svg = @encode.to_svg_string(m, 4, 8) // margin=4 modules, cell=8px
    ...
    }
    None => ... // capacity exceeded, or an explicit `version` too small for the text
    }

    encode(text, ec, version) returns Matrix?: None for an empty string or when the text doesn't fit the given/selected version. Pass version=None to auto-select the smallest QR version (1–40) that fits; pass Some(v) to force one.

    #Decode

    // data: RGBA bytes, width * height * 4 long
    let result = @decode.decode(data, width, height, true) // invert=true also tries the inverted binarization
    match result {
    Some(r) => {
    // r.text : String, r.bytes : Array[Int], r.version : Int,
    // r.ec : @encode.EcLevel, r.corners : Array[Point] (TL, TR, BR, BL, in pixel space)
    ...
    }
    None => ... // no QR code found in the frame
    }

    #License and attribution

    Apache License 2.0 — see LICENSE.

    Portions of decode are ported from jsQR (Apache-2.0), and the Reed–Solomon block / alignment-pattern position tables in encode are derived from qrcode-generator (MIT). See NOTICE and THIRD_PARTY_LICENSES for the full attribution.