Regions Package
Internal utility package for extracting colours from specific regions of 2D images for ambient lighting applications.
Overview
This package provides functionality to sample colours from edges and corners of images in various configurations (4, 8, 12, or 16 regions). It's designed to support ambient LED lighting setups where lights are positioned around a monitor and should match colours from the wallpaper edges.
Features
- Multiple Configurations: Support for 4, 8, 12, and 16 region layouts
- Flexible Sampling: Configurable sample size and extraction method
- RoleHints Integration: Automatically maps extracted colours to positional semantic roles
- Two Extraction Methods:
- Average: Calculate average colour of all pixels in region (default)
- Dominant: Find most frequent colour in region (more vibrant)
Configurations
4 Regions - Corners Only
[TL] [TR]
Monitor
[BL] [BR]
- Use Case: Budget setups, small monitors
- Positions: 4 corners
8 Regions - Corners + Mid-Edges (Default)
[T]
[L] [R]
Monitor
[L] [R]
[B]
- Use Case: Standard setups, 24-32" monitors
- Positions: 4 corners + 4 mid-edges
- Recommended for most users
12 Regions - Corners + Double Edges
[TL] [T] [TR]
[L] [R]
Monitor
[L] [R]
[BL] [B] [BR]
- Use Case: Large monitors, ultrawide displays
- Positions: 4 corners + 8 edge positions (2 per edge)
16 Regions - Corners + Triple Edges
[TL][TL][T][TR][TR]
[L] [R]
Monitor
[L] [R]
[BL][BL][B][BR][BR]
- Use Case: Enthusiast setups, massive displays
- Positions: 4 corners + 12 edge positions (3 per edge)
Usage
Basic Example
package main
import (
"image"
_ "image/jpeg"
"os"
"github.com/jmylchreest/tinct/internal/plugin/input/shared/regions"
)
func main() {
// Load an image
file, _ := os.Open("wallpaper.jpg")
defer file.Close()
img, _, _ := image.Decode(file)
// Create sampler
sampler := regions.NewSampler()
// Extract 8 regions (default)
palette, err := sampler.Extract(img, regions.Config8Regions)
if err != nil {
panic(err)
}
// palette.Colours contains the extracted colours
// palette.RoleHints maps positional roles to colour indices
}
Custom Configuration
// Create sampler with custom settings
sampler := ®ions.Sampler{
SamplePercent: 15, // Sample 15% of edges (default: 10%)
Method: "dominant", // Use dominant colour (default: "average")
}
// Extract 12 regions
palette, err := sampler.Extract(img, regions.Config12Regions)
Accessing Results
palette, _ := sampler.Extract(img, regions.Config8Regions)
// Colours are in the palette
for i, colour := range palette.Colours {
rgb := colour.ToRGB(colour)
fmt.Printf("Colour %d: %s\n", i, rgb.Hex())
}
// RoleHints map positions to colour indices
for role, index := range palette.RoleHints {
colour := palette.Colours[index]
fmt.Printf("%s -> Colour %d: %s\n", role, index, colour.ToRGB(colour).Hex())
}
Positional Roles
The package uses semantic roles from internal/colour to identify positions:
Core 8 Positions
RolePositionTopLeft
RolePositionTop
RolePositionTopRight
RolePositionRight
RolePositionBottomRight
RolePositionBottom
RolePositionBottomLeft
RolePositionLeft
Extended Positions (12 regions)
RolePositionTopLeftInner
RolePositionTopRightInner
RolePositionRightTop
RolePositionRightBottom
RolePositionBottomRightInner
RolePositionBottomLeftInner
RolePositionLeftBottom
RolePositionLeftTop
Ultra Positions (16 regions)
RolePositionTopLeftCenter
RolePositionTopCenter
RolePositionTopRightCenter
RolePositionRightTopOuter
RolePositionRightBottomOuter
RolePositionBottomRightCenter
RolePositionBottomCenter
RolePositionBottomLeftCenter
RolePositionLeftBottomOuter
RolePositionLeftTopOuter
Sampling Strategy
Sample Size
- Default: 10% of edge dimensions
- Adjustable: 1-50% via
SamplePercent
- Automatic Scaling: Reduces for higher region counts to avoid overlap
- 8 regions: 10% (default)
- 12 regions: 8%
- 16 regions: 6%
Average (default):
- Calculates arithmetic mean of all pixels in region
- Produces natural, smooth colours
- Best for most use cases
Dominant:
- Finds most frequent colour in region (quantized)
- Produces more vibrant, saturated colours
- Better for images with distinct colour blocks
Integration with Image Plugin
This package is designed to be used by the image input plugin:
// In image plugin
if mode == "ambient" {
sampler := regions.NewSampler()
return sampler.Extract(img, regions.Config8Regions)
}
Extraction is very fast:
- 4 regions: ~0.02s
- 8 regions: ~0.04s
- 12 regions: ~0.06s
- 16 regions: ~0.08s
Performance scales linearly with region count and sample size.
Design Decisions
Why Not More Regions?
- Beyond 16 regions, diminishing visual returns
- Most LED setups have 4-16 lights
- Complexity increases significantly
- Sample overlap becomes an issue
Why Positional Roles?
- RoleHints system allows explicit mapping
- Output plugins can map roles to physical light IDs
- Separates extraction from output
- Extensible to other LED systems
Why Sample Percentage?
- Allows users to control precision vs averaging
- Larger samples = smoother, more representative colours
- Smaller samples = more precise, position-specific colours
- Default (10%) works well for most images
Testing
# Run tests
go test ./internal/plugin/input/shared/regions
# Run with coverage
go test -cover ./internal/plugin/input/shared/regions
See Also