File size: 2,864 Bytes
8be9ae3
5828b5b
 
 
 
8be9ae3
5828b5b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8be9ae3
 
5828b5b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
---
title: PixelLock
emoji: 🎨
colorFrom: purple
colorTo: indigo
sdk: docker
app_port: 7860
pinned: true
license: gemma
short_description: Footprint-locked AI pixel-art retexturing
models:
  - solarkyle/pixellock-gemma-12b-pixelart-gguf
tags:
  - gradio
  - build-small-hackathon
  - track:wood
  - achievement:offbrand
  - achievement:welltuned
  - achievement:llama
  - achievement:sharing
  - achievement:fieldnotes
  - achievement:offgrid
  - best-demo
  - bonus-quest-champion
  - pixel-art
---

# 🎨 PixelLock β€” AI Pixel-Art Retexturing

Upload a sprite, pick a vibe (or write your own), hit **Run**. PixelLock restyles
the colors and shading while keeping the **exact silhouette** β€” pixel-perfect,
*guaranteed by construction*.

> ⏳ This is a GPU Space that auto-sleeps. The first visit cold-starts the model
> (~30–60s). If the first edit errors, the model is still waking β€” try again.

## πŸ”— Links

- πŸŽ₯ **Demo video:** [WATCH β–Ά](VIDEO_LINK)
- πŸ“£ **Social post:** [SEE POST](SOCIAL_POST_LINK)
- 🧠 **Model (fine-tuned GGUF):** https://huggingface.co/solarkyle/pixellock-gemma-12b-pixelart-gguf
- πŸ“„ **Full technical writeup:** [read it](WRITEUP_LINK)

## The idea: the *wrong* model on purpose

PixelLock does **not** use an image generator. It uses a **fine-tuned text LLM**
(Gemma-4-12B). The sprite is serialized to a tiny text wire β€” a `PALETTE` block
plus a `GRID` of space-separated cells β€” and the model **rewrites that text** in a
new style. The trick is a per-sprite **GBNF decoding grammar** (llama.cpp): every
transparent cell is pinned to a fixed literal, so the model is *physically
incapable* of moving a pixel. The footprint and transparency are preserved **by
construction**, not by luck. It's language modeling, not diffusion β€” and that's
exactly why the shape can never break.

In a benchmark, *no* model could emit a correct 32Γ—32 grid unconstrained
(~0/150 attempts); the grammar takes validity from **0% β†’ 100%** at every size
(16Γ—16 β†’ 128Γ—128, incl. 2Γ— upscale), footprint-perfect every time.

## The tech

- **Fine-tuned model** β€” QLoRA fine-tune of Gemma-4-12B on a curated corpus of
  palette-indexed pixel-art sprites (≀64px); completion-only loss,
  step-checkpointing, final eval loss **0.378**. Exported to GGUF (q4_k_m).
- **Grammar-constrained decoding** β€” a per-sprite GBNF grammar compiled from the
  input footprint; the silhouette is locked in the decoder, not post-filtered.
- **Custom Gradio UI** β€” a heavily themed `gr.Blocks` interface (Off-Brand) that
  builds the grammar per upload, footprint-checks the output, and shows you the
  **raw text the model wrote**.
- **Serving** β€” Docker GPU Space running llama.cpp `llama-server` (CUDA) with the
  per-request grammar; auto-sleeps when idle.

Built for the **Build Small** hackathon Β· *Thousand Token Wood* track.