Small curiosities, with room to become something.

A space for creative coding, visual studies, and practical ideas. Try the experiments, then take a look behind the build.

Featured experimentInteractive gallery · WordPress plugin

Opening your gallery…

01 / Design and development

Color Scope.

A photograph can be remembered as a color before it has a name. I built a gallery around that idea, with a visual color filter and an editor that makes the details easy to shape.

Pick a color and explore. Open the editor to change the layout, add images, or build your own filters. Save to update the gallery here.

Built with
PHP · JavaScript · Canvas
Format
WordPress gallery plugin
Color views
Four measured displays
Your changes
Saved in this browser

Color Scope

Behind the build

Designing Color Scope

A photograph holds
more than one story.

Color Scope began as a different way to browse photographs. Instead of starting with a filename, a visitor could start with a color. Building that interaction exposed a more interesting question: which colors actually matter in a photograph?

A small red flower against a large blue sky became the test. So did a photographer who wanted to explore a collection by camera and film stock. Those two examples shaped the plugin: measured color, room for editorial judgment, and filters that belong to the collection rather than to a fixed category.

01 / Start with the photograph

Keep a distribution,
not one average color.

A single average can describe a color that barely appears in the image. A single dominant swatch can lose the small detail that makes the photograph interesting. The early coarse bins needed to become a richer description of the actual pixels.

The plugin makes a small analysis copy, preserving the full composition and aspect ratio. Its longest side is bounded at 96 pixels. Nearby RGB samples are grouped, but each group keeps a real sampled pixel close to its mean as its representative. That distinction matters: the palette should show colors that came from the photograph.

Each image retains up to 256 measured color groups, two kinds of weight, and a spatial summary. Coverage describes how much of the image a color occupies. Attention adds an estimate of visual importance. The spatial summary keeps enough information to revisit a selected subject area without resampling the full photograph.

Every photograph contributes the same total weight to the collection display. A larger upload doesn’t get a louder voice simply because it contains more pixels.

The measurement path

  1. Full compositionA bounded, uncropped analysis copy.
  2. Measured color groupsReal RGB representatives, coverage, and attention.
  3. Spatial memoryUp to 16 × 16 cells preserve color and position.
  4. Two outputsA collection-wide instrument and image-specific matching.

The originals remain untouched. Compact profiles do the filtering work.

A note on color profiles and palette swatches

The WordPress analyzer uses an embedded sRGB profile with Imagick when an input profile is available, with a separate GD fallback. Browser-added images in this playground use the browser’s image decoder and Canvas. Those are different processing environments. The image viewer groups measured colors in Oklab, merges near-duplicates, and selects up to three influential representatives. An almost monochrome image can have fewer than three; it doesn’t need invented colors to fill the space.

02 / Build a usable color instrument

The coordinates stay fixed.
The collection gives them shape.

The displays borrow from photographic scopes, but the interaction is explicitly a hue-and-saturation map. It isn’t a broadcast Cb/Cr vectorscope. Keeping that distinction clear let the visual character serve a precise, understandable control.

Density scope rendered from this gallery's measured colors
Density scopeAngle selects hue. Distance from the center selects saturation. Measured samples accumulate into clusters.
Hue landscape rendered from the same gallery
Hue landscapeHue runs left to right. Peaks show prevalence. Vertical pointer position still chooses saturation.
Radial spectrum rendered from the same gallery
Radial spectrumHue has a fixed direction. Bar length shows its weight. Pointer radius controls saturation.
Color field rendered from the same gallery
Color fieldHue runs horizontally, saturation vertically. Contour bands reveal where measured colors concentrate.

A pointer position is converted into a hue from 0 to 359 degrees and a saturation from neutral to fully saturated. Circular displays use angle and distance from the center. Rectangular displays use horizontal and vertical position. All four views feed the same matcher.

Pointer capture keeps a drag connected even when a finger or mouse moves outside the canvas. Fine controls provide separate hue and saturation sliders for keyboard use and precise adjustment. Quick swatches provide another way in.

The field represents the current collection, including its metadata filters and text search. It stays still while someone changes the color, sorts results, or moves between pages. Otherwise, selecting a color would erase the surrounding colors and move the target underneath the pointer.

The RGB and HEX readout belongs to the selected search color. The picker uses a normalized brightness for that reference. The viewer’s palette swatches are a different thing: measured colors from the actual photograph, including their lightness.

03 / Give the match range a clear meaning

A wider search should
still know what red means.

The earlier wide-range behavior loosened two things at once: color similarity and the amount of matching color an image needed. At larger settings, the results could feel arbitrary. A predominantly red image shouldn’t become a green match just because the range is wide.

I separated tolerance from presence. The range now broadens a bounded neighborhood of related hues and saturation levels. It doesn’t lower the minimum presence rule. A candidate still needs enough matching color, a sufficient score, and a meaningful share of its chromatic palette.

Hue comparison uses both HSV hue and perceptual Oklab hue. That helps with natural olive and green neighbors that can be awkwardly spaced in HSV. Neutrals follow their own rule, instead of borrowing an arbitrary hue from almost gray pixels.

What the range changes

Precise
12° neighborhood
Related
45° neighborhood

Hue tolerance expands with the slider. The required presence of matching color stays in place.

A wider setting explores neighboring colors. It does not turn the entire color wheel into a match.

The rules behind the result

Hue tolerance is 12 + 33 × range, with range normalized from 0 to 1. Saturation tolerance expands from 0.22 to 0.85. Chromatic matches require at least 16% matching weight, a score of at least 0.105, and a share of the chromatic palette appropriate to the matching mode. Neutral matching requires 40% neutral weight. These are product rules, not a universal definition of photographic meaning.

The development checks included opposite hue families, natural olive foliage, small contrasting subjects, incidental color, and increasing range. A permissive range still had to reject unrelated primary colors. Changing a label on the slider wouldn’t have fixed the underlying behavior.

04 / The subject-focus dilemma

The sky takes more space.
The flower may matter more.

The original question was specific: if a red flower occupies a small part of a blue-sky photograph, should the image be considered red? Coverage answers what occupies the frame. It can’t decide what the photographer meant.

I kept two matching preferences. Similar palettes uses the image’s color coverage. Subject-aware palettes combines coverage with an attention estimate. The automatic estimate looks at contrast against the image border, position within the frame, and the amount of color present. It does not identify objects or read intent.

That estimate helps, but a bright sign could be more noticeable than the intended subject. So the image editor also lets the owner choose a subject area. Draw a box, redraw it, adjust its percentages with the keyboard, or return to Automatic.

The selected rectangle is stored as relative coordinates. The matcher intersects it with the spatial color cells, maps those cells back to the measured color groups, and builds a new attention distribution. It doesn’t crop the image or throw away its surrounding palette.

Subject-aware matching blends 35% coverage with 65% attention. The overall photograph still contributes. Manual focus guides that balance when the automatic estimate misses.

Illustrative red flower against a larger blue sky, used to demonstrate color coverage
Search this study for red

Illustrative test image, measured with the same profile and matching logic. Range: 28%. The box guides attention; it doesn’t alter the image.

In this example, automatic attention improves the red weight but still misses the eligibility rule. The selected subject area produces a match. That is exactly why the manual correction belongs in the editor.

05 / Make the filters belong to the collection

A label is a choice.
A value makes it useful.

The first use case was camera and film stock. One photographer needed “Camera used for this shot” paired with “Nikon F3,” then “Film stock used for this shot” paired with “Kodak Portra 400.” Hard-coding Camera and Film would have solved only that one use case.

The editor instead gives each gallery three optional detail fields. The label belongs to the gallery. The value belongs to the individual image. A field-level switch decides whether the values also become a filter. Filled details still appear in the image viewer when filtering is off, while empty details disappear.

That same structure can describe an artist, material, location, client, project, season, or collection. It is open to the owner’s categories within three reusable fields, rather than promising a separate feature for every possible archive.

Previously entered values become suggestions. Bulk editing applies shared details to several images, while leaving unchecked fields alone. A recorded camera can be suggested when that metadata is available. Labels and switches don’t have to be re-entered for every photograph.

Same structure, different collections

Labels are shared. Values are image-specific. Each field can become a filter.

The 1.4.0 image editor showing a subject area, camera and film labels, per-image values, and filter switches
From the 1.4.0 development build: the subject area and reusable label/value fields share the image-details editor. The pictured artwork is test imagery.
Within one fieldNikon F3 or another camera

Several selected values are alternatives.

Across fieldsCamera and film and color

Each additional field narrows the results.

Filtering changes which images are included and updates the count. Sorting changes their order. The scope then represents the metadata-filtered collection, so it can tell the color story of one camera, one material, or one project. Selecting a color narrows the photographs without rebuilding that base map.

Small rules that keep flexible fields manageable

Values are compared without surrounding whitespace or letter-case differences. Filter choices come from values actually present in the gallery. Counts reflect the other active conditions, and unavailable options can be disabled without hiding a current selection. Search includes image details as well as titles and captions. A color reset leaves the metadata selection intact; clearing collection filters is a separate action.

These are categorical filters. Three reusable fields do not mean an unlimited field builder, date-range queries, or numeric comparison rules. The flexibility comes from letting each owner define useful categories without changing the plugin’s code.

06 / Finding the visual character

From soft patches
to weighted contours.

The visual iterations were about making the data legible. The earlier fields were too muted. The right idea was there, but pale spots didn’t communicate the concentrated areas clearly enough.

Development comparison of the 1.4.1 and 1.5.0 color fields using identical illustrative profiles
An early comparison from the build: stronger cores improved the field, but the density still needed a clearer visual structure.

The field places each weighted color at fixed hue and saturation coordinates, then spreads its influence through a Gaussian density calculation. Overlapping contributions build concentration. Contour bands make those differences visible without drawing every individual sample.

Hue wraps around the edge of the map, so red doesn’t become two unrelated regions at opposite ends. The bandwidth stays fixed. This keeps the relative color contributions meaningful while the collection determines the shape.

Once the contour structure worked, it still looked too transparent on white and too dim on black. The 1.5.3 refinement raised the six bands to 68%, 78%, 87%, 94%, 98%, and 100% opacity. The density map, coordinates, and underlying weights stayed the same.

Light and dark backgrounds are remembered independently for each display. The goal was a clear instrument in either setting, without muting the photographs to make the interface feel restrained.

Actual 1.5.2 and 1.5.3 renderer comparison showing stronger contour opacity on white and black
Actual renderer comparison from the 1.5.3 update. Identical illustrative profiles, unchanged positions and weights, stronger separation from both backgrounds.
07 / Design both sides of the gallery

The editor should explain
what each choice changes.

The editor developed alongside the front end. Six sections separate the starting design, images, layout and loading, color filter, image viewer, and style. Visual presets make the first choice concrete. A live preview connects every adjustment to its result.

The less common settings sit behind specific disclosures rather than filling the screen at once. Image details live with the images. Shared labels, bulk values, and subject focus use the same editing context because they all describe how a photograph participates in the gallery.

On smaller screens, the editor gives settings and preview their own space. The Save action stays reachable, inputs have room for readable text, and the image-detail dialog uses the available height. Reordering also has explicit arrows, so dragging is optional.

The image viewer has independent choices

Layout
Simple / Image and story
Tone
Light / Dark
Surface
Solid / Blurred page

The controls remember their values when the popup is disabled. Re-enabling it restores the chosen combination.

The viewer originally tied too many choices together. Separating layout, tone, and surface made eight combinations possible without eight unrelated presets. Navigation moved above the photograph. Notes became a content-sized panel that could be shown or hidden. The three influential colors stayed stacked vertically, with separate RGB and HEX copy actions.

Even the blur needed a structural correction. A compositing boundary in the viewer prevented a child background from sampling the page behind it. Moving the backdrop treatment to the outer viewer made the blur work without applying any filter to the photograph itself.

08 / Make repeated use feel settled

The small shifts
were worth investigating.

Filtering to zero results exposed a sideways jump. It was measurable: the desktop scrollbar disappeared, adding 15 pixels to the viewport and moving the centered scope 7.5 pixels. Reserving that space and stabilizing short result sets addressed the cause.

Rapid selections also needed a different rhythm from a single change. The control and readout respond immediately. Incoming thumbnails get a short opportunity to prepare. Retained photographs ease into new positions, outgoing images leave once, and newer selections replace work that has become stale.

Horizontal galleries needed to retain the position after a drag. Arrow navigation now aligns to actual image boundaries rather than assuming every card has the same width. A movement threshold separates a deliberate drag from opening a photograph.

Input hints follow the way someone is interacting. Touch, mouse, and keyboard get appropriate guidance. Native page scrolling remains available outside the color control and subject-selection area. Reduced-motion preferences remove nonessential movement.

The WordPress version also separates cached page markup from the current public gallery manifest. Saving a gallery publishes its current settings and images; the renderer revalidates them instead of trusting an old cached embed. The public manifest keeps internal editing data out of its response.

Here, visitors have their own saved browser gallery. They can change settings, add images, adjust subject focus, rename detail fields, enable filters, and save the result back to the working gallery on this page. The editor and front end use the same renderer and matching logic.

Where it landed

Measured color.
Human judgment.
A collection’s own language.

The result is a gallery that can be explored visually and configured around the material it contains. Its most important decisions are connected: a stable color map, bounded matching, a way to correct subject importance, and reusable fields that make the same system useful beyond its first photography example.

Development notes and limits

The source package includes checks for color-family rejection, selected subject geometry, detail-field persistence, filter combinations, gallery layouts, caching behavior, and viewer settings. Those records distinguish real browser and WordPress checks from simulated DOM checks. They aren’t a claim that every device or hosting configuration behaves identically.

Automatic subject awareness remains an estimate. Small analysis copies and spatial summaries trade fine detail for fast, bounded work. The public editor saves to this browser, while the installable WordPress plugin saves authorized changes to the site’s gallery. Neither makes an artistic decision on the photographer’s behalf.

Small decisions change the whole reading.

A type study in emphasis. The words stay the same; the contrast changes how you read them.

Make room for a different reading.

Creative coding

Small interactive systems that give an idea something tangible to become.

Visual studies

Type, texture, movement, and the subtle decisions that shape an experience.

Useful automation

Practical workflows that make more room for thinking, designing, and making.