--- title: Ling Hatch emoji: 🔴 colorFrom: red colorTo: blue sdk: gradio sdk_version: 6.2.0 python_version: "3.12" app_file: app.py pinned: false --- # Ling hatch Turns photos into A4 outline-and-crosshatch sheets in the Ling style: one SVG on white and one on black per image. ## Run ``` pip install -r requirements.txt python app.py # Gradio app, opens on http://127.0.0.1:7860 python ling_hatch.py a.jpg b.png --out sheets --hues 5 --coding spectrum # command line ``` Each image gives `_white.svg`, `_black.svg`, a preview PNG of each, and `all.zip` with every SVG. ## What it does 1. Crops the image to the picture area of the sheet (never stretches it), or fits the whole image if you choose that. 2. Posterizes it into up to seven colour regions, one Ling hue each, and up to four hatch densities per hue. 3. Signs the image file with ML-DSA-87 and uses the signature bytes to pick each hue's hatch family, angle and period. 4. Traces every region to an outline and fills it with clipped hatch lines. Nothing is filled. 5. Draws the frame, legend, dial, digest and title plate with the Ling component bundle (`ling_bundle.js`). The signature is a visual encoding. It does not protect or authenticate the print. ## Options | Option | Meaning | |---|---| | `layout` | `instruments`: picture plus legend, dial, digest and title plate. `picture`: picture only, portrait or landscape. | | `crop`, `anchor` | `fill` crops to the picture area and `anchor` says which part to keep. `fit` keeps the whole image. | | `hues`, `steps` | Colour regions (3 to 7) and hatch densities per hue (2 to 4). | | `coding` | `perceptual`: many colour clusters, each keeps its own hue (nearest hue angle; neutrals take the nearest hatched appearance). `cryptographic`: seven regions ordered light to dark take the hues in an order shuffled by the signature. `appearance`: seven regions, one hue each, nearest overall. `spectrum`, `spectrum-reversed`: red to violet by lightness. | | `analysis_px`, `smooth`, `simplify`, `min_region` | How fine, how smooth and how small the regions may be. | | `contrast`, `gamma`, `tone_weight` | Local contrast, mid-tone darkness, and whether regions follow tone or colour. | | `vivid` | Colour strength. 0: density follows light and dark only. 1: saturated colours get dense hatch. -1 (default): auto, 0 for photos rising to 0.5 for flat, saturated artwork. | | `keep_transparent` | Transparent parts of a PNG stay empty: no hatch and no outline. Turn off to treat them as white. | | `dpi`, `line_mm`, `spacing_mm`, `quality` | Coordinates sit on the dpi grid. Spacing below 0.22 mm is under the Ling print floor. | | `key_phrase` | Empty: fresh random key per image, discarded. Set: key derived from the phrase, same image gives same hatch. | | `black_ground` | Turn off to print the black version on black stock. | ## Tiles and text rings `python ling_tiles.py photo.jpg --out sheets` (or Style: "Tiles and text rings" in the app) packs each colour region with square tiles and circles instead of hatching it. Pieces never cross a region edge and are placed largest first, so flat areas get large pieces and detailed areas small ones. Circles carry rings of text spelling the hue's key, set in Chesilin with one glyph per ring cell (`--ring-face lingring` for Ling Ring); circles too small for text show the hue's node shape. Tiles are hatched at the region's density and the larger ones carry the hue's spectrum letter (R O Y G B I V) in Daemon (`--tile-face lingring` for Ling Ring). `--png-scale 2` also writes PNGs at twice screen size (1588 x 2246 for A4). Options: `ring_face`, `tile_face`, `circle_bias`, `mix`, `tile_min_mm`, `circle_min_mm`, `circle_max_mm`, `tile_max_mm`, `gap_mm`, `ring_text`. `--animate true` writes a screen version whose SVG carries CSS animation: rings turn at different speeds and directions, ring glyphs spark or light one by one, hub shapes and tile letters turn, larger tile frames light in a wave across the sheet, and each hue's second hatch direction fades out and back. Only transforms and fades are animated, with no filters or glows, and lit colours stay inside their own hue. It honours the reduced-motion setting. For screens use lighter settings, for example `--quality draft --line-mm 0.25 --spacing-mm 0.42 --tile-min-mm 0.7 --gap-mm 0.15`. `density_sizing` caps piece size by tone, so dense tones get smaller pieces where the regions are large enough to matter. ## Files - `ling_tiles.py`: the tile-and-ring packer. Needs `LingRing-Variable.ttf` beside it and `fonttools`. - `ling_hatch.py`: the pipeline, a library and a command-line tool. - `app.py`: the Gradio app. - `ling_bundle.js`: the Ling design system component bundle. Replace it to follow the design system. - `hub_glyph.json`: outline of 灵 for the dial hub (from Noto Sans CJK SC, SIL OFL 1.1). The frames and legend need a JavaScript engine: `mini-racer` (in requirements) or, failing that, Node.js on the PATH.