Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
# @suaveplan/emblem-solver - Minimal-rectangle SVG converter for pixelated sprite emblems: layered occlusion, overlapping rect optimisation, dual-axis maximal rectangles, strip decomposition, and exhaustive layer ordering
Minimal-rectangle SVG converter for pixelated sprite emblems.
Converts a pixel grid (`RGBA[]`) into the smallest possible set of
axis-aligned coloured rectangles by combining four covering strategies
(dual-axis maximal rectangles + greedy cover, per-island independent
cover, strip decomposition, adjacent-rect merge), pairwise + triple-wise
overlap reductions, and exhaustive z-stacking search across up to 8! layer
orderings. Outputs a deterministic SVG string ready for direct embedding
or further compression.
<!-- begin:auto-docs -->
## Documentation tree
- [converter](./src/converter/converter.md) — This module is the public-facing entry point of `@suaveplan/emblem-solver`. It coordinates the entire pipeline — schema…
- [converter](./src/converter/converter.md) — This module is the public-facing entry point of `@suaveplan/emblem-solver`. It coordinates the entire pipeline — schema…
- [errors](./src/errors/errors.md) — This module exposes the typed error surface for `@suaveplan/emblem-solver`. It defines the stable, namespaced code regi…
- [errors](./src/errors/errors.md) — This module exposes the typed error surface for `@suaveplan/emblem-solver`. It defines the stable, namespaced code regi…
- [fixtures](./src/fixtures/fixtures.md) — This module is the canonical test-fixture surface for the package. Each exported function returns a deterministic `RGBA…
- [fixtures](./src/fixtures/fixtures.md) — This module is the canonical test-fixture surface for the package. Each exported function returns a deterministic `RGBA…
- [analyse](./src/grid/analyse/analyse.md) — This module owns `analyseGrid`, the diagnostic phase of the conversion pipeline. It walks an RGBA grid once, buckets op…
- [analyse](./src/grid/analyse/analyse.md) — This module owns `analyseGrid`, the diagnostic phase of the conversion pipeline. It walks an RGBA grid once, buckets op…
- [helpers](./src/helpers/helpers.md) — This module is the shared kernel of utility functions used by the analyser, the solver strategies, and the optimisers.…
- [helpers](./src/helpers/helpers.md) — This module is the shared kernel of utility functions used by the analyser, the solver strategies, and the optimisers.…
- [parse](./src/io/parse/parse.md) — This module owns the two import paths into the solver: `parseRGBABuffer` turns a raw RGBA `Uint8Array` (e.g. the output…
- [parse](./src/io/parse/parse.md) — This module owns the two import paths into the solver: `parseRGBABuffer` turns a raw RGBA `Uint8Array` (e.g. the output…
- [merge](./src/optimizer/merge/merge.md) — This module owns `mergeAdjacentRects`, the post-processing pass that combines pairs of edge-sharing same-extent rectang…
- [merge](./src/optimizer/merge/merge.md) — This module owns `mergeAdjacentRects`, the post-processing pass that combines pairs of edge-sharing same-extent rectang…
- [overlap](./src/optimizer/overlap/overlap.md) — This module owns `optimiseOverlap`, the deepest cover-reduction pass in the package. It looks for three patterns that t…
- [overlap](./src/optimizer/overlap/overlap.md) — This module owns `optimiseOverlap`, the deepest cover-reduction pass in the package. It looks for three patterns that t…
- [redundancy](./src/optimizer/redundancy/redundancy.md) — This module owns `eliminateRedundant`, the final cross-layer optimisation the converter runs after every layer's cover…
- [redundancy](./src/optimizer/redundancy/redundancy.md) — This module owns `eliminateRedundant`, the final cross-layer optimisation the converter runs after every layer's cover…
- [schemas](./src/schemas/schemas.md) — This module owns the runtime validation surface for `@suaveplan/emblem-solver`. It exposes `ConvertOptionsSchema`, a Zo…
- [schemas](./src/schemas/schemas.md) — This module owns the runtime validation surface for `@suaveplan/emblem-solver`. It exposes `ConvertOptionsSchema`, a Zo…
- [greedy](./src/solver/greedy/greedy.md) — This module provides the greedy selector that drives the primary covering strategy. `enhancedGreedyCover` picks rectang…
- [greedy](./src/solver/greedy/greedy.md) — This module provides the greedy selector that drives the primary covering strategy. `enhancedGreedyCover` picks rectang…
- [histogram](./src/solver/histogram/histogram.md) — This module enumerates every distinct maximal-rectangle candidate inside an opaque-pixel grid. It is the candidate pool…
- [histogram](./src/solver/histogram/histogram.md) — This module enumerates every distinct maximal-rectangle candidate inside an opaque-pixel grid. It is the candidate pool…
- [layer](./src/solver/layer/layer.md) — This module owns `processLayerMultiStrategy`, the function the converter calls once per layer in the current ordering.…
- [layer](./src/solver/layer/layer.md) — This module owns `processLayerMultiStrategy`, the function the converter calls once per layer in the current ordering.…
- [ordering](./src/solver/ordering/ordering.md) — This module provides the layer-ordering machinery the converter consults when it has to decide which colour sits on the…
- [ordering](./src/solver/ordering/ordering.md) — This module provides the layer-ordering machinery the converter consults when it has to decide which colour sits on the…
- [strip](./src/solver/strip/strip.md) — This module implements `stripDecomposition`, a complementary cover strategy that ignores the maximal-rect candidate poo…
- [strip](./src/solver/strip/strip.md) — This module implements `stripDecomposition`, a complementary cover strategy that ignores the maximal-rect candidate poo…
- [build](./src/svg/build/build.md) — This module owns `buildSVG`, the deterministic SVG serialiser the converter uses to produce its final `<svg>` string. I…
- [build](./src/svg/build/build.md) — This module owns `buildSVG`, the deterministic SVG serialiser the converter uses to produce its final `<svg>` string. I…
- [telemetry](./src/telemetry/telemetry.md) — This module owns the OpenTelemetry instruments emitted by `convert()`. It exposes a counter (`emblem_solver.convert.tot…
- [telemetry](./src/telemetry/telemetry.md) — This module owns the OpenTelemetry instruments emitted by `convert()`. It exposes a counter (`emblem_solver.convert.tot…
- [types](./src/types/types.md) — This module is the single source of truth for the public type surface of `@suaveplan/emblem-solver`. It defines the imm…
- [types](./src/types/types.md) — This module is the single source of truth for the public type surface of `@suaveplan/emblem-solver`. It defines the imm…
<!-- end:auto-docs -->
## Install
```sh
bun add @suaveplan/emblem-solver
```
## Quick start
```ts
import { convert, fromIndexedGrid } from "@suaveplan/emblem-solver";
const { pixels, width, height } = fromIndexedGrid(
[
[0, 1, 0],
[1, 1, 1],
[0, 1, 0],
],
new Map([[1, { r: 255, g: 0, b: 0 }]])
);
const { svg, totalRects, ratio } = convert(pixels, width, height);
console.log(svg); // <svg …>…</svg>
console.log(totalRects); // 2 — the cross collapses to two overlapping rects
console.log(ratio.toFixed(1)); // 2.5 — naïve per-pixel would have been 5 rects
```
## API surface
| Symbol | Subpath | Purpose |
|---|---|---|
| `convert` | root | Public orchestrator |
| `analyseGrid` | `/grid` | Per-colour islands, density, fragmentation |
| `parseRGBABuffer`, `fromIndexedGrid` | `/io` | Input adapters |
| `buildSVG` | `/svg` | Standalone serialiser |
| `dualAxisMaximalRects`, `enhancedGreedyCover`, `perIslandCover`, `stripDecomposition`, `processLayerMultiStrategy`, `permutations`, `factorial`, `getStaticOrdering` | `/solver` | Composition primitives |
| `mergeAdjacentRects`, `optimiseOverlap`, `eliminateRedundant` | `/optimizer` | Composition primitives |
| `ConvertOptionsSchema` | `/schemas` | Zod input validation |
| `EmblemSolverError`, `EMBLEM_SOLVER_CODES` | `/errors` | Typed errors |
## Options
```ts
interface ConvertOptions {
/** Default: "auto" */
layerOrder?: "auto" | "area-desc" | "area-asc" | "island-aware" | "perimeter-desc";
/** Default: 40320 (= 8!) */
maxPermutations?: number;
/** Default: Math.random — supply a seeded RNG for deterministic auto-ordering on > 8-colour inputs */
rng?: () => number;
}
```
## Errors
All failures throw `EmblemSolverError` whose `.code` is one of:
- `EMBLEM_SOLVER.INVALID_GRID` — dimensions non-positive or
`pixels.length !== width * height`.
- `EMBLEM_SOLVER.INVALID_OPTIONS` — Zod rejected the options bag.
- `EMBLEM_SOLVER.INVALID_PIXEL` — reserved for future use.
## Observability
`convert()` emits two OpenTelemetry instruments via the meter
`@suaveplan/emblem-solver`:
- Counter `emblem_solver.convert.total`
- Histogram `emblem_solver.convert.duration_ms` (unit: `ms`)
Instruments are registered lazily on first call, so importing the package
has no observability side effects.
## Tier
Universal: zero browser / Node / React dependencies. Runs unchanged on
Bun, Node, Deno, and modern browsers.
## License
MIT — Suaveplan Team.