GeezerVison is showing github.com — colorthief is unmaintained and will break with Pillow 14 · Issue #365 · openzim/python-scraperlib
colorthief is unmaintained and will break with Pillow 14 #365Descriptionzimscraperlib.image.probing.get_colors relies on colorthief (pinned to 0.2.1), which calls Image.Image.getdata(). Pillow 13 deprecates this method and will remove it in Pillow 14 (2027-10-15):
colorthief.py:65: DeprecationWarning: Image.Image.getdata is deprecated and will be removed in Pillow 14 (2027-10-15). Use get_flattened_data instead.
pixels = image.getdata()
This is currently the only warning raised by our test suite (tests/image/test_image.py::test_colors_*).
Our pillow<14.0 upper bound protects us for now, but it means we will be stuck on Pillow 13 until this is solved.
colorthief is unmaintained
- last release (0.2.1) is from February 2017, last commit from 2019
- a fengsp/color-thief-py#36 issue about this exact deprecation got no answer from the maintainer
- an upstream fix and release is hence very unlikely
Options
- Vendor colorthief into zimscraperlib (BSD-licensed, ~420 lines including docstrings, pure Python, only depends on Pillow), replacing
getdata() by get_flattened_data().
- pros: no new dependency, exact same colors as today (no change for scrapers), we can type it properly and drop the many
pyright: ignore in get_colors
- cons: we own the maintenance of the code (but the MMCQ algorithm is stable, only Pillow API evolutions are expected to matter)
- Switch to
modern_colorthief, a Rust re-implementation created precisely because of this deprecation (MIT, actively maintained, last release 0.3.0 in June 2026).
- pros: maintained, fast, no Python dependency
- cons: single maintainer and low adoption (supply-chain risk), compiled wheels needed for all platforms our scrapers run on (amd64/arm64, glibc/musl), results are slightly different from colorthief (see their DIFFERENCES.md) so our expected colors in tests (and scrapers output) would change slightly; to be assessed on our test images
- Reimplement with Pillow only (
Image.quantize(..., method=Quantize.MEDIANCUT) + getcolors()).
- pros: no dependency, very little code
- cons: different algorithm, so different colors; colorthief also ignores white and transparent pixels, which we would need to replicate
Other packages considered and discarded: fast-colorthief (needs numpy, no release since 2023, no wheels for recent Python), Pylette (way too heavy: OpenCV, scikit-learn, ...), extcolors and haishoku (unmaintained since 2019/2020).
Proposal
Option 1 seems the most conservative one: it removes an unmaintained dependency without changing any output nor adding a new third-party dependency. Option 2 is worth considering if we prefer not to own this code. Activityanshuman83-40 commented on Oct 29, 2026 I'd be happy to work on this. Option 1 seems the safest to me since it keeps exactly the same colours for existing scrapers and adds no dependency: vendor colorthief (keeping its BSD license notice), replace getdata() with get_flattened_data(), add type hints so the pyright: ignores in get_colors can go, and then lift the pillow<14 bound once Pillow 14 is out. Would that work for you, or do you prefer another option? benoit74 commented on Oct 29, 2026 CollaboratorAuthor More actions
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|