Skip to content

Latest commit

 

History

History
202 lines (143 loc) · 7.21 KB

File metadata and controls

202 lines (143 loc) · 7.21 KB

pixel2polygon

A web application that turns raster images into geometric mosaics by tiling them with regular polygons — hexagons, squares, or equilateral triangles — and filling each tile with a representative colour.

All geometry computation runs in WebAssembly compiled from French Multilingual sources. The browser relies entirely on the WASM binary.


Features

  • Three tiling modes: hexagon (pointy-top, staggered rows), square, equilateral triangle
  • Tile size configurable from 5 px to 120 px
  • Optional tile outlines with adjustable colour and opacity
  • Drag-and-drop / click / paste image upload
  • Before-and-after canvas view with one-click PNG download
  • Geometry (sommet_hex_x, espacement_horiz, hauteur_tri, couleur_moyenne, …) exported from WASM with French identifiers
  • Full canonical implementation — including KMeans dominant-colour mode via MiniBatchKMeans — available in src/hexagonify_canonique.ml

Project structure

pixel2polygon/
├── src/
│   ├── hexagonify_wasm.ml       # WASM module — geometry + mean colour (French multilingual)
│   ├── hexagonify_canonique.ml  # Canonical source — full algorithm + KMeans (French multilingual)
│   └── main.ml                  # Entry point: importer hexagonify_wasm
├── scripts/
│   └── compile_wasm.ml          # Build script (French multilingual)
├── public/
│   ├── index.html               # Web UI
│   ├── style.css                # Dark-theme stylesheet
│   ├── app.js                   # JavaScript frontend (WASM-only, no fallback)
│   ├── hexagonify.wasm          # Compiled binary  ← generated by build
│   └── hexagonify.wat           # WAT text format  ← generated by build
└── requirements-build.txt       # Python build dependencies

Architecture

src/hexagonify_wasm.ml   (French multilingual)
        │
        ▼
  Lexer / Parser
        │
        ▼
  WATCodeGenerator  ──►  hexagonify.wat
        │
        ▼
  wasmtime.wat2wasm ──►  hexagonify.wasm
        │
        ▼
  Browser loads WASM, calls French exports:
    sommet_hex_x / sommet_hex_y
    espacement_horiz / espacement_vert
    hauteur_tri / sommet_tri_x / sommet_tri_y
    couleur_moyenne

The JavaScript frontend (public/app.js) calls these exports directly. If the WASM binary is absent or invalid, the application is disabled and the build command is shown.


Building the WASM

Prerequisites

pip install -r requirements-build.txt
# installs: multilingualprogramming, wasmtime

Compile

multilingual run scripts/compile_wasm.ml

Outputs:

File Description
public/hexagonify.wasm Binary WebAssembly module loaded by the browser
public/hexagonify.wat Human-readable WAT (WebAssembly Text) for inspection

To point the build script at a local development checkout of the multilingual runtime:

MULTILINGUAL_DEV_PATH=/path/to/multilingual multilingual run scripts/compile_wasm.ml

Running the web application

Serve the public/ directory with any static file server that sets the correct MIME type for .wasm files (application/wasm):

# Python (built-in)
python -m http.server 8080 --directory public

# Node.js (npx serve)
npx serve public

Then open http://localhost:8080 in a browser.

Note: opening index.html directly as a file:// URL will block the WASM fetch due to browser CORS restrictions. Always use a local server.


Smoke tests

Run the lightweight frontend smoke suite with plain Node.js:

node tests/smoke.js

The smoke tests validate that the main UI controls are present, the shape selector triggers a render, studio/source tab switching works, and every supported tiling method produces at least one tile.


Source files

src/hexagonify_wasm.ml — WASM module

Written in French multilingual. Exports pure numeric functions that the JavaScript frontend calls per tile:

Export (French) Description
sommet_hex_x(cx, cy, a, idx) x-coordinate of vertex idx (0–5) of a pointy-top hexagon
sommet_hex_y(cx, cy, a, idx) y-coordinate of the same vertex
espacement_horiz(a) Horizontal stride: √3 · a
espacement_vert(a) Vertical stride: 1.5 · a
hauteur_tri(a) Triangle height: √3/2 · a
sommet_tri_x(x, a, idx, vers_haut) x-coordinate of triangle vertex idx
sommet_tri_y(y, a, idx, vers_haut) y-coordinate of triangle vertex idx
couleur_moyenne(total, compte) Per-channel colour mean: round(total / compte)
methode_hexagone() / methode_carre() / methode_triangle() Method codes (0 / 1 / 2)

src/hexagonify_canonique.ml — canonical source

Written in French multilingual. Implements the complete algorithm as a Python-compiled program, including:

  • PIL/NumPy polygon masks and bounding-box sampling
  • mode_couleur="kmeans" — dominant colour via MiniBatchKMeans (scikit-learn)
  • mode_couleur="moyenne" — fast per-channel mean
  • carreler_image() — main entry point equivalent to the original hexagonify.py
  • CLI demo block (si __name__ == "__main__":)

Run canonically with:

multilingual run src/hexagonify_canonique.ml

Requires Pillow, numpy, and optionally scikit-learn:

pip install pillow numpy scikit-learn

scripts/compile_wasm.ml — build script

Written in French multilingual. Mirrors the pattern established by Cellcosmos:

  1. Locates the project root
  2. Reads and bundles src/main.ml + src/hexagonify_wasm.ml
  3. Lexes and parses the bundle with language="fr"
  4. Generates WAT via WATCodeGenerator
  5. Compiles to binary WASM via wasmtime.wat2wasm
  6. Copies source files into public/ alongside the binary

Colour modes

Mode Where implemented How
Moyenne (mean) hexagonify_wasm.ml → WASM → browser Per-channel arithmetic mean of all pixels inside the tile
KMeans hexagonify_canonique.ml → Python MiniBatchKMeans finds the dominant cluster centroid; falls back to mean if scikit-learn is unavailable

The web interface uses moyenne (computed in WASM). The canonical .ml source exposes both modes for offline / batch use.


Tiling geometry

  • Hexagons — pointy-top orientation, staggered rows (offset every other row by half the horizontal pitch). Partial tiles at all four borders are preserved.
  • Squares — axis-aligned grid, top-left anchored. Border tiles clipped to image dimensions.
  • Triangles — alternating upward/downward equilateral triangles on a (row + col) % 2 parity grid. Border tiles preserved.

Relation to hexagonify.py

hexagonify_canonique.ml is a faithful French-multilingual translation of the original hexagonify.py algorithm, preserving the same geometry helpers, mask generation, and KMeans colour logic. hexagonify_wasm.ml is the minimal numeric subset of that algorithm that maps cleanly to WebAssembly.