Metadata-Version: 2.4
Name: color-counter
Version: 0.1.0
Summary: Count and analyze colors in PDF files
Author-email: Louis Devillez <louis.devillez@gmail.com>
License: MIT License
        
        Copyright (c) 2026 Louis Devillez
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Requires-Python: >=3.10
Requires-Dist: click>=8.1.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: pillow>=10.0.0
Requires-Dist: pymupdf>=1.23.0
Requires-Dist: rich>=13.0.0
Requires-Dist: scikit-learn>=1.3.0
Provides-Extra: dev
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# color-counter

A command-line tool to count and analyze colors in PDF files. It rasterizes each page, extracts pixel color frequencies, and displays ranked color tables with terminal swatches.

## Features

- Per-page color tables and a cross-page summary
- Three quantization methods to group similar colors: exact top-N, k-means (RGB), k-means (perceptual LAB)
- Optional gray separation: isolate near-gray colors into their own table
- Page range selection
- Pixel-sampling stride for faster analysis of large documents
- Configurable terminal color system for accurate swatch rendering

## Installation

Requires Python 3.10+.

```bash
pip install -e .
```

For development (includes pytest):

```bash
pip install -e ".[dev]"
```

The `lab` quantization method additionally requires [scikit-image](https://scikit-image.org/):

```bash
pip install scikit-image
```

## Usage

```bash
color-counter file.pdf
```

By default, only the global summary is printed. Add `--per-page` to also print a table for every page.

### Examples

```bash
# Summary only (default)
color-counter report.pdf

# Per-page tables + summary
color-counter report.pdf --per-page

# Analyze only pages 2 to 5
color-counter report.pdf --pages 2-5

# Reduce to 8 dominant colors using perceptual clustering
color-counter report.pdf --reduce 8 --method lab

# Separate gray shades (max channel spread ≤ 15) into their own table
color-counter report.pdf --gray-threshold 15

# Fix swatches that all look the same color
color-counter report.pdf --color-system truecolor

# Fast pass on a large document (sample every 4th pixel)
color-counter report.pdf --sample-step 4
```

## Options

| Option | Default | Description |
|---|---|---|
| `--dpi N` | `150` | Rasterization resolution |
| `--top N` | `10` | Top N colors shown per table |
| `--reduce N` | — | Reduce palette to N colors before reporting |
| `--method` | `kmeans` | Color reduction method: `exact`, `kmeans`, `lab` |
| `--sample-step N` | `1` | Pixel sampling stride (>1 skips pixels for speed) |
| `--pages RANGE` | all | Page range, e.g. `1-3` or `2,4` |
| `--summary / --no-summary` | on | Print aggregated total across all pages |
| `--per-page / --no-per-page` | off | Print a color table for each page |
| `--gray-threshold N` | — | Separate colors with max RGB spread ≤ N into a gray table |
| `--color-system` | `auto` | Terminal color depth: `auto`, `truecolor`, `256`, `standard`, `none` |

### Color reduction methods

| Method | Description |
|---|---|
| `exact` | Keep the N most frequent raw colors, no merging |
| `kmeans` | Cluster similar colors in RGB space (weighted by pixel count) |
| `lab` | Cluster in perceptual CIE LAB space — better at grouping visually similar colors. Requires `scikit-image`. |

### Gray threshold

A color is classified as gray when its maximum RGB channel minus its minimum RGB channel is at or below the threshold.

- `0` — only exact grays where R = G = B (pure black, white, neutral)
- `15` — also catches near-grays from anti-aliasing or compression artifacts

### Swatch colors look wrong

If swatches all appear as the same color, your terminal's color depth is being misdetected. Run with `--color-system truecolor` to force 24-bit color output.

## Architecture

| Module | Role |
|---|---|
| `rasterizer.py` | PDF → PIL Images via PyMuPDF |
| `analyzer.py` | PIL Image → `ColorData` (unique colors + pixel counts) |
| `quantizer.py` | `ColorData` → reduced `ColorData` (exact / k-means / LAB) |
| `reporter.py` | `ColorData` → Rich terminal tables |
| `cli.py` | Click entry point wiring everything together |

## License

MIT — see [LICENSE](LICENSE).
