league/color-extractor
League ColorExtractor is a PHP package for extracting representative colors from images, with palette helpers, most-used color detection, and transparency handling via Composer.
One primitive, several roadmap items. league/color-extractor turns any uploaded image into structured data — a palette of colors with pixel counts, plus an extract(n) call for the most representative ones. That single integration seeds a family of features that would otherwise look like separate bets: shop-by-color filters, auto-tagging catalog items, dominant-color "blur-up" placeholders on product cards, theme generation from a merchant's logo, and color-based sorting in a media library. As a PM, the pitch to yourself is leverage: one queued job and one column buys optionality across four or five backlog items.
Build vs. buy vs. wrap. The realistic options are hand-rolled GD/Imagick code, a commercial color/vision API, or this package. It lands in the sweet spot for a PHP/Laravel shop: MIT-licensed, self-hosted, no per-call cost, no vendor onboarding, no user images leaving the infrastructure (material if the images are unreleased product shots or user-generated content). Scope is genuinely one sprint — a job, a cached column, an endpoint — so treat it as a shippable enabler, not a platform commitment.
Data-model decisions it forces (decide these early). Output is integers/hex plus counts. That supports a dominant_color hex column alongside a JSON palette cast on the product/media record, and it supports your own dominance threshold ("only call this item 'red' if red exceeds X% of pixels"). It does not give human-readable names — "red sneakers," "navy," "burgundy" all require a separate hex→name mapping plus a QA process. Scope that as its own work item; do not let stakeholders assume it comes free.
Roadmap sequencing that de-risks the visible feature. (1) Batch-backfill the existing catalog and measure how often extraction is correct enough against a human-labeled sample; (2) ship an internal admin view of extracted palettes with merchandiser override; (3) only then expose the filter to customers. The invisible work funds the credibility of the visible work.
Decisions it should not drive. Treat it as a heuristic, not a vision model. It knows which colors are present and in what proportion; it does not know a shoe is white with a red sole, does not classify patterns, and is not a substitute for ML visual search. Also, do not assume it handles every format users upload — GD's coverage is narrower than reality, so "unsupported image" is a product path with copy and telemetry, not an edge case. Finally, anything accessibility-adjacent (WCAG contrast, harmony generation, perceptual ΔE distance) is a separate layer on top of the counts, not a feature of this library.
Adopt when:
ext-gd is present in every target environment. Confirm this before committing; it's the single most common adoption blocker, and default CLI Docker images ship without it. Add "ext-gd": "*" to composer.json so deploys fail loudly rather than at runtime.Look elsewhere when:
Two product decisions to make explicit rather than inherit:
Palette::fromFilename($path, Color::fromHexToInt('#FFFFFF'))) so a 50%-opacity red reads as it would on the page.To executives: "We can make the image library searchable and themeable by color for roughly one sprint of engineering and zero ongoing vendor cost. It's a small, MIT-licensed, self-hosted PHP library that reads an image and returns its dominant colors the way a person would describe them — no third-party API, no per-image fees, no image data leaving our systems. It's the same primitive behind several roadmap items: shop-by-color filters, automatic palette generation from merchant logos, and better sorting in the media library. The honest caveats: it's a heuristic, not machine learning — it knows colors are present, not that a shoe is 'white with a red sole' — so we'll launch behind an internal review screen where merchandisers can override results, and expose it to customers only after we've measured accuracy on a real catalog sample. The one technical dependency is a standard PHP image extension we must confirm is enabled in all environments."
To engineering: "Small, focused library — Palette::fromFilename/fromContents/fromUrl builds a color histogram, ColorExtractor::extract(n) returns representative colors, Color::fromIntToHex for output. Pure PHP plus ext-gd, PHP 8 supported, MIT, no framework coupling. Bind it in the container, wrap it in a queued job, cache the result on the model. Three things I want aligned before we build: (1) confirm ext-gd everywhere and define the degraded path for unreadable images; (2) downscale before extraction; (3) make an explicit transparency decision — the default drops all alpha pixels, so logos and cut-outs should blend against a known background. And assume a thin wrapper so we can swap implementations later without touching call sites."
How can I help you explore Laravel packages today?