PrismatIQ v0.6.1

A high-performance Crystal shard for extracting dominant color palettes from images using the YIQ color space. This is a port of the Color Thief logic (MMCQ) but optimized for Crystal's performance and perception-based color math.

PrismatIQ

A high-performance Crystal shard for extracting dominant color palettes from images using the YIQ color space. This is a port of the Color Thief logic (MMCQ) but optimized for Crystal's performance and perception-based color math.

Features

  • Color Palette Extraction: Extract dominant colors from any image format
  • SVG Support: Extract colors directly from SVG vector graphics (no rasterization needed)
  • WCAG Accessibility: Built-in WCAG contrast checking and color adjustment
  • Theme Detection: Automatic dark/light theme detection and color pairing
  • ICO Support: Extract palettes from Windows icon files (PNG and BMP encoded)
  • Multi-threaded: Parallel histogram building for improved performance
  • Caching: Intelligent caching for frequently-used calculations
  • Error Handling: Explicit error handling with Result types

Quick Examples

Basic Palette Extraction

require "prismatiq"

options = PrismatIQ::Options.new(color_count: 5, quality: 10, threads: 0)

# With explicit error handling (recommended)
result = PrismatIQ.get_palette_v2("image.png", options)
case result
when .ok?
  result.value.each { |color| puts color.to_hex }
when .err?
  puts "Error: #{result.error.message}"
end

# Or the raising variant
begin
  colors = PrismatIQ.get_palette_v2!("image.png", options)
  colors.each { |color| puts color.to_hex }
rescue ex : Exception
  puts "Failed: #{ex.message}"
end

Single Color Extraction

color = PrismatIQ.get_color("image.png")
if color
  puts color.to_hex
end

Theme Extraction

# Extract theme (background + text colors) from file or URL
theme = PrismatIQ.extract_theme("favicon.ico")
if theme
  puts "Background: #{theme.bg}"
  puts "Light text: #{theme.text["light"]}"
  puts "Dark text: #{theme.text["dark"]}"
end

# For caching across calls, manage your own instance
extractor = PrismatIQ::ThemeExtractor.new
theme = extractor.extract("favicon.ico")
extractor.clear_cache

SVG Color Extraction

# From SVG string
colors = PrismatIQ::SVGColorExtractor.extract_colors(%(<svg><rect fill="#FF0000"/></svg>))

# From SVG file
result = PrismatIQ::SVGColorExtractor.extract_from_file("icon.svg")

Buffer-based Extraction

palette = PrismatIQ.get_palette_from_buffer(pixels, width, height, options)

Documentation

Version

0.6.2

Security Considerations

SSRF Protection

When using the ThemeExtractor to fetch images from URLs, PrismatIQ includes built-in Server-Side Request Forgery (SSRF) protection:

  • Private IP Blocking: Requests to private/reserved IP ranges are blocked by default:
    • IPv4: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16, 0.0.0.0/8
    • IPv6: ::1/128, fc00::/7, fe80::/10
  • URL Scheme Validation: Only http:// and https:// URLs are allowed
  • DNS Rebinding Protection: IP addresses are resolved and validated before connection

Configuration

config = PrismatIQ::Config.new(ssrf_protection: false)

Or via environment variables:

export PRISMATIQ_SSRF_PROTECTION=false
export PRISMATIQ_SSRF_ALLOWLIST=internal.company.com,localhost

Path Validation

When extracting from local files, PrismatIQ validates:

  • Path Traversal: Blocks .. and URL-encoded variants (%2e%2e, %252e%252e)
  • Null Byte Injection: Rejects paths containing \0
  • System Directories: Prevents access to system paths on Linux
  • File Size Limits: Enforces 100MB maximum file size

Debug Mode

When PRISMATIQ_DEBUG=true is set, all caught exceptions are logged to STDERR. This may include sensitive information (URLs, file paths) - use only during development.

Repository

PrismatIQ

Owner
Statistic
  • 0
  • 0
  • 0
  • 1
  • 2
  • about 2 hours ago
  • February 6, 2026
License

Links
Synced at

Mon, 20 Apr 2026 11:06:04 GMT

Languages