Metadata-Version: 2.4
Name: ember-colorized
Version: 0.1.0
Summary: Apply Ember color palettes to images with high precision
Author: JesusChapman
Author-email: JesusChapman <jesuschapman@openlat.dev>
License-Expression: LGPL-3.0-only
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
Requires-Dist: numpy>=2.2.6
Requires-Dist: pillow>=12.3.0
Requires-Dist: scikit-learn>=1.7.2
Requires-Dist: torch>=2.7.0 ; extra == 'gpu'
Requires-Python: >=3.10
Project-URL: Homepage, https://openlat.dev/jesuschapman/ember-colorized
Project-URL: Repository, https://openlat.dev/jesuschapman/ember-colorized
Provides-Extra: gpu
Description-Content-Type: text/markdown

# Ember Colorizer

[English](README.md) · [Español](README.es.md)

Apply Ember color palettes to images with high precision.

## Installation

```bash
uv sync
```

### GPU acceleration (optional)

```bash
# Apple Silicon (MPS) or NVIDIA (CUDA)
pip install 'ember-colorized[gpu]'
```

## Usage

```bash
# Auto-generated output: filename-{palette}-colorized.ext
ember-colorizer --colors=ember-light /path/to/image.png

# Custom output path
ember-colorizer --colors=ember -o /path/to/output.png /path/to/image.jpg

# Fast mode (direct RGB mapping, no K-means)
ember-colorizer --colors=ember-soft -m fast /path/to/image.png

# Adjust recolor strength (0.0 = original, 1.0 = full)
ember-colorizer --colors=ember-light -s 0.7 /path/to/image.png

# More clusters for better accuracy (aggressive mode)
ember-colorizer --colors=ember -k 20 /path/to/image.png

# Use GPU acceleration (aggressive mode only)
ember-colorizer --colors=ember --use-gpu /path/to/image.png
```

## Palettes

| Palette | Background | Type |
|---------|-----------|------|
| `ember` | `#1c1b19` | dark |
| `ember-soft` | `#242320` | dark |
| `ember-light` | `#e6dac4` | light |
| `ember-lighter` | `#e8e4de` | light |

## Modes

### Aggressive mode (`-m aggressive`)

Uses **K-means clustering** to analyze the image before recoloring.

**What is K-means?** It's an algorithm that groups similar colors together. Imagine throwing 12 darts at a color wheel — each dart moves to the "center of gravity" of the colors closest to it. After several rounds, the darts settle on the most representative colors in the image.

**How it works:**
1. K-means finds the 12 dominant colors in your image (configurable with `-k`)
2. Each dominant color is mapped to its nearest Ember palette color (RGB Euclidean distance)
3. Every pixel is reassigned to its cluster's mapped palette color
4. Strength controls the blend between original and recolored

**Result:** Colors group naturally — sky areas stay coherent, skin tones stay unified. Best for photos and complex images.

### Fast mode (`-m fast`)

**Direct pixel-by-pixel RGB nearest-color mapping** — no clustering, no filters. Each pixel independently maps to the closest Ember palette color using Euclidean distance in RGB space.

**How it works:**
1. For each pixel, compute Euclidean distance to all palette colors in RGB space
2. Replace the pixel with the nearest palette color

**Result:** Maximum detail preservation — edges, gradients, fine lines (anime hair, outlines) stay sharp. Best for anime, illustrations, line art, or when speed matters.

### GPU acceleration (`--use-gpu`)

When `--use-gpu` is passed, K-means clustering runs on the GPU with smart downsampling — clusters on a 200K-pixel subset, then assigns all pixels vectorized. This greatly accelerates the recoloring time for complex, high-resolution images.

**Supported backends** (auto-detected):
| Backend | Hardware | Package |
|---------|----------|---------|
| cuML | NVIDIA GPU | `cuml-cu12` |
| PyTorch MPS | Apple Silicon | `torch` |
| PyTorch CUDA | NVIDIA GPU | `torch` |
| sklearn | CPU fallback | (always available) |

**Performance** (5304×7952 image, 12 clusters):
| Backend | Time |
|---------|------|
| CPU (sklearn) | ~127s |
| GPU (Apple MPS) | ~8s |

**Output example:**
```
Input:    photo.png
Palette:  ember (Ember)
Mode:     aggressive
Strength: 1.0
GPU:      yes (Apple (arm64))
Output:   photo-ember-colorized.png
  ⠹ Clustering colors...
Success! in 7.818s
```

### Key differences

| | Aggressive | Fast |
|---|---|---|
| Algorithm | K-means → cluster mapping | Direct RGB nearest-color |
| Speed | Slower (clustering pass) | Fastest (vectorized) |
| Accuracy | Higher (cluster coherence) | Good (per-pixel) |
| Best for | Photos, complex scenes | Anime, illustrations, line art |
| Control | `-k` clusters, `-s` strength | `-s` strength only |
| GPU | `--use-gpu` supported | CPU only |

## Showcase

- High-resolution image recoloring using GPU --use-gpu

![gpu_yes](./showcase/use_gpu.png)

- Same image recoloring using CPU only

![gpu_no](./showcase/use_cpu.png)

- Simple image recoloring using fast mode

![fast_mode](./showcase/fast_mode.png)

As you can see, when processing a high-resolution image, GPU mode significantly accelerates the process.

This feature has been tested on Apple Silicon GPUs; it should also work on NVIDIA. If you encounter any issues with your GPU, feel free to open an [issue](https://openlat.dev/JesusChapman/ember-colorized/issues/new).

## License

LGPL-3.0
