{"id":35881840,"url":"https://github.com/zeriyoshi/liblierre","last_synced_at":"2026-02-26T08:47:53.310Z","repository":{"id":331919418,"uuid":"1129088443","full_name":"zeriyoshi/liblierre","owner":"zeriyoshi","description":"QR Encoder / Decoder, written in C99","archived":false,"fork":false,"pushed_at":"2026-01-11T16:53:32.000Z","size":11401,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-11T19:41:06.492Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://zeriyoshi.github.io/liblierre/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zeriyoshi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-06T15:34:02.000Z","updated_at":"2026-01-11T16:53:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zeriyoshi/liblierre","commit_stats":null,"previous_names":["zeriyoshi/liblierre"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/zeriyoshi/liblierre","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriyoshi%2Fliblierre","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriyoshi%2Fliblierre/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriyoshi%2Fliblierre/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriyoshi%2Fliblierre/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zeriyoshi","download_url":"https://codeload.github.com/zeriyoshi/liblierre/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriyoshi%2Fliblierre/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28400397,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-08T18:02:50.423Z","updated_at":"2026-01-13T21:56:41.005Z","avatar_url":"https://github.com/zeriyoshi.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# liblierre\n\n[![CI](https://github.com/zeriyoshi/liblierre/actions/workflows/ci.yaml/badge.svg)](https://github.com/zeriyoshi/liblierre/actions/workflows/ci.yaml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n**Lightweight Image Encoding \u0026 Reading for Resilient Encoded data**\n\n[🇯🇵 日本語版 README はこちら](README_ja.md)\n\nliblierre is a lightweight, high-performance QR code encoding and decoding library written in C99. It provides complete QR code generation and reading capabilities with optional SIMD acceleration for maximum performance.\n\n## Features\n\n- **Pure C99 Implementation** - No external dependencies (except libpoporon for Reed-Solomon), portable across platforms\n- **QR Code Generation** - Support for all QR versions (1-40), all error correction levels (L/M/Q/H), all mask patterns (0-7)\n- **QR Code Reading** - Advanced image preprocessing with multiple detection strategies\n- **SIMD Acceleration** - Automatic optimization using AVX2 (x86_64), NEON (ARM64), or WASM SIMD128\n- **WebAssembly Support** - Can be compiled to WASM using Emscripten\n- **Memory Safe** - Carefully designed API with proper resource management\n- **Extensive Testing** - Comprehensive test suite with sanitizer and Valgrind support\n\n## Quick Start\n\n### Building\n\n```bash\n# Clone the repository with submodules\ngit clone --recursive https://github.com/zeriyoshi/liblierre.git\ncd liblierre\n\n# Build with CMake\ncmake -B build -DCMAKE_BUILD_TYPE=Release\ncmake --build build\n```\n\n### Build Options\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `LIERRE_USE_SIMD` | `ON` | Enable SIMD optimizations |\n| `LIERRE_USE_TESTS` | `OFF` | Build test suite |\n| `LIERRE_USE_VALGRIND` | `OFF` | Enable Valgrind memory checking |\n| `LIERRE_USE_COVERAGE` | `OFF` | Enable code coverage |\n| `LIERRE_USE_ASAN` | `OFF` | Enable AddressSanitizer |\n| `LIERRE_USE_MSAN` | `OFF` | Enable MemorySanitizer |\n| `LIERRE_USE_UBSAN` | `OFF` | Enable UndefinedBehaviorSanitizer |\n| `BUILD_SHARED_LIBS` | `OFF` | Build shared library |\n\n### Running Tests\n\n```bash\ncmake -B build -DCMAKE_BUILD_TYPE=Debug -DLIERRE_USE_TESTS=ON\ncmake --build build\nctest --test-dir build --output-on-failure\n```\n\n## Usage Examples\n\n### Generating a QR Code\n\n```c\n#include \u003clierre.h\u003e\n#include \u003clierre/writer.h\u003e\n#include \u003cstdio.h\u003e\n#include \u003cstring.h\u003e\n\nint main(void) {\n    const char *text = \"Hello, World!\";\n    lierre_writer_param_t param;\n    lierre_rgba_t fill = {0, 0, 0, 255};      // Black\n    lierre_rgba_t bg = {255, 255, 255, 255};  // White\n\n    // Initialize parameters\n    lierre_writer_param_init(\n        \u0026param,\n        (uint8_t *)text,\n        strlen(text),\n        4,           // scale (4x)\n        2,           // margin (2 modules)\n        ECC_MEDIUM,  // error correction level\n        MASK_AUTO,   // auto-select mask pattern\n        MODE_BYTE    // byte mode\n    );\n\n    // Get output resolution\n    lierre_reso_t res;\n    lierre_writer_get_res(\u0026param, \u0026res);\n    printf(\"QR code size: %zux%zu\\n\", res.width, res.height);\n\n    // Create writer and generate\n    lierre_writer_t *writer = lierre_writer_create(\u0026param, \u0026fill, \u0026bg);\n    if (!writer) {\n        fprintf(stderr, \"Failed to create writer\\n\");\n        return 1;\n    }\n\n    if (lierre_writer_write(writer) == LIERRE_ERROR_SUCCESS) {\n        const uint8_t *rgba = lierre_writer_get_rgba_data(writer);\n        size_t size = lierre_writer_get_rgba_data_size(writer);\n        printf(\"Generated %zu bytes of RGBA data\\n\", size);\n        // Use RGBA data (save to file, display, etc.)\n    }\n\n    lierre_writer_destroy(writer);\n    return 0;\n}\n```\n\n### Reading a QR Code\n\n```c\n#include \u003clierre.h\u003e\n#include \u003clierre/reader.h\u003e\n#include \u003cstdio.h\u003e\n\nint main(void) {\n    // Assume you have RGB image data\n    uint8_t *rgb_data = /* your image data */;\n    size_t width = 640, height = 480;\n\n    // Create RGB data wrapper\n    lierre_rgb_data_t *rgb = lierre_rgb_create(\n        rgb_data, width * height * 3, width, height\n    );\n    if (!rgb) {\n        fprintf(stderr, \"Failed to create RGB container\\n\");\n        return 1;\n    }\n\n    // Initialize reader parameters\n    lierre_reader_param_t param;\n    lierre_reader_param_init(\u0026param);\n\n    // Optional: Enable preprocessing strategies\n    lierre_reader_param_set_flag(\u0026param, LIERRE_READER_STRATEGY_GLAYSCALE);\n    lierre_reader_param_set_flag(\u0026param, LIERRE_READER_STRATEGY_DENOISE);\n\n    // Create reader and decode\n    lierre_reader_t *reader = lierre_reader_create(\u0026param);\n    lierre_reader_set_data(reader, rgb);\n\n    lierre_reader_result_t *result = NULL;\n    if (lierre_reader_read(reader, \u0026result) == LIERRE_ERROR_SUCCESS) {\n        uint32_t count = lierre_reader_result_get_num_qr_codes(result);\n        printf(\"Found %u QR code(s)\\n\", count);\n\n        for (uint32_t i = 0; i \u003c count; i++) {\n            const uint8_t *data = lierre_reader_result_get_qr_code_data(result, i);\n            size_t size = lierre_reader_result_get_qr_code_data_size(result, i);\n            printf(\"QR[%u]: %.*s\\n\", i, (int)size, data);\n        }\n        lierre_reader_result_destroy(result);\n    }\n\n    lierre_reader_destroy(reader);\n    lierre_rgb_destroy(rgb);\n    return 0;\n}\n```\n\n## API Reference\n\n### Core Types\n\n```c\n// Error codes\ntypedef enum lierre_error {\n    SUCCESS = 0,\n    ERROR_INVALID_PARAMS,\n    ERROR_INVALID_GRID_SIZE,\n    ERROR_INVALID_VERSION,\n    ERROR_FORMAT_ECC,\n    ERROR_DATA_ECC,\n    ERROR_UNKNOWN_DATA_TYPE,\n    ERROR_DATA_OVERFLOW,\n    ERROR_DATA_UNDERFLOW,\n    ERROR_SIZE_EXCEEDED\n} lierre_error_t;\n\n// RGB image data container\ntypedef struct {\n    uint8_t *data;\n    size_t data_size;\n    size_t width;\n    size_t height;\n} lierre_rgb_data_t;\n\n// RGBA color\ntypedef struct {\n    uint8_t r, g, b, a;\n} lierre_rgba_t;\n\n// 2D vector and rectangle\ntypedef struct { size_t x, y; } lierre_vec2_t;\ntypedef struct { size_t width, height; } lierre_reso_t;\ntypedef struct { lierre_vec2_t origin; lierre_reso_t size; } lierre_rect_t;\n```\n\n### Writer API\n\n```c\n// Error correction levels\nECC_LOW, ECC_MEDIUM, ECC_QUARTILE, ECC_HIGH\n\n// Mask patterns\nMASK_AUTO, MASK_0 through MASK_7\n\n// Encoding modes\nMODE_NUMERIC, MODE_ALPHANUMERIC, MODE_BYTE, MODE_KANJI, MODE_ECI\n\n// Functions\nlierre_error_t lierre_writer_param_init(lierre_writer_param_t *param, ...);\nlierre_qr_version_t lierre_writer_qr_version(const lierre_writer_param_t *param);\nbool lierre_writer_get_res(const lierre_writer_param_t *param, lierre_reso_t *res);\nlierre_writer_t *lierre_writer_create(const lierre_writer_param_t *param,\n                                      const lierre_rgba_t *fill_color,\n                                      const lierre_rgba_t *bg_color);\nlierre_error_t lierre_writer_write(lierre_writer_t *writer);\nconst uint8_t *lierre_writer_get_rgba_data(const lierre_writer_t *writer);\nsize_t lierre_writer_get_rgba_data_size(const lierre_writer_t *writer);\nvoid lierre_writer_destroy(lierre_writer_t *writer);\n```\n\n### Reader API\n\n```c\n// Strategy flags (can be combined with |)\nLIERRE_READER_STRATEGY_NONE\nLIERRE_READER_STRATEGY_MINIMIZE          // Minimize image for easier detection\nLIERRE_READER_STRATEGY_GLAYSCALE         // Convert to grayscale\nLIERRE_READER_STRATEGY_USE_RECT          // Focus on specific area\nLIERRE_READER_STRATEGY_DENOISE           // Apply denoising filter\nLIERRE_READER_STRATEGY_BRIGHTNESS_NORMALIZE  // Normalize brightness\nLIERRE_READER_STRATEGY_CONTRAST_NORMALIZE    // Normalize contrast\nLIERRE_READER_STRATEGY_SHARPENING        // Apply sharpening filter\nLIERRE_READER_STRATEGY_MT                // Enable multi-threading\n\n// Functions\nlierre_error_t lierre_reader_param_init(lierre_reader_param_t *param);\nvoid lierre_reader_param_set_flag(lierre_reader_param_t *param, lierre_reader_strategy_flag_t flag);\nvoid lierre_reader_param_set_rect(lierre_reader_param_t *param, const lierre_rect_t *rect);\nlierre_reader_t *lierre_reader_create(const lierre_reader_param_t *param);\nvoid lierre_reader_set_data(lierre_reader_t *reader, lierre_rgb_data_t *data);\nlierre_error_t lierre_reader_read(lierre_reader_t *reader, lierre_reader_result_t **result);\nuint32_t lierre_reader_result_get_num_qr_codes(const lierre_reader_result_t *result);\nconst uint8_t *lierre_reader_result_get_qr_code_data(const lierre_reader_result_t *result, uint32_t index);\nsize_t lierre_reader_result_get_qr_code_data_size(const lierre_reader_result_t *result, uint32_t index);\nconst lierre_rect_t *lierre_reader_result_get_qr_code_rect(const lierre_reader_result_t *result, uint32_t index);\nvoid lierre_reader_result_destroy(lierre_reader_result_t *result);\nvoid lierre_reader_destroy(lierre_reader_t *reader);\n```\n\n### Utility Functions\n\n```c\nconst char *lierre_strerror(lierre_error_t err);   // Get error message\nuint32_t lierre_version_id(void);                  // Get library version\nlierre_buildtime_t lierre_buildtime(void);         // Get build timestamp\nlierre_rgb_data_t *lierre_rgb_create(...);         // Create RGB container\nvoid lierre_rgb_destroy(lierre_rgb_data_t *rgb);   // Destroy RGB container\n```\n\n## SIMD Support\n\nThe library automatically detects and enables SIMD optimizations based on the target architecture:\n\n| Platform | SIMD | Status |\n|----------|------|--------|\n| Linux x86_64 | AVX2 | ✅ Fully supported |\n| Linux ARM64 | NEON | ✅ Fully supported |\n| macOS x86_64 | AVX2 | ✅ Fully supported |\n| macOS ARM64 | NEON | ✅ Fully supported |\n| Windows x86_64 | AVX2 | ✅ Fully supported |\n| WebAssembly | SIMD128 | ✅ Fully supported |\n\nTo disable SIMD optimizations:\n```bash\ncmake -B build -DLIERRE_USE_SIMD=OFF\n```\n\n## Code Coverage\n\nTo generate coverage reports (requires GCC, `lcov`, and `genhtml`):\n\n```bash\ncmake -B build -DCMAKE_BUILD_TYPE=Debug \\\n               -DLIERRE_USE_TESTS=ON \\\n               -DLIERRE_USE_COVERAGE=ON\ncmake --build build\ncmake --build build --target coverage\n```\n\nThe HTML report will be generated at `build/coverage/html/index.html`.\n\n## Integration\n\n### Using CMake `find_package`\n\nAfter installation, use in your CMakeLists.txt:\n\n```cmake\nfind_package(Lierre REQUIRED)\ntarget_link_libraries(your_target PRIVATE lierre::lierre)\n```\n\n### Using CMake `add_subdirectory`\n\nAdd liblierre as a subdirectory in your project:\n\n```cmake\nadd_subdirectory(path/to/liblierre)\ntarget_link_libraries(your_target PRIVATE lierre)\n```\n\n### Integrating with Existing libpoporon\n\nIf your project already uses libpoporon, you can avoid duplicate symbol conflicts:\n\n```cmake\n# Your existing libpoporon setup\nadd_subdirectory(your/path/to/libpoporon)\n\n# liblierre will detect the existing poporon target and skip its bundled version\nadd_subdirectory(path/to/liblierre)\n\ntarget_link_libraries(your_target PRIVATE lierre)\n```\n\n## Project Structure\n\n```\nliblierre/\n├── include/\n│   ├── lierre.h           # Main header (types, errors, utilities)\n│   └── lierre/\n│       ├── reader.h       # QR reader API\n│       ├── writer.h       # QR writer API\n│       └── portable.h     # Cross-platform threading\n├── src/\n│   ├── lierre.c           # Core utilities\n│   ├── image.c            # Image processing\n│   ├── portable.c         # Platform abstraction\n│   ├── decode/            # QR decoding implementation\n│   │   ├── decode_qr.c    # QR decode logic\n│   │   ├── decoder.c      # Main decoder\n│   │   ├── decoder_detect.c   # QR detection\n│   │   ├── decoder_grid.c     # Grid processing\n│   │   └── reader.c       # Reader interface\n│   ├── encode/            # QR encoding implementation\n│   │   └── writer.c       # Writer interface\n│   └── internal/          # Internal headers\n│       ├── decoder.h      # Decoder internals\n│       ├── image.h        # Image processing internals\n│       ├── memory.h       # Memory management\n│       ├── simd.h         # SIMD abstractions\n│       └── structs.h      # Internal structures\n├── tests/                 # Unit tests (Unity framework)\n│   ├── test_lierre.c      # Core tests\n│   ├── test_portable.c    # Threading tests\n│   ├── test_qr_codec.c    # Encode/decode tests\n│   ├── test_reader.c      # Reader tests\n│   └── test_writer.c      # Writer tests\n├── third_party/\n│   ├── libpoporon/        # Reed-Solomon library\n│   ├── unity/             # Unity Test framework\n│   └── valgrind/          # Valgrind headers\n└── cmake/                 # CMake modules\n    ├── buildtime.cmake    # Build timestamp\n    ├── emscripten.cmake   # WebAssembly support\n    ├── test.cmake         # Test configuration\n    └── LierreConfig.cmake.in  # CMake package config\n```\n\n## Dependencies\n\n- **[libpoporon](https://github.com/zeriyoshi/libpoporon)** - Reed-Solomon error correction library (bundled)\n- **[Unity](https://github.com/ThrowTheSwitch/Unity)** - Unit testing framework (bundled, tests only)\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Author\n\n**Go Kudo** ([@zeriyoshi](https://github.com/zeriyoshi)) - [zeriyoshi@gmail.com](mailto:zeriyoshi@gmail.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeriyoshi%2Fliblierre","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzeriyoshi%2Fliblierre","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeriyoshi%2Fliblierre/lists"}