Fully offline AI image generation and editing for Mac Silicon (Apple MPS). No cloud. No API keys. No subscriptions. Everything runs on your machine.
Standalone project. Started as a fork of newideas99/ultra-fast-image-gen but has diverged significantly — Gradio replaced with a FastAPI backend + React UI, new features (batch img2img, depth maps, watermark removal, LoRA stacking, iterative inpainting), and a different architecture overall. Not intended to track upstream.
- Text-to-image — generate images from a prompt
- Image-to-image editing — upload a reference photo and transform it with natural language
- Inpainting — draw a rectangle mask on any region and regenerate just that area
- Multi-slot reference images — up to 6 reference images, each with its own mask and strength slider
- Iterative multi-mask inpainting — chain multiple mask passes automatically (one per slot)
- Video generation — text-to-video and image-to-video with LTX-Video
- Multi-LoRA stacking — load up to 5
.safetensorsLoRA adapters simultaneously, each with its own strength slider; the dropdown is filtered to only show LoRAs compatible with the active model - Batch img2img — point at a folder of images and run the current prompt + params over all of them automatically; gallery updates after each image
- Upscaling — 4× single image or batch-folder upscale with any Spandrel-compatible model
- Workflow save/load — save your full setup (model, params, reference images, masks) and reload it later
- Gallery — browse recent outputs, drag them into reference slots, upscale or delete
- Depth map generation — generate 16-bit DA3 depth maps directly from the Gallery; white = near, black = far
- Auto-outpaint — automatically fill borders when the reference image is a different aspect ratio
| Model | VRAM | Notes |
|---|---|---|
| FLUX.2-klein-4B (4-bit SDNQ) | < 8 GB @ 512 px | Fastest FLUX — text + image editing |
| FLUX.2-klein-9B (4-bit SDNQ) | ~12 GB @ 512 px | Higher quality |
| FLUX.2-klein-4B (Int8) | ~16 GB | Alternative quantization |
| Z-Image Turbo (Quantized) | ~8 GB | Fastest overall — text-to-image only |
| Z-Image Turbo (Full) | ~24 GB | LoRA support |
| LTX-Video | — | Text-to-video / image-to-video |
Models are downloaded automatically the first time you select them. They are cached in ./models/.
| Minimum | |
|---|---|
| Mac | Apple Silicon (M1 or later) — macOS 13+ |
| Python | 3.11 or 3.12 |
| RAM | 16 GB recommended (more = better) |
| Disk | ~20 GB per model |
git clone https://github.com/KrissTos/off-line-Image-gen-mac.git
cd off-line-Image-gen-macThen double-click Launch.command in Finder.
The first launch installs all dependencies (~5 min). A browser tab opens automatically at http://localhost:7860.
Terminal lifecycle: The Terminal window that opens is managed automatically. When you close the browser tab the server shuts down and Terminal closes itself — you don't need to quit it manually. Refreshing the page reconnects within ~1 s and cancels the shutdown.
# Install uv (package manager) if you don't have it
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create venv and install deps
uv venv
source .venv/bin/activate
uv sync
# Build the frontend
cd frontend && npm install && npm run build && cd ..
# Start the server
python server.py --port 7860Open http://localhost:7860 in your browser.
./Launch.command --dev
# FastAPI on :7861, Vite HMR on :5173- Open the UI and select a model from the Model accordion in the sidebar
- Click Load Model — the model downloads from HuggingFace and is cached locally
- Some models are gated (require a free HuggingFace account + accepting terms):
- Create an account at huggingface.co
- Accept the model terms on the model page
- Paste your Read token in Settings → HuggingFace Login
┌──────────────────────────────────────────────────────────┐
│ TopBar — model name · device · VRAM · status │
├──────────────┬───────────────────────────────────────────┤
│ │ Canvas (result image / video) │
│ Sidebar ├───────────────────────────────────────────┤
│ (params) │ Reference image slots + mask editor │
│ ├───────────────────────────────────────────┤
│ │ Gallery (recent outputs) │
└──────────────┴───────────────────────────────────────────┘
| Section | What it does |
|---|---|
| Model | Pick and load a model |
| Parameters | Steps, guidance scale, seed, repeat count |
| Size | Output resolution — presets change per model |
| LoRA | Stack up to 5 LoRA adapters, each with its own strength; filtered by active model |
| Upscale | 4× single image or batch folder |
| Batch Img2Img | Process a whole folder of images with the current settings |
| Video | LTX-Video settings (only visible with LTX model) |
| Depth Map | Generate a 16-bit depth PNG for the current output image |
| Workflows | Save / load your full setup |
- Click + to add a reference image (upload, drag from gallery, or paste a URL)
- Click the pencil icon to draw a rectangle mask — only that region will be regenerated
- Adjust the strength slider per slot (how much the model can change the image)
- Slot #1 is always the base image; slots #2+ are style references
| Mode | When to use |
|---|---|
| Crop & Composite (Fast) | Quick edits — crops the masked region, generates at lower res, composites back |
| Inpainting Pipeline (Quality) | Full-resolution inpainting — slower but cleaner results (Z-Image only) |
When Inpainting Pipeline (Quality) is selected and you have masks on multiple slots, the button changes to Iterate Masks. This chains the generation passes: output of pass N becomes the input of pass N+1, applying each mask in sequence.
Workflows save your entire session — model, all parameters, reference images, masks, and strength values — into a folder under workflows/.
- Save — type a name and click Save → creates
workflows/yy-mm-dd_name/ - Load — pick from the dropdown (last 15 shown) and click Load
- Open — click the folder icon to browse to any workflow folder in Finder
Images are saved to ~/Pictures/ultra-fast-image-gen/ by default (change in Settings).
Each image gets a .json sidecar with the prompt, seed, model, and all parameters.
Filename format: YYYYMMDD_prompt-slug.png (collisions get _2, _3 suffix).
When reference images or masks are present, a companion folder prompt-slug/ is created alongside the image containing params.json, ref_slot_N.png, and mask.png.
Open Settings (gear icon, top-right):
| Setting | Description |
|---|---|
| Output folder | Where generated images are saved |
| HuggingFace token | Required for gated models |
| Models | See which models are cached, download, delete |
| Upscale models | Manage upscaler weights |
| Model Sources | Curated list of base models, LoRAs, and upscalers — open HF page or download; locally cached entries highlighted with a green border |
| Server log | View and save the current session log |
| Hardware | Time |
|---|---|
| M3 Max (36 GB) | ~11 s |
| M2 Max (32 GB) | ~15 s |
| Hardware | Time |
|---|---|
| M2 Max | ~14 s |
| M1 Max | ~23 s |
off-line-Image-gen-mac/
├── server.py ← FastAPI backend + static file server (main entry point)
├── app.py ← Generation logic, model management (no Gradio)
├── pipeline.py ← Async bridge: FastAPI ↔ generation thread (SSE)
├── generate.py ← CLI for Z-Image Turbo only
├── Launch.command ← 1-click Mac launcher (production + dev modes)
│
├── frontend/ ← React + Vite + TypeScript UI → builds to frontend/dist/
│ └── src/
│ ├── App.tsx ← Root: SSE handler, ref-slot logic, iterate loop
│ ├── store.ts ← useReducer global state
│ ├── api.ts ← Typed fetch helpers
│ ├── types.ts ← Shared TypeScript types
│ └── components/
│ ├── Sidebar.tsx ← All generation params + accordions
│ ├── Canvas.tsx ← Result image / video + progress overlay
│ ├── RefImagesRow.tsx ← Reference image slots + mask editor
│ ├── Gallery.tsx ← Recent outputs strip
│ ├── TopBar.tsx ← Brand, model, device, VRAM status
│ ├── SettingsDrawer.tsx ← HF login, model list, storage, log
│ ├── MaskEditorModal.tsx← Rectangle mask drawing canvas
│ └── HelpTip.tsx ← Inline ⓘ tooltips
│
├── core/
│ ├── depth_map.py ← DA3 / DA2 depth estimation → 16-bit PNG
│ ├── lora_flux2.py ← LoRA for FLUX.2-klein (PEFT)
│ ├── lora_zimage.py ← LoRA for Z-Image (forward-patch)
│ ├── quantized_flux2.py ← 4-bit SDNQ + int8 quantization
│ └── workflow_utils.py ← Workflow save/load, ComfyUI importer
│
├── models/ ← Downloaded model weights (gitignored)
├── lora_uploads/ ← User-uploaded LoRA files (gitignored)
├── upscale_models/ ← Upscaler weights (gitignored)
├── workflows/ ← Saved workflow folders
└── logs/ ← Server logs (server.log + timestamped snapshots)
All contributions are welcome — bug reports, feature ideas, new model support, UI improvements, docs.
- Bug? → open an Issue
- Idea? → start a Discussion
- Question? → use Q&A Discussions
- Code? → fork, branch, PR — please describe what you changed and why
- FLUX.2-klein by Black Forest Labs
- Z-Image Turbo by Alibaba / Tongyi
- SDNQ quantization by Disty0
- LTX-Video by Lightricks
- diffusers by HuggingFace
- Spandrel for upscaling
See the individual model licenses for usage terms. Project source code is provided as-is for personal and research use.