Skip to content

multilingualprogramming/pixel2polygon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

Pixel2Polygon converts images into geometric mosaics by replacing pixels with regular polygon tiles (triangles, squares, hexagons, and more).

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors