Skip to main content
Glama
colors.ts4.2 kB
// Color conversion utilities for Hue lights export interface RGB { r: number; // 0-255 g: number; // 0-255 b: number; // 0-255 } export interface HSV { h: number; // 0-360 s: number; // 0-100 v: number; // 0-100 } export interface XY { x: number; y: number; } // Convert RGB to XY color space (Philips Hue format) export function rgbToXy(rgb: RGB): XY { // Normalize RGB values const r = rgb.r / 255; const g = rgb.g / 255; const b = rgb.b / 255; // Apply gamma correction const red = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92; const green = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92; const blue = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92; // Convert to XYZ using Wide RGB D65 conversion formula const X = red * 0.664511 + green * 0.154324 + blue * 0.162028; const Y = red * 0.283881 + green * 0.668433 + blue * 0.047685; const Z = red * 0.000088 + green * 0.072310 + blue * 0.986039; // Calculate xy from XYZ const sum = X + Y + Z; if (sum === 0) { return { x: 0, y: 0 }; } return { x: X / sum, y: Y / sum, }; } // Convert HSV to RGB export function hsvToRgb(hsv: HSV): RGB { const h = hsv.h / 360; const s = hsv.s / 100; const v = hsv.v / 100; const i = Math.floor(h * 6); const f = h * 6 - i; const p = v * (1 - s); const q = v * (1 - f * s); const t = v * (1 - (1 - f) * s); let r: number, g: number, b: number; switch (i % 6) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; default: r = 0; g = 0; b = 0; } return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255), }; } // Convert natural language color to HSV export function parseColorDescription(description: string): HSV | null { const colors: Record<string, HSV> = { // Basic colors 'red': { h: 0, s: 100, v: 100 }, 'orange': { h: 30, s: 100, v: 100 }, 'yellow': { h: 60, s: 100, v: 100 }, 'green': { h: 120, s: 100, v: 100 }, 'cyan': { h: 180, s: 100, v: 100 }, 'blue': { h: 240, s: 100, v: 100 }, 'purple': { h: 270, s: 100, v: 100 }, 'magenta': { h: 300, s: 100, v: 100 }, 'pink': { h: 330, s: 50, v: 100 }, 'white': { h: 0, s: 0, v: 100 }, // Atmospheric colors 'sunrise': { h: 30, s: 60, v: 90 }, 'sunset': { h: 15, s: 80, v: 85 }, 'dusk': { h: 250, s: 30, v: 40 }, 'dawn': { h: 200, s: 20, v: 70 }, 'stormy': { h: 240, s: 20, v: 30 }, 'stormy dusk': { h: 250, s: 35, v: 25 }, // Warm/cool 'warm': { h: 30, s: 40, v: 90 }, 'cool': { h: 200, s: 30, v: 90 }, 'cold': { h: 200, s: 50, v: 80 }, // Nature-inspired 'forest': { h: 120, s: 60, v: 40 }, 'ocean': { h: 200, s: 70, v: 60 }, 'sky': { h: 200, s: 40, v: 90 }, 'fire': { h: 10, s: 90, v: 90 }, 'ice': { h: 200, s: 20, v: 95 }, }; const normalized = description.toLowerCase().trim(); // Direct match if (colors[normalized]) { return colors[normalized]; } // Partial match for (const [key, value] of Object.entries(colors)) { if (normalized.includes(key) || key.includes(normalized)) { return value; } } return null; } // Convert color temperature name to mireds export function parseColorTemp(description: string): number | null { const temps: Record<string, number> = { 'candlelight': 500, // 2000K 'candle': 500, 'warm white': 370, // 2700K 'warm': 370, 'soft white': 323, // 3100K 'neutral': 250, // 4000K 'neutral white': 250, 'cool white': 182, // 5500K 'cool': 182, 'daylight': 153, // 6500K 'cold': 153, }; const normalized = description.toLowerCase().trim(); if (temps[normalized]) { return temps[normalized]; } // Check for partial matches for (const [key, value] of Object.entries(temps)) { if (normalized.includes(key) || key.includes(normalized)) { return value; } } return null; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rmrfslashbin/hue-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server