Initial Commit
This commit is contained in:
134
packages/media/image/emblem-solver/README.md
Normal file
134
packages/media/image/emblem-solver/README.md
Normal 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.
|
||||
|
||||
Reference in New Issue
Block a user