Skip to content
willmortimerPublic

About

Advanced QR code generation library for JVM with advanced styling features, inspired by kozakenyz/qr-code-styling. Kotlin DSL, Spring Boot integration, SVG/PNG rendering, batch processing, and enterprise-ready architecture.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

39 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QRForge4J

QRForge4J is a multi-module JVM QR generation library written in Kotlin. It ships a core QR engine, SVG/PNG/JPEG/PDF output, a unified render pipeline, optional ZXing verification, a Kotlin DSL, batch helpers, server integrations for Ktor, Spring Boot, and Micronaut, a CLI, and a standalone Gradle plugin build.

Status

  • Current release: 2.0.0
  • Main multi-module build: ./gradlew build
  • Standalone Gradle plugin build: ./gradlew -p qrgen-gradle-plugin build
  • Java baseline: 17
  • Source builds require a locally available JDK 17 toolchain
  • Gradle wrapper: 9.4.0
  • Main repo Kotlin plugin: 2.3.10

Project status details are in documents/STATE_OF_REPO.md. Installation details are in documents/MAVEN_INSTALL.md.

Modules

Module Purpose
qrgen-core QR matrix generation, QrStyleConfig, templates/profiles, cache helpers
qrgen-svg SVG renderer with advanced styling
qrgen-png PNG and JPEG raster rendering (Batik-backed)
qrgen-pdf PDF output (raster QR embedded in page)
qrgen-render QrRenderPipeline and QrOutputFormat — single entry point for all output formats
qrgen-verify QrDecodeVerifier — ZXing decode/scannability checks on rendered images
qrgen-dsl Kotlin builder and fluent API
qrgen-cli Command-line interface
qrgen-batch Batch generation helpers
qrgen-test Integration tests, goldens, and benchmark entry points (not published for app use)
qrgen-ktor Ktor routes and helpers
qrgen-spring-boot-starter Spring Boot auto-configuration
qrgen-micronaut Micronaut controllers and services
qrgen-gradle-plugin Standalone Gradle plugin (nested build)

Typical dependency choices:

  • Styled SVG only: qrgen-core + qrgen-svg
  • PNG/JPEG in apps: add qrgen-png or depend on qrgen-render (pulls format modules transitively)
  • HTTP integrations: qrgen-ktor, qrgen-spring-boot-starter, or qrgen-micronaut
  • Post-render scan checks: qrgen-verify (lightweight; no Batik/PDF required)

Features

  • Module styles: circle, square, classy, rounded, extra-rounded, classy-rounded (DotType)
  • Neighbor-aware rounded modules and roundSize-style dynamic sizing
  • Corner locator styling with separate outer/inner shapes, per-corner overrides, and optional corner logos
  • Custom alignment pattern styling: square, circle, diamond, star
  • Background colors, rounded backgrounds, gradients, gradient masking, and background patterns
  • Quiet zone accents, module outlines, drop shadows, and micro typography
  • SVG animation presets: fade, pulse, draw-in
  • Center logo support with hole carving
  • JSON/YAML templates and named profile loading
  • Jackson JsonNode deep merge for template/profile overrides
  • SVG, PNG, JPEG, and PDF output through one pipeline

Local Development

With mise:

mise install
mise run build
mise run verify_integrations
mise run docs
mise run benchmarks
mise run build_plugin
mise run publish_local

With the Gradle wrapper:

./gradlew build
./gradlew -p qrgen-gradle-plugin build

mise manages the toolchain. If you build with the Gradle wrapper directly, make sure JDK 17 is installed and discoverable locally. The repo does not auto-download JDK toolchains from settings.gradle.kts.

Build version is taken from the current git tag when present (v2.0.0 → artifact version 2.0.0). Untagged working trees publish as 1.0.0-SNAPSHOT.

Installation

Published modules use group io.github.willmortimer and artifact ids that match the module names.

Detailed install guidance for GitHub Packages, mavenLocal(), and Ktor apps is in documents/MAVEN_INSTALL.md.

GitHub Packages repository:

repositories {
    mavenCentral()
    maven {
        url = uri("https://maven.pkg.github.com/willmortimer/QRForge4J")
        credentials {
            username = System.getenv("GITHUB_ACTOR")
            password = System.getenv("GITHUB_TOKEN")
        }
    }
}

Kotlin app — core + styled PNG:

dependencies {
    implementation("io.github.willmortimer:qrgen-render:2.0.0") // core, svg, png, pdf
    implementation("io.github.willmortimer:qrgen-verify:2.0.0") // optional decode checks
}

Kotlin app — DSL + Ktor:

dependencies {
    implementation("io.github.willmortimer:qrgen-dsl:2.0.0")
    implementation("io.github.willmortimer:qrgen-ktor:2.0.0")
}

Usage

Render pipeline (recommended)

QrRenderPipeline is the canonical way to generate any output format. Integrations, batch, CLI, and the Gradle plugin all delegate to it.

import io.github.qrgen.core.QrStyleConfig
import io.github.qrgen.render.QrOutputFormat
import io.github.qrgen.render.QrRenderPipeline

val pipeline = QrRenderPipeline()

val pngBytes = pipeline.render("https://example.com", QrStyleConfig(), QrOutputFormat.PNG)

val output = pipeline.renderOutput("https://example.com", QrStyleConfig(), QrOutputFormat.SVG)
// output.bytes, output.contentType, output.filename

Supported formats: SVG, PNG, JPEG, PDF. Parse user input with QrOutputFormat.parse("png").

Verify rendered output

Use qrgen-verify when you need to assert a PNG (or BufferedImage) still scans after styling:

import io.github.qrgen.verify.QrDecodeVerifier

val result = QrDecodeVerifier().verifyRenderedPng(pngBytes, "https://example.com")
check(result.isSuccessful && result.contentMatches)

Kotlin DSL

import io.github.qrgen.dsl.QRCode
import io.github.qrgen.core.LocatorFrameShape

val svg = QRCode.ofRoundedSquares()
    .size(640)
    .withColor("#111827")
    .backgroundCorners(28.0)
    .cornerLocators {
        rounded()
        logo("https://example.com/corner-logo.png")
        topRight {
            outer(LocatorFrameShape.DIAMOND)
        }
    }
    .alignmentPattern {
        star()
        color = "#0f766e"
    }
    .dotStyle {
        dynamicSize(0.92)
    }
    .animation {
        pulse()
        durationSeconds = 2.0
    }
    .buildSvg("https://example.com")

Direct API

Lower-level access when you want separate generate and render steps:

import io.github.qrgen.core.DefaultQrGenerator
import io.github.qrgen.core.QrStyleConfig
import io.github.qrgen.svg.DefaultSvgRenderer

val qr = DefaultQrGenerator().generateFromText("Hello QRForge4J", QrStyleConfig())
val svg = DefaultSvgRenderer().render(qr)

Ktor

import io.github.qrgen.ktor.qrGenRoutes
import io.ktor.server.application.Application
import io.ktor.server.routing.routing

fun Application.module() {
    routing {
        qrGenRoutes("/qr")
    }
}

Routes:

  • GET /qr/generate?data=...&format=PNG
  • POST /qr/generate (JSON body with data, optional format, style fields)
  • GET /qr/health

Format names match QrOutputFormat (SVG, PNG, JPEG, PDF).

Spring Boot

Auto-configuration registers QrRenderPipeline, QrGenService, and QrBatchProcessor. Inject QrGenService and call generateQr(data, format = QrOutputFormat.PNG).

CLI

echo "https://example.com" | ./gradlew qrgen-cli:run --args="--format pdf --dots rounded --round-size --corner-style classy --alignment-shape star --output qr.pdf"

Templates and profiles

profile: kiosk
config:
  layout:
    width: 640
    height: 640
    margin: 24
  modules:
    type: ROUNDED
  alignmentPatterns:
    enabled: true
    shape: STAR

Load with QrConfigIO.readTemplate(...) and merge through QrProfileRegistry.merge(...).

Merge rules (2.0):

  • Key absent in template config → keep base profile value
  • Key present as JSON/YAML null → clear nullable field on base
  • Object values → recursive merge
  • Scalars and arrays → replace base value

Register named profiles with full configs or JsonNode patches:

registry.register("kiosk", patchJsonNode)
registry.register("minimal", QrStyleConfig())

Upgrading from 1.x

2.0 is a breaking release. Main changes:

Removed / changed Migration
QrStyleConfigPatch, QrStyleConfigMerger, OptionalField Use QrConfigMerger.merge(base, jsonPatch) or QrProfileRegistry.register(name, JsonNode)
Per-module format enums (QrFormat, QrKtorFormat, etc.) Use io.github.qrgen.render.QrOutputFormat
ModuleOptions.rounded, extraRounded, classyRounded Set modules.type / DSL DotType instead (booleans were unused in library render path)
Decode helpers only in qrgen-test Use qrgen-verify artifact: QrDecodeVerifier
Java2DPngRenderer Use BatikPngRenderer via QrRenderPipeline; Java2D class is deprecated and throws

Integration modules now take QrOutputFormat in service methods. Batch output format strings still accept svg, png, jpeg, pdf (case-insensitive).

Publishing

Published modules are configured for GitHub Packages. The release workflow lives at .github/workflows/release.yml and runs on GitHub Release published events.

Tag releases as v2.0.0 (with v prefix). Gradle derives the Maven version from that tag.

Required environment variables for GitHub Packages:

  • GITHUB_ACTOR
  • GITHUB_TOKEN

Optional Maven Central release secrets for GitHub Actions:

  • CENTRAL_PORTAL_USERNAME
  • CENTRAL_PORTAL_PASSWORD
  • SIGNING_KEY
  • SIGNING_PASSWORD

Local publishing:

./gradlew publishAllToMavenLocal
./gradlew -p qrgen-gradle-plugin publishToMavenLocal

Maven Central publishing:

./gradlew releaseToCentralPortal
./gradlew -p qrgen-gradle-plugin releaseToCentralPortal

API docs:

./gradlew verifyDocs

Notes

  • app/ is legacy sample code and is not part of the published library.
  • ported-library/qr-code-styling-master/ is a vendored JS reference, not a Kotlin module.
  • PDF output embeds a rendered QR image in the page. It is suitable for distribution and scanning tests, but it is not a vector PDF renderer.
  • BatikPngRenderer is the supported production raster path. Java2DPngRenderer is deprecated and throws until a real lightweight rasterizer lands in a future release.
  • Template/profile merging uses Jackson JsonNode deep merge on QrStyleConfig; explicit JSON/YAML null clears nullable fields.

License

MIT License. See LICENSE.

About

Advanced QR code generation library for JVM with advanced styling features, inspired by kozakenyz/qr-code-styling. Kotlin DSL, Spring Boot integration, SVG/PNG rendering, batch processing, and enterprise-ready architecture.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages