IDFC about the name, its fucking given by epicguest97.
This repo is a full reference implementation of *****, an experimental continuous image format based on anisotropic 2D Gaussian splat atoms. There is no pixel grid stored in the file. Decoders evaluate the field at any resolution.
I wrote this in a plain, practical way. It is deterministic and not ML based. It does what it says, no extra stuff.
I was not able to come up with a name when epicguest97 said *****. So that became the placeholder name and it stuck.
This format stores a list of splats. Each splat is a 2D Gaussian with color. There is no pixel grid. When you render, you pick an output size, then evaluate the field at every pixel. That means:
- you can render at any resolution
- you do not have a fixed native size
- rendering cost scales with
$N_{pixels} \times N_{atoms}$
If you want the exact byte layout, use SPEC.md. That is the source of truth.
- Spec and format details: SPEC.md
- Core library (file IO, f16, color conversion): src/*****.h and src/*****.c
- CPU renderer (reference rasterizer): src/*****_render.h and src/*****_render.c
- PNG to ***** encoder (Windows WIC): tools/png2*****.c
- ***** to PPM raster tool: tools/*****_raster.c
- Tests: tests/*****_tests.c
- Win32 + OpenGL viewer: viewer/viewer.c
- Python viewer (uses *****_raster.exe): viewer/*****_viewer.py
The header is fixed at 24 bytes and is fully described in SPEC.md. It contains:
- magic string
- version
- flags
- atom count
- header size
- reserved
Each atom is exactly 20 bytes. It stores:
- center (x, y) in normalized coordinates
- covariance (sxx, sxy, syy)
- alpha
- color in linear YCoCg
- per-atom flags
All fields are little-endian. Atoms are stored in f16 to keep files small. See SPEC.md for the exact byte offsets and validation rules.
Each atom defines a 2D Gaussian with covariance
Each atom contributes
Then normalize:
The renderer uses
Color is stored in linear YCoCg and converted to linear RGB at decode time, then to sRGB for 8-bit output. The transform is round-trip safe:
Inverse:
If you are implementing another decoder, use the same math to avoid color drift.
The encoder in tools/png2*****.c is multi-stage. The short version:
- Load PNG using WIC (Windows only).
- Build a 5D feature for each pixel: (x, y, r, g, b) with a spatial weight.
- k-means++ seeding, then Lloyd iterations to get clusters.
- Fit Gaussian covariances and atom colors from clusters.
- Soft color refit to match how the renderer blends.
- Error-driven splitting to add detail where it matters.
- Final soft refit at full resolution.
Important detail: color is stored in YCoCg, and the encoder uses linear RGB for all math. That keeps the math consistent with the renderer in src/*****_render.c.
The renderer in src/*****_render.c is a direct CPU reference. It evaluates every atom at every pixel, which is expensive but simple and correct. It also has OpenMP parallel loops for speed where possible.
Complexity is roughly:
That is the reason large outputs get slow. This is a reference implementation, not a GPU splat renderer.
From the repo root, run build.bat. It builds png2*****.exe, *****_raster.exe, and *****_tests.exe.
Manual compile commands:
- Build *****_raster.exe with cl /O2 /W4 /I src tools*_raster.c src*.c src*****_render.c
- Build png2*****.exe with cl /O2 /W4 /I src tools\png2*****.c src*.c src*_render.c src\wic_png.c /link windowscodecs.lib ole32.lib
The Windows PNG path uses WIC, so no extra image libraries are required on Windows.
Converts PNG to *****. Default settings are balanced for quality and speed.
Usage:
- png2***** input.png output.*****
- png2***** input.png output.***** hq
- png2***** input.png output.***** fast
- png2***** input.png output.***** atoms=10000 max_atoms=40000 sharp=1.6 sample=1
Encoder parameters:
- atoms (default 5000): initial k-means clusters
- max_atoms (default 40000): upper bound after splits
- spatial (default 2.0): position vs color weight in the 5D feature space
- sharp (default 1.2): covariance scaling, >1 = sharper splats
- refine (default 6): number of split passes
- split (default 30): percent of atoms to split per pass
- iters (default 50): Lloyd iterations per stage
- sample (default 2): pixel sampling stride during refinement (1 = full)
- fast / hq: presets
Rasterizes a .***** to PPM at a chosen resolution.
Usage:
- _raster input. output.ppm 1024 1024
- _raster input. output.ppm 1024 1024 --p3
The --p3 flag writes ASCII PPM for basic web viewers.
Prebuilt Windows viewer:
Source is in viewer/viewer.c. Build with viewer/build.bat after running viewer/setup.ps1 (that script downloads ImGui). This viewer renders in the background and keeps UI responsive.
Run *****_tests.exe. Tests cover:
- file IO validation
- f16 conversions
- YCoCg round-trip
- deterministic rendering
- Rendering is CPU-only.
- Output quality depends on atom count and refinement settings.
- Very large resolutions can be slow because the renderer is
$O(N_{pixels} \times N_{atoms})$ .
