---
title: HexaGrid Creator — Project Spec / Context
version: 0.1
source_repo:
  github: https://github.com/Oncorporation/HexaGrid
  huggingface_space: https://huggingface.co/spaces/Surn/HexaGrid
last_updated: 2026-02-12
---

# HexaGrid Creator (Beeuty-MapMaker)

## 1) What this project is
HexaGrid Creator is a Gradio (Hugging Face Spaces) application that:

- Takes an **input image** and generates a **tiled grid overlay** (hexagon / square / triangle) suitable for tabletop maps.
- Optionally generates a new image via **FLUX** (Diffusers) with **LoRA** styles, and then applies the grid.
- Supports interactive **image filtering** via **LUT (.cube)** files, plus compositing/blur utilities.
- Can generate a **depth map** (DPT) and a **3D asset** (TRELLIS pipeline), then export **GLB** and **Gaussian PLY**.
- Can produce a shareable **permalink** to an external 3D viewer by uploading assets to a Hugging Face **dataset repo**.

Primary entrypoint: `app.py`.

## 2) Deployment target and runtime
### Hugging Face Spaces metadata (from `README.md` frontmatter)
- SDK: `gradio`
- `python_version`: **3.10.13**
- `sdk_version`: **5.44.1**
- `app_file`: `app.py`
- OAuth: `hf_oauth: true`

### GPUs and ZeroGPU note
The UI warns that **ZeroGPU** may be unavailable or crash intermittently. This is treated as an infrastructure limitation rather than a code defect.

## 3) Repository layout (high-level)
- `app.py`: Main Gradio Blocks UI + orchestration.
- `utils/`: Application modules used by `app.py`.
- `trellis/`: TRELLIS 3D pipeline package (imported as `trellis.*`).
- `assets/`, `images/`, `LUT/`, `fonts/`: Static resources used by the UI.
- `style_20250314.css`: UI CSS.
- `requirements.txt`, `pre-requirements.txt`: Python dependencies.
- `wheels/`: platform-specific wheel artifacts referenced by `requirements.txt`.

## 4) Key dependencies and version-sensitive components
### Python package stack (from `requirements.txt`)
This project relies on:
- Gradio UI + Spaces GPU decorator: `gradio`, `spaces`
- Diffusers & model tooling: `diffusers` (git), `transformers`, `accelerate`, `safetensors`, `peft`
- Torch stack (CUDA index used): `torch`, `torchvision`, `xformers==0.0.29.post3`
- Image processing: `Pillow`, `opencv-python`, `opencv-python-headless`, `imageio`, `imageio-ffmpeg`, `numpy==1.26.4`, `scipy`
- Palette extraction: `Haishoku`
- 3D processing: `open3d`, `trimesh`, `xatlas`, `pyvista`, `pymeshfix`, `igraph`, `utils3d` (git)
- Background removal: `rembg`, `onnxruntime`
- Cairo/Pango for text rendering: `pycairo`, `cairocffi`, `pangocffi`, `pangocairocffi`, `cairosvg`
- CUDA/3D special wheels referenced (Linux-specific links present):
  - `flash_attn` wheel
  - `diff_gaussian_rasterization` wheel
  - `nvdiffrast` wheel

### Environment and tokens
- `utils/constants.py` requires `HF_TOKEN` to be present; it raises at import time if missing.
- Several Hugging Face operations implicitly depend on write permissions to a dataset used for uploads/shortlinks.

## 5) Session model and temp storage
### Session directories
- `start_session(req)` creates a per-session directory at `utils.constants.TMPDIR/<session_hash>`.
- `end_session(req)` deletes that directory on unload.

Notes:
- Many image outputs are written under `TMPDIR/<session_hash>`.
- Some functions still use the module-level `user_dir = constants.TMPDIR`; watch for places where session scoping is expected but not passed through.

## 6) Feature map & UI structure (Gradio)
The app is defined using `gr.Blocks(...) as hexaGrid` in `app.py` with major sections:

### Left panel
- `Input Image` (uploaded file path)
- `Sketch Pad` (`gr.Sketchpad`) for drawing/overlaying; can replace the input image.
- `Generate HURA Background` (procedural pattern generator from `utils/hex_hura.py`).

### Right panel
- `Image Filters (LUT)`: upload/select `.cube` file and apply to input/sketch/HURA.
- `Color Composite` and `Blur` tools.

### Tabs
1. `HexaGrid Generation`
   - Core grid parameters (hex size, border, fill, rotation, background/border colors).
   - Excluded color list management.
   - Grid shape selection: triangle / square / hexagon.
   - Optional text labeling inside tiles.
   - Output images: grid render + overlay.
   - Post transforms: tilt/rotate, alpha composite, multiply blend, interpolate (lerp).

2. `Image Generation (AI)`
   - Generates an image using FLUX pipelines and LoRA “style gallery”.
   - Supports img2img and “Fill” model flows.
   - Template (pre-rendered) image gallery.

3. `Add Margins`
   - Adds printable margins (DPI-aware) to input/overlay image.

4. `3D and Depth (fun)`
   - Loads DPT depth estimation + TRELLIS 3D pipeline on accordion expand.
   - Creates depth map, then generates 3D asset, video preview.
   - Exports GLB and Gaussian PLY.
   - Builds permalink for external viewer.

## 7) Core pipelines (end-to-end flows)

### 7.1 Grid generation pipeline
Entry: `hex_button.click(...)` → `hex_create(...)`

- Loads input image, coerces to RGBA; if conversion fails, it pads onto a minimum canvas.
- Builds an input palette via `Haishoku.loadHaishoku(...)`.
- Converts UI colors + opacity to RGBA tuples via `utils.color_utils.update_color_opacity`.
- Calls `utils.hex_grid.generate_hexagon_grid_interface(...)` (wrapper around grid generation + overlay creation).
- Writes output files with `utils.image_utils.save_image_to_temp_png(...)` under the session directory.

Outputs:
- `output_image`: rendered tiled grid result
- `overlay_image`: overlay-only layer

### 7.2 Excluded color workflow
Module: `utils/excluded_colors.py`

- Stores excluded colors as a `gr.State` list of RGBA tuples.
- UI allows adding via `add_color`, deleting rows via `delete_color`, and manual edits via `on_input`.
- Grid sampling can filter out excluded colors (`filter_color` checkbox).

### 7.3 LUT filter pipeline
Module: `utils.image_utils.py`

- UI selects a LUT filename (from `constants.lut_files`) and previews it (`show_lut`).
- Apply operations call `apply_lut_to_image_path(lut_filename, image_path, intensity)`.

Important behavior:
- Images are opened through `open_image(...)` which supports local paths, URLs, and DataURL strings.
- Some file types (SVG/ICO) are converted to PNG.

### 7.4 AI image generation (FLUX + LoRA)
Primary functions:
- `get_model_and_lora(model_textbox)`
- `set_pipeline(model_name, lora_weights, pipeline_name)`
- `generate_image_lowmem(...)` (decorated with `@spaces.GPU(duration=230)`)
- `generate_ai_image_local(...)`
- `generate_input_image_click(...)` (UI handler)

Key concepts:
- Pipeline classes are selected from `PIPELINE_CLASSES`:
  - `FluxPipeline`
  - `FluxImg2ImgPipeline`
  - `FluxControlPipeline`
  - `FluxFillPipeline`
- LoRA configuration is driven by `utils.constants.LORA_DETAILS` and helper methods in `utils/lora_details.py`.
- For long prompts, `split_prompt_precisely(...)` is used when token count exceeds a threshold.

Performance/memory approach:
- Pipeline is moved to `device` for execution then returned to CPU with CUDA cache cleared.
- `enable_model_cpu_offload()` is used in some paths.

### 7.5 Depth + 3D generation (DPT + TRELLIS)
Load/unload model flow:
- `load_3d_models(is_open=True)` loads:
  - `DPTImageProcessor.from_pretrained("Intel/dpt-large")`
  - `DPTForDepthEstimation.from_pretrained("Intel/dpt-large", ignore_mismatched_sizes=True)`
  - TRELLIS pipeline via `load_trellis_model()` when not in shared space.
- `unload_3d_models(is_open=False)` deletes models and runs GC.

Depth map creation:
- `depth_process_image(image_path, resized_width, z_scale)` produces an 8-bit depth image.

3D asset creation:
- `generate_3d_asset_part1(...)` chooses source image, creates depth map file.
- `generate_3d_asset_part2(...)` runs TRELLIS:
  - preprocesses images
  - optionally uses multi-image algorithms (`singleimage`, `stochastic`, `multidiffusion`)
  - renders a preview mp4 via `render_utils.render_video`
  - packs results into a serializable “state” dict (`pack_state` / `unpack_state`).

Exports:
- `extract_glb(state, mesh_simplify, texture_size)` writes `<name>.glb`.
- `extract_gaussian(state)` writes `<name>.ply`.

### 7.6 Permalink creation + upload storage
The 3D tab can create a shareable viewer link.

Implementation components:
- `app.py:create_permalink(...)` calls `utils.storage.upload_files_to_repo(...)` with:
  - smallest of (GLB, Gaussian)
  - depth image
  - source image used for depth
- `utils/storage.py` handles:
  - extension filtering
  - `upload_folder(...)` batching
  - link building under `https://huggingface.co/datasets/<repo_id>/resolve/main/<folder_name>/...`
  - optional permalink building and URL shortening via JSON mapping

`utils/storage.py` version:
- `__version__ = "0.1.1"`

Shortener behavior:
- `gen_full_url(full_url=...)` stores mapping in a JSON file in a dataset repo.
- `version_info.versions_html()` links to the shortener JSON file for debugging.

## 8) `utils/` modules (responsibilities)
This list focuses on modules imported directly by `app.py`.

- `utils/constants.py`
  - Environment loading (`.env`) and required `HF_TOKEN` enforcement
  - UI prompt presets and negative prompts (`PROMPTS`, `NEGATIVE_PROMPTS`)
  - Pre-rendered template image registry (`PRE_RENDERED_MAPS_JSON_LEVELS`)
  - Model registry (`MODELS`, `LORA_WEIGHTS`, `LORA_TO_MODEL`, `LORA_DETAILS`)
  - Temp directory root (`TMPDIR`) used for session subfolders

- `utils/image_utils.py`
  - `open_image(...)` + helpers (`get_image_from_dict`, SVG/ICO conversion)
  - LUT preview/apply helpers
  - Compositing/blending functions (`alpha_composite_with_control`, lerp, multiply)
  - Temp PNG writer `save_image_to_temp_png(...)`
  - Pre-rendered gallery builder `build_prerendered_images_by_quality(...)`

- `utils/hex_grid.py`
  - Core grid rendering algorithms (hex/square/triangle tiling)
  - Shape selection mapping via `map_sides(...)`
  - Text-in-tile rendering utilities (Pango/Cairo + emoji font)

- `utils/excluded_colors.py`
  - Gradio state + DataFrame helpers for excluded RGBA colors

- `utils/file_utils.py`
  - File path parsing and safe extension normalization
  - Temp file cleanup tracking via `constants.temp_files`

- `utils/storage.py`
  - Upload assets to HF dataset repo and create permalink
  - URL shortener JSON file management

- `utils/version_info.py`
  - Visible runtime diagnostics in UI footer

## 9) Operational notes / gotchas
- `utils/constants.py` raises if `HF_TOKEN` is not set — this affects local dev and any import-time tooling.
- Some dependencies are platform-specific (Linux wheels referenced directly). Windows dev may require different wheels.
- Some paths in `hexaGrid.launch(allowed_paths=...)` include absolute drive paths (e.g., `e:/TMP`), which may not exist locally.
- `atexit.register(end_session)` registers `end_session(req)` without a `req`; this is likely a no-op or error path in some environments. Session cleanup is mostly handled by Gradio `load`/`unload` events.

## 10) How to extend safely (agent/human guidance)
- Prefer adding new UI actions as pure functions in `utils/` with minimal coupling to Gradio components.
- Keep session scoping by writing outputs to `TMPDIR/<session_hash>`.
- When adding new upload/permalink types, update `utils/constants.py` extension lists and ensure `utils/storage.py` filters accept them.
- When adding LoRAs, use `constants.LORA_DETAILS` and `utils/lora_details.py` conventions rather than hardcoding behavior in `app.py`.

## 11) Quick pointers for reading the code
- Start with `app.py` to understand UI event wiring and high-level orchestration.
- Then read:
  - `utils/hex_grid.py` for the tiling algorithm
  - `utils/image_utils.py` for I/O and image transforms
  - `utils/storage.py` for permalink/upload semantics
  - `utils/constants.py` for the “registry” of models, LoRAs, templates, and environment variables
