New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@slithy/prim-lib

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@slithy/prim-lib

Core engine for primitive-based image reconstruction.

latest
Source
npmnpm
Version
0.4.1
Version published
Maintainers
1
Created
Source

@slithy/prim-lib

Core engine for primitive-based image reconstruction. Consumed by @slithy/prim-interface.

What it does

Reconstructs an image by iteratively placing geometric shapes. Each step evaluates candidate shapes, mutates them, picks the one that most reduces the difference from the target, and draws it onto the working canvas.

Exports

Classes

  • Canvas — wraps HTMLCanvasElement or OffscreenCanvas (environment-detected); handles image loading, pixel reads, drawing steps, and SVG output
  • Optimizer — runs the step loop; calls onStep after each shape is placed. Accepts an optional schedule function (defaults to requestAnimationFrame; pass fn => setTimeout(fn, 0) for worker contexts)
  • State — holds the current canvas and its distance from the target
  • Step — a single candidate shape placement; computes best color and difference change

Shapes

  • Shape — abstract base
  • Triangle, Rectangle, Ellipse, Circle, Square, Hexagon, Glyph, Debug

Types

Cfg — runtime config (all fields required):

interface Cfg {
  width: number         // image width for computation (set by Canvas.original)
  height: number        // image height for computation (set by Canvas.original)
  steps: number         // total shapes to place
  shapes: number        // candidate shapes evaluated per step
  mutations: number     // hill-climb attempts per candidate
  alpha: number         // starting shape opacity
  mutateAlpha: boolean  // whether opacity is mutated per candidate
  computeSize: number   // max image dimension for pixel distance calculations
  viewSize: number      // max image dimension for display canvas
  allowUpscale?: boolean // allow output larger than source image (default: false)
  scale?: number        // viewSize / computeSize ratio (set by Canvas.original)
  shapeTypes: Array<new (w: number, h: number) => ShapeInterface>
  shapeWeights?: number[]  // per-shape selection weights (same length as shapeTypes)
  fill: 'auto' | string
}
  • PreCfgCfg with optional width/height; used before image dimensions are known
  • ShapeInterface — structural interface for shapes; includes toData(alpha, color): StepData
  • Ctx2DCanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; used for canvas operations that work in both main-thread and worker contexts
  • Bbox, Point, ImageDataLike, ShapeImageData

RGB[number, number, number] tuple

StepData — discriminated union of serialized shape data, keyed by t:

type StepData =
  | { t: 't';  a: number; c: RGB; pts: [number, number][] }       // Triangle
  | { t: 'r';  a: number; c: RGB; pts: [number, number][] }       // Rectangle
  | { t: 'e';  a: number; c: RGB; cx: number; cy: number; rx: number; ry: number } // Ellipse
  | { t: 'c';  a: number; c: RGB; cx: number; cy: number; r: number }              // Circle
  | { t: 's';  a: number; c: RGB; cx: number; cy: number; r: number }              // Square
  | { t: 'h';  a: number; c: RGB; cx: number; cy: number; r: number; angle: number } // Hexagon
  | { t: 'sm'; a: number; c: RGB; cx: number; cy: number; fs: number; text: string } // Glyph

SerializedOutput — compact, storage-ready representation of a completed run:

interface SerializedOutput {
  v: 1             // schema version
  w: number        // compute width
  h: number        // compute height
  scale: number    // viewSize / computeSize ratio
  fill: RGB        // background fill color
  steps: StepData[]
}

ReplayResult — returned by replayOutput:

interface ReplayResult {
  raster: HTMLCanvasElement | OffscreenCanvas
  svg: SVGSVGElement
  svgString: string
}

Functions

replayOutput(data: SerializedOutput): ReplayResult — reconstructs canvas and SVG natively from serialized output, without re-running the optimizer. Useful for restoring saved results from localStorage or a database.

renderStepToCtx(data: StepData, ctx: Ctx2D): void — renders a single StepData onto a 2D canvas context. Used internally by replayOutput and by runWorker to incrementally apply worker-posted steps to the display canvas.

stepDataToSVGElement(data: StepData): SVGElement — creates a DOM SVGElement from a StepData. Used internally by replayOutput and by runWorker to build the live SVG incrementally on the main thread.

Utilities

  • getFill(data: ImageDataLike): string — computes a fill color (average of corner pixels) from image data
  • parseColor(str: string): RGB — parses "rgb(r, g, b)" to an [r, g, b] tuple
  • stepPerf — accumulator for profiling rasterize vs pixel math time per step

Differences from primitive.js

prim-lib is derived from primitive.js, a JavaScript port of the Go primitive library by Michael Fogleman. The core algorithm — iterative shape placement via hill-climbing — is unchanged. What's different:

  • TypeScript, strict mode — fully typed throughout; strict: true on both packages
  • ESM only — no CommonJS; no importScripts()
  • Canvas reuse — the original creates a new <canvas> element for every shape rasterization call (~58,000 per run at default settings). prim-lib reuses a single module-level canvas, growing it only when a larger bbox is seen. This delivered a ~27× speedup (37 s → ~0.8 s rasterize time per run)
  • willReadFrequently: true — canvas contexts used for getImageData are created with this flag, keeping pixel data in CPU memory and suppressing browser warnings
  • Worker-compatibleCanvas detects its environment: in a browser context it creates HTMLCanvasElement; in a worker it creates OffscreenCanvas (same 2D API). Canvas.fromBitmap() loads an image from an ImageBitmap (worker-compatible) rather than new Image(). Optimizer accepts an injectable schedule function so callers can substitute setTimeout for requestAnimationFrame in worker contexts. The original included importScripts()-based worker stubs (not ESM-compatible) which were removed; worker support is now done properly via prim-interface's runWorker()
  • Architecture split — the original is a single-layer library. Here, prim-lib is the pure algorithm (no knowledge of how images arrive or where results go), and prim-interface is the adapter that wires it to the browser
  • PreCfg / Cfg distinctionCanvas.original() accepts PreCfg (optional width/height) and resolves to a fully-populated Cfg, making the config lifecycle explicit in the types
  • SerializationStepData / SerializedOutput allow completed runs to be stored compactly and replayed via replayOutput() without re-running the optimizer
  • Additional shapesCircle, Square, Hexagon, and Glyph are not in the original; Circle is a uniform-radius variant of Ellipse
  • Shape weightingshapeWeights allows biased shape selection with a guaranteed distribution: the optimizer pre-allocates exact per-shape step counts (largest-remainder rounding) and shuffles them, so the final mix always matches the requested weights

Architecture notes

  • Shape.rasterize() reuses a single module-level canvas (_rasterCanvas) grown to the max shape size seen; in a worker, this is an OffscreenCanvas (environment-detected by the Canvas constructor). Avoids per-call canvas creation which was the dominant cost (27x speedup)
  • Cfg.shapeTypes holds shape constructors; shapes are chosen randomly each step unless shapeWeights is set
  • When shapeWeights is provided (same length as shapeTypes), Optimizer builds a step plan at construction time: each shape type is allocated an exact number of slots proportional to its weight (using largest-remainder rounding), then the plan is Fisher-Yates shuffled. This guarantees the final shape distribution matches the weights, rather than just biasing random selection
  • PreCfg exists to bridge the gap between call time (dimensions unknown) and runtime (dimensions set by Canvas.original() or Canvas.fromBitmap())
  • Canvas.svgRoot() is a static helper shared by Canvas.empty() and replayOutput() to create the SVG root with clip path and background fill; it uses DOM APIs and is main-thread only

Keywords

image

FAQs

Package last updated on 30 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts