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+.
pip install -e .
For development (includes pytest):
pip install -e ".[dev]"
The lab quantization method additionally requires scikit-image:
pip install scikit-image
Usage
color-counter file.pdf
By default, only the global summary is printed. Add --per-page to also print a table for every page.
Examples
# 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.
Metadata
Release files for color-counter 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| color_counter-0.1.0.tar.gz | 11.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| color_counter-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.9 kB
Release files / color_counter-0.1.0.tar.gz
| Download URL | color_counter-0.1.0.tar.gz |
|---|---|
| Size | 11.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
00848bdbf6d7ae795004abf0715965d73755e6de21a0932995bf5721e8a05ecf
|
|
BLAKE2b-256 checksum How to use checksums |
809fbcf3c812c94e5c0724e632fc34d25860937ef070891a13920d8dc60fcb02
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.10.12 Linux/6.8.0-124-generic
|
Release files / color_counter-0.1.0-py3-none-any.whl
| Download URL | color_counter-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ff482b7bad38d14d423d06a24a5c73804d2d420670bfd467a0610c3c8f330551
|
|
BLAKE2b-256 checksum How to use checksums |
43f503a0b05271df6b869cc6951bf3a45796c2859bd7a4a1ff953130131b0152
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.10.12 Linux/6.8.0-124-generic
|
Security for color-counter 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.