A 34.4M-parameter text-to-image model for pixel art, flat icons and stickers. Small enough for laptops and, next, the browser. Part of Darkroom, a project to build tiny image generators that run where you are. The same held-out prompts, never seen in training, from the 0.6B teacher and from each Pinhole size: ONNX Runtime Web (WebAssembly or WebGPU), so prompts and images never leave the browser. Parity: the ONNX-only pipeline matches PyTorch to within a mean of 0.00/255 per pixel (same noise, 20 steps). The browser's tokenizer is checked against Python by the demo's Self-test button. Start with one of the three styles, then describe a simple subject: of a. - Adjust guidance with cfg: 3–6…
pinhole-l is an open-weight model for text to image from Nuhman PK, released under Open RAIL++ License. It has 71M parameters. At 16-bit it needs about 0.2 GB of GPU memory, which fits on 1x MI300X from $1.85 an hour, at the lowest prices in the SAVRN Index.
A 70.8M-parameter text-to-image model for pixel art, flat icons and stickers. Small enough for laptops and, next, the browser. Part of Darkroom, a project to build tiny image generators that run where you are.
Runs On
What it takes to serve pinhole-l (71M parameters): the memory its weights need at each precision, and the cheapest way to rent enough data-center GPUs to hold them.
| Precision | Weights | Memory needed | Cheapest setup | Per hour | Also fits |
|---|---|---|---|---|---|
| 16-bit | 0.1 GB | 0.2 GB | 1x MI300X (192 GB) Vultr |
$1.85 | 1x H100 $1.99 · 1x MI325X $2.00 |
| 8-bit | 0.1 GB | 0.1 GB | 1x MI300X (192 GB) Vultr |
$1.85 | 1x H100 $1.99 · 1x MI325X $2.00 |
| 4-bit | 0.0 GB | 0.0 GB | 1x MI300X (192 GB) Vultr |
$1.85 | 1x H100 $1.99 · 1x MI325X $2.00 |
Memory is the weights at that precision plus 20% for the runtime and a short context; a long context needs more. Prices are the lowest on-demand hourly rates in the SAVRN Index, read Oct 18, 2026.
pinhole-l on every accelerator the SAVRN Index prices, at every precision
Model Card
By Nuhman PK, published under openrail++, revision 075ff1e7b2bd.
A 70.8M-parameter text-to-image model for pixel art, flat icons and stickers. Small enough for laptops and, next, the browser. Part of Darkroom, a project to build tiny image generators that run where you are. The same held-out prompts, never seen in training, from the 0.6B teacher and from each Pinhole size: ONNX Runtime Web (WebAssembly or WebGPU), so prompts and images never leave the browser. Parity: the ONNX-only pipeline matches PyTorch to within a mean of 0.00/255 per pixel (same noise, 20 steps). The browser's tokenizer is checked against Python by the demo's Self-test button. Start with one of the three styles, then describe a simple subject: of a. - Adjust guidance with cfg: 3–6…
Read Nuhman PK's full model card
A 70.8M-parameter text-to-image model for pixel art, flat icons and stickers. Small enough for laptops and, next, the browser. Part of Darkroom, a project to build tiny image generators that run where you are.
| Parameters | 70.8M (plus CLIP ViT-B/32 text encoder, TAESD decoder) |
| Weights | 142 MB (fp16) |
| Output | 256x256 RGB |
| Speed, T4 GPU | 258 ms per image (20 steps, guidance 4) |
| Speed, CPU (Kaggle) | 6,764 ms per image |
| CLIP score, held-out prompts | 30.57 (teacher PixArt-LCM: 32.64) |
Samples
The same held-out prompts, never seen in training, from the 0.6B teacher and from each Pinhole size:
Run it in your browser
No install needed: open the live demo. The model runs on your device with ONNX Runtime Web (WebAssembly or WebGPU), so prompts and images never leave the browser.
| Browser file | Size |
|---|---|
onnx/dit.onnx (Pinhole-L) |
284 MB |
onnx/text_encoder.onnx (CLIP ViT-B/32, fp32) |
253 MB |
onnx/taesd_decoder.onnx |
4.9 MB |
| Total first download (cached afterwards) | 542 MB |
Parity: the ONNX-only pipeline matches PyTorch to within a mean of 0.00/255 per pixel (same noise, 20 steps). The browser's tokenizer is checked against Python by the demo's Self-test button.
import * as ort from "https://cdn.jsdelivr.net/npm/[email protected]/dist/ort.all.min.mjs";
import { AutoTokenizer } from "https://cdn.jsdelivr.net/npm/@huggingface/[email protected]";
import { PinholeWeb } from "./pinhole-web.js"; // web/pinhole-web.js in this repo
const pinhole = await PinholeWeb.load("nuhmanpk/pinhole-l", { ort, AutoTokenizer });
const { rgba, width, height } = await pinhole.generate("sticker of a happy red fox", { steps: 20, cfg: 4, seed: 7 });
canvas.getContext("2d").putImageData(new ImageData(rgba, width, height), 0, 0);
Quick start
pip install torch diffusers transformers safetensors huggingface_hub
from huggingface_hub import snapshot_download
import sys
path = snapshot_download("nuhmanpk/pinhole-l"); sys.path.insert(0, path)
from pinhole import Pinhole
pipe = Pinhole.from_pretrained(path) # GPU if available, else CPU
images = pipe("sticker of a happy red fox", n=4, steps=20, cfg=4.0, seed=0)
images[0].save("fox.png")
Prompting
Start with one of the three styles, then describe a simple subject: <style> of a <adjective> <colour> <subject>.
| Style | Example |
|---|---|
pixel art |
pixel art of a retro blue rocket |
flat icon |
flat icon of a cozy green house |
sticker |
sticker of a smiling pink cupcake |
Tips:
- Single, simple subjects work best: animals, food, objects, plants, vehicles and fantasy items.
- Adjust guidance with cfg: 3–6 is the useful range; higher means stronger prompt following and less variety.
- Adjust steps with steps: 12 is faster; 20 is the default.
The Pinhole family
| Model | Params | Weights | CLIP score | T4 GPU | CPU |
|---|---|---|---|---|---|
pinhole-s |
13.1M | 26 MB | 30.28 | 187 ms | 1,844 ms |
pinhole-m |
34.4M | 69 MB | 30.36 | 225 ms | 3,661 ms |
pinhole-l |
70.8M | 142 MB | 30.57 | 258 ms | 6,764 ms |
| PixArt-LCM teacher (reference) | 600M + 4.7B text encoder | ~11 GB | 32.64 |
How it works
- Generator: a small diffusion transformer (adaLN-Zero blocks with cross-attention to text) predicts 4x32x32 latents with patch size 2 (256 tokens).
- Text: frozen CLIP ViT-B/32 text features (77 tokens plus the pooled embedding).
- Pixels: the TAESD decoder turns latents into 256x256 RGB.
- Training objective: rectified-flow matching (
x_t = (1 - t) x0 + t * noise, predictnoise - x0) with logit-normal timesteps and 10% caption dropout for classifier-free guidance. - Weights: an EMA of the training weights is shipped.
Training
- Data: nuhmanpk/darkroom-pinhole-18k, 18,000 images made by PixArt-alpha/PixArt-LCM-XL-2-1024-MS (4 steps) for short captions in 3 styles.
- Schedule: 24,000 steps, global batch 128, AdamW (lr 0.0002), warmup plus cosine, fp16, EMA 0.999, horizontal-flip augmentation.
- Hardware: Kaggle 2x T4, 211 minutes. Final training loss 0.3332.
Limitations
- Low resolution: 256x256, best for icons, sprites and stickers, not photographs.
- Simple subjects: it learned single, centered subjects on plain backgrounds. Complex scenes, counting, text in images and people are not supported.
- Limited by the teacher and a small dataset. Expect some off-prompt or blobby results, especially from
pinhole-s. The CLIP-score gap to the teacher is shown above. - English captions only.
License
CreativeML Open RAIL++-M, inherited from the PixArt-LCM teacher, including its use-based restrictions (see LICENSE.md).
pinhole.py is Apache-2.0.
Credits
Built by Nuhman PK. Teacher: PixArt-α / PixArt-LCM. Text encoder: OpenAI CLIP ViT-B/32. Decoder: TAESD by Ollin Boer Bohan. Training ideas from DiT and rectified flow.
Identity and Version
- Repository
- nuhmanpk/pinhole-l
- Publisher
- Nuhman PK
- Task
- Text to image
- Modality
- Image
- Library
- pytorch
- Parameters
- 71M parameters
- Languages
- en
- Revision
- 075ff1e7b2bd3f7e18a3fee3b7a1c0fa72e4d827
- First published
- 2026-10-05
- Last updated
- 2026-10-05
Files and Weights
18 files, 688.9 MB in total. The weights are 4 files totalling 683.5 MB in onnx, safetensors.
Every file
| File | Type | Size | SHA-256 |
|---|---|---|---|
| model.safetensors | Weights | 141.6 MB | 1ea65aedb4f9 |
| onnx/dit.onnx | Weights | 284.2 MB | 2fe47153a64f |
| onnx/taesd_decoder.onnx | Weights | 4.9 MB | 4824881a485c |
| onnx/text_encoder.onnx | Weights | 252.8 MB | d57da24f6bbc |
| config.json | Configuration | 508 B | — |
| pinhole.py | Configuration | 10.1 KB | — |
| train_log.json | Configuration | 2.6 KB | — |
| web/fixtures.json | Configuration | 14.1 KB | — |
| web/pinhole_web.json | Configuration | 855 B | — |
| LICENSE.md | Documentation | 669 B | — |
| README.md | Documentation | 6.0 KB | — |
| assets/banner.png | Other | 202.5 KB | c6c467f3ead9 |
| assets/samples_l.png | Other | 645.1 KB | 0f7ff2ce0a02 |
| assets/teacher_vs_pinhole.png | Other | 831.6 KB | cec303eab5d1 |
| web/pinhole-web.js | Other | 8.2 KB | — |
| .gitattributes | Repository | 1.7 KB | — |
| tokenizer.json | Tokenizer | 3.6 MB | — |
| tokenizer_config.json | Tokenizer | 350 B | — |
License and Download
- License
- openrail++
- Access
- Open weights, no gate
- Download size
- 683.5 MB
Released by Nuhman PK through its official repository on Hugging Face.
Built From
- Trained on (disclosed) nuhmanpk/darkroom-pinhole-18k
Memory Requirements
| Precision | Weights in memory |
|---|---|
| As published | 683.5 MB |
| 16-bit | 0.1 GB |
| 8-bit | 0.1 GB |
| 4-bit | 0.0 GB |
Weights only, from the published parameter count; the key-value cache and runtime add to this.
Questions About pinhole-l
How much GPU memory does pinhole-l need?
About 0.2 GB at 16-bit and 0 GB at 4-bit: the weights (71M parameters) plus a working margin. A long context needs more.
What is the cheapest GPU to run pinhole-l on?
At 16-bit, 1x MI300X from $1.85 an hour; at 4-bit, 1x MI300X from $1.85 an hour, at the lowest on-demand prices the SAVRN Index lists.
Can I use pinhole-l commercially?
Yes, with conditions. pinhole-l is released under Open RAIL++ License. Open RAIL++ permits use, including commercial use, subject to the use-based restrictions listed in the license, which must be passed on to downstream users.
Similar Models
A 13.1M-parameter text-to-image model for pixel art, flat icons and stickers. Small enough for laptops and, next, the browser. Part of Darkroom, a project to build tiny image generators that run where you are. The same held-out prompts, never seen in training, from the 0.6B teacher and from each Pinhole size: ONNX Runtime Web (WebAssembly or WebGPU), so prompts and images never leave the browser. Parity: the ONNX-only pipeline matches PyTorch to within a mean of 0.00/255 per pixel (same noise, 20 steps). The browser's tokenizer is checked against Python by the demo's Self-test button. Start with one of the three styles, then describe a simple subject: of a. - Adjust guidance with cfg: 3–6…
This is a modular diffusion pipeline built with Diffusers' modular pipeline framework. Description: Auto Modular pipeline for text-to-image and image-conditioned generation using Qwen-Image 2.1. - for text-to-image generation, all you need to provide is prompt - for image-conditioned generation, you need to provide prompt and image (one image or a list) This pipeline uses a 4-block architecture that can be customized and extended. [TODO] This modular pipeline is composed of the following blocks: 1. textencoder (QwenImage21AutoTextEncoderStep) - Text encoder step that encodes the prompt, together with the condition images when there are any. 2. vaeencoder (QwenImage21AutoVaeEncoderStep)…
GGUF, Safetensors, and MLX quantized formats of Qwen/Qwen-Image-2.1 for local image generation using the original upstream base weights. Q4KM is recommended for the best balance of size and quality for GGUF. INT8 ConvRot and NVFP4 offer high performance on supported GPUs, while MLX formats are optimized for Apple Silicon. Companion model files packaged for ComfyUI: Use the model with ComfyUI and ComfyUI-GGUF. All required companion files (GGUF transformer, text encoder, and VAE) are hosted directly in this repository. Download the files and place them in their respective ComfyUI directories: 1. Install ComfyUI-GGUF: Use the maintained fork with native Qwen-Image 2.1 support by cloning…
GGUF quantizations of Qwen/Qwen-Image-2.1 for local image generation using the original upstream base weights. Q4KM is recommended for the best balance of size and quality. Companion model files packaged for ComfyUI: Use the model with ComfyUI and ComfyUI-GGUF. All required companion files (GGUF transformer, text encoder, and VAE) are hosted directly in this repository. Download the files and place them in their respective ComfyUI directories: 1. Install ComfyUI-GGUF: Use the maintained fork with native Qwen-Image 2.1 support by cloning leejet/ComfyUI-GGUF into your custom nodes: (Note: If you have the older city96/ComfyUI-GGUF installed and encounter an Unknown model architecture! error…
This is a GGUF quantized version of Qwen-Image-2.1. unsloth/Qwen-Image-2.1-GGUF uses Unsloth Dynamic 2.0 methodology for SOTA performance. - Important layers are upcasted to higher precision, per tensor, from a measured sensitivity scan. - Run these with Unsloth Desktop, stable-diffusion.cpp and more. A GGUF is the denoiser only, so it needs the VAE and the Qwen3-VL text encoder alongside it. See below for image editing operating inside of Unsloth Desktop: Rendered with the Q4KM denoiser and the Q4KM text encoder, 1024x1024, 20 steps, cfg 6.0, euler. We are excited to open-source Qwen-Image-2.1, a unified text-to-image generation and image editing model in the Qwen family. With just 7B…