4rn0 / statamic-image-colors
Background and text colors that match your images, picked per asset.
Package info
github.com/4rn0/statamic-image-colors
Type:statamic-addon
pkg:composer/4rn0/statamic-image-colors
Requires
- php: ^8.3
- ext-fileinfo: *
- ksubileau/color-thief-php: ^3.0
- statamic/cms: ^6.16
Requires (Dev)
- orchestra/testbench: ^10.8
- phpunit/phpunit: ^11.5
Suggests
- ext-gd: To sample JPEG, PNG, GIF and WebP images.
- ext-imagick: To sample AVIF and animated WebP as well.
Provides
None
Conflicts
None
Replaces
None
README
Image Colors gives every image asset a palette of its own colors, and lets an editor decide which one is the color of that image. Templates get it as hex, RGB, HSL or OKLCH, plus whether it is light or dark, which text color reads on it, and how much contrast that gives. Use it for a background behind a photo, a caption band beneath it, a placeholder while it loads, a card tinted to match. The image file itself is never touched.
What you get
- A palette, automatically. Six colors per image, sampled on upload and again whenever the file changes, on the queue when the site has one. Existing images are handled from the asset browser or the command line.
- One color per image, chosen by a human. Swatches in the asset editor: the first is the dominant color and applies by default, click any swatch to pin it, or pick a color of your own with the color picker or the eyedropper. A pinned color is kept even when a new palette no longer contains it.
- Ready for CSS.
{{ hero:imagecolors }}prints hex,:rgb,:hsland:oklchprint CSS functions,:r:g:bthe channels. - Text that reads on the color.
:textgives black or white, whichever contrasts more with that color, and:contrastthe WCAG ratio of that pairing. - Nothing to configure. No config file, no settings screen, no new permissions: whoever may edit an asset may pin its color.
- Every container, remote and private disks included.
- Your own fields stay yours. Everything lives under one
imagecolorskey on the asset; a field or value of your own with that name is left alone.
In a template
A background that matches the image, and a caption that reads on it:
{{ hero }}
<figure style="background: {{ imagecolors }}; color: {{ imagecolors:color:text }}">
<img src="{{ url }}" alt="{{ alt }}">
<figcaption>{{ alt }}</figcaption>
</figure>
{{ /hero }}
A title on a band in the image's color, above or below the photo:
<header style="background: {{ hero:imagecolors }}; color: {{ hero:imagecolors:color:text }}"> <h2>{{ title }}</h2> </header> <img src="{{ hero:url }}" alt="{{ hero:alt }}">
:text and :contrast are measured against that one solid color, not against the
photo. A picture of a bright sky over a dark street can have a dark dominant color, and
the white text that reads fine on it disappears once it sits on the sky. So put text on
the color, not straight on the image; if it has to overlap the photo, give the text a
background of its own, such as a band or a semi-transparent overlay in {{ hero:imagecolors }}.
And the whole palette, for a strip or a gradient:
{{ hero:imagecolors:colors }}<i style="background: {{ hex }}"></i>{{ /hero:imagecolors:colors }}
Everything else is in DOCUMENTATION.md.
Requirements
Statamic 6.16 or later, PHP 8.3, and GD or Imagick. Statamic already needs one of those for Glide, and Image Colors uses whichever one your site is set to.
Edge cases
- JPEG, PNG, GIF and WebP work everywhere. AVIF needs Imagick, or a GD built with libavif. Animated images are sampled from their first frame. SVG is skipped: it has no pixels.
- Near-white pixels are ignored, so a product shot on a white background gives you the
product's color instead of
#fefefe. Pick white by hand if that is what you wanted. - The palette comes from a 200 pixel copy, so a single-pixel accent will not turn up in it.
- The dominant color is not stored, it is simply the first of the palette, so re-sampling an edited image can change it. Pin the color on images where that matters.
- One color per asset, not per entry. The same photo on three pages has one color; if a page needs its own, that is a color field on the entry.
- Without a queue the sampling runs during the upload request and costs about a second per image.
Works well with
Image Colors only reads pixels. Two other addons of mine write them, and all three follow the same conventions:
- ImageOptimizer makes JPEG, PNG, GIF and WebP files smaller with jpegoptim, pngquant, optipng, gifsicle and cwebp, and keeps the originals.
- Image Editor crops, rotates and adjusts images in the control panel and saves over the asset.
Both rewrite the file, so the palette is sampled again afterwards, while a color you pinned stays. Both are paid; Image Colors needs neither of them.
Install
composer require 4rn0/statamic-image-colors php please image-colors:extract
Image Colors is free and MIT licensed. Color extraction is done by Color Thief, MIT, © Kevin Subileau.