GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

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 #365

New issue
Copy link
New issue
Copy link
Open
Task
Open
colorthief is unmaintained and will break with Pillow 14#365
Task
Copy link
Assignees
anshuman83-40
Milestone
5.6.0

Description

@benoit74
benoit74
opened on Oct 29, 2026
Issue body actions

zimscraperlib.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

  1. 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)
  2. 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
  3. 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.

Activity

  1. benoit74
    added this to the 5.6.0 milestone on Oct 29, 2026
  2. benoit74
    added the
    Bug
    issue type on Oct 29, 2026
  3. benoit74
    changed the issue type from
    Bug
    to
    Task
    on Oct 29, 2026
  4. anshuman83-40 commented on Oct 29, 2026

    @anshuman83-40
    anshuman83-40
    on Oct 29, 2026
    Contributor
    More actions

    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?

  5. benoit74 commented on Oct 29, 2026

    @benoit74
    benoit74
    on Oct 29, 2026
    CollaboratorAuthor
    More actions

    @anshuman83-40 please proceed with option 1

  6. benoit74
    assigned
    anshuman83-40
    on Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @anshuman83-40
    anshuman83-40

Labels

No labels
No labels

Type

Task

Projects

No projects

    Milestone

    • 5.6.0No due date

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402520 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.