From 6f53b7634e8dc3f053e734f69708934c58b741c9 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Mon, 30 May 2022 16:39:11 +0200 Subject: [PATCH] Support for RGB <-> HSL --- ts/WoltLabSuite/Core/ColorUtil.ts | 83 +++++++++++++++++-- .../files/js/WoltLabSuite/Core/ColorUtil.js | 52 +++++++++++- 2 files changed, 124 insertions(+), 11 deletions(-) diff --git a/ts/WoltLabSuite/Core/ColorUtil.ts b/ts/WoltLabSuite/Core/ColorUtil.ts index afaa0d968a..cd3335a2e2 100644 --- a/ts/WoltLabSuite/Core/ColorUtil.ts +++ b/ts/WoltLabSuite/Core/ColorUtil.ts @@ -8,6 +8,44 @@ * @module WoltLabSuite/Core/ColorUtil */ +type HSVL = { + h: number; + s: number; + v: number; + l: number; +}; + +/** + * Converts a HSL color into RGB. + * + * @see https://www.rapidtables.com/convert/color/hsl-to-rgb.html + */ +export function hslToRgb(hue: number, saturation: number, lightness: number): RGB { + if (hue > 359) { + throw new TypeError("Hue cannot be larger than 359°"); + } + + saturation /= 100; + lightness /= 100; + + const C = (1 - Math.abs(2 * lightness - 1)) * saturation; + const X = C * (1 - Math.abs(((hue / 60) % 2) - 1)); + const m = lightness - C / 2; + + const [R, G, B] = ((0 <= hue && hue < 60 && [C, X, 0]) || + (60 <= hue && hue < 120 && [X, C, 0]) || + (120 <= hue && hue < 180 && [0, C, X]) || + (180 <= hue && hue < 240 && [0, X, C]) || + (240 <= hue && hue < 300 && [X, 0, C]) || + (300 <= hue && hue < 360 && [C, 0, X])) as number[]; + + return { + r: Math.round((R + m) * 255), + g: Math.round((G + m) * 255), + b: Math.round((B + m) * 255), + }; +} + /** * Converts a HSV color into RGB. * @@ -77,11 +115,11 @@ export function hsvToRgb(h: number, s: number, v: number): RGB { } /** - * Converts a RGB color into HSV. + * Converts a RGB color into HSVL. * * @see https://secure.wikimedia.org/wikipedia/de/wiki/HSV-Farbraum#Transformation_von_RGB_und_HSV */ -export function rgbToHsv(r: number, g: number, b: number): HSV { +function rgbToHsvl(r: number, g: number, b: number): HSVL { let h: number, s: number; r /= 255; @@ -119,13 +157,34 @@ export function rgbToHsv(r: number, g: number, b: number): HSV { s = diff / max; } + const l = (max + min) / 2; + return { h: Math.round(h), s: Math.round(s * 100), v: Math.round(max * 100), + l: Math.round(l * 100), }; } +/** + * Converts a RGB color into HSL. + */ +export function rgbToHsl(r: number, g: number, b: number): HSL { + const { h, s, l } = rgbToHsvl(r, g, b); + + return { h, s, l }; +} + +/** + * Converts a RGB color into HSV. + */ +export function rgbToHsv(r: number, g: number, b: number): HSV { + const { h, s, v } = rgbToHsvl(r, g, b); + + return { h, s, v }; +} + /** * Converts HEX into RGB. */ @@ -300,33 +359,41 @@ export function stringToRgba(color: string): RGBA { throw new Error(`Cannot process color '${color}'.`); } -export interface RGB { +export type RGB = { r: number; g: number; b: number; -} +}; -export interface RGBA { +export type RGBA = { r: number; g: number; b: number; a: number; -} +}; -export interface HSV { +export type HSV = { h: number; s: number; v: number; -} +}; + +export type HSL = { + h: number; + s: number; + l: number; +}; // WCF.ColorPicker compatibility (color format conversion) window.__wcf_bc_colorUtil = { hexToRgb, + hslToRgb, hsvToRgb, isValidColor, rgbaToHex, rgbaToString, rgbToHex, rgbToHsv, + rgbToHsl, stringToRgba, }; diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/ColorUtil.js b/wcfsetup/install/files/js/WoltLabSuite/Core/ColorUtil.js index 53b4575b6b..9f70e448c1 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/ColorUtil.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/ColorUtil.js @@ -10,7 +10,34 @@ define(["require", "exports"], function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - exports.stringToRgba = exports.isValidColor = exports.rgbaToString = exports.rgbaToHex = exports.rgbToHex = exports.hexToRgb = exports.rgbToHsv = exports.hsvToRgb = void 0; + exports.stringToRgba = exports.isValidColor = exports.rgbaToString = exports.rgbaToHex = exports.rgbToHex = exports.hexToRgb = exports.rgbToHsv = exports.rgbToHsl = exports.hsvToRgb = exports.hslToRgb = void 0; + /** + * Converts a HSL color into RGB. + * + * @see https://www.rapidtables.com/convert/color/hsl-to-rgb.html + */ + function hslToRgb(hue, saturation, lightness) { + if (hue > 359) { + throw new TypeError("Hue cannot be larger than 359°"); + } + saturation /= 100; + lightness /= 100; + const C = (1 - Math.abs(2 * lightness - 1)) * saturation; + const X = C * (1 - Math.abs(((hue / 60) % 2) - 1)); + const m = lightness - C / 2; + const [R, G, B] = ((0 <= hue && hue < 60 && [C, X, 0]) || + (60 <= hue && hue < 120 && [X, C, 0]) || + (120 <= hue && hue < 180 && [0, C, X]) || + (180 <= hue && hue < 240 && [0, X, C]) || + (240 <= hue && hue < 300 && [X, 0, C]) || + (300 <= hue && hue < 360 && [C, 0, X])); + return { + r: Math.round((R + m) * 255), + g: Math.round((G + m) * 255), + b: Math.round((B + m) * 255), + }; + } + exports.hslToRgb = hslToRgb; /** * Converts a HSV color into RGB. * @@ -71,11 +98,11 @@ define(["require", "exports"], function (require, exports) { } exports.hsvToRgb = hsvToRgb; /** - * Converts a RGB color into HSV. + * Converts a RGB color into HSVL. * * @see https://secure.wikimedia.org/wikipedia/de/wiki/HSV-Farbraum#Transformation_von_RGB_und_HSV */ - function rgbToHsv(r, g, b) { + function rgbToHsvl(r, g, b) { let h, s; r /= 255; g /= 255; @@ -106,12 +133,29 @@ define(["require", "exports"], function (require, exports) { else { s = diff / max; } + const l = (max + min) / 2; return { h: Math.round(h), s: Math.round(s * 100), v: Math.round(max * 100), + l: Math.round(l * 100), }; } + /** + * Converts a RGB color into HSL. + */ + function rgbToHsl(r, g, b) { + const { h, s, l } = rgbToHsvl(r, g, b); + return { h, s, l }; + } + exports.rgbToHsl = rgbToHsl; + /** + * Converts a RGB color into HSV. + */ + function rgbToHsv(r, g, b) { + const { h, s, v } = rgbToHsvl(r, g, b); + return { h, s, v }; + } exports.rgbToHsv = rgbToHsv; /** * Converts HEX into RGB. @@ -264,12 +308,14 @@ define(["require", "exports"], function (require, exports) { // WCF.ColorPicker compatibility (color format conversion) window.__wcf_bc_colorUtil = { hexToRgb, + hslToRgb, hsvToRgb, isValidColor, rgbaToHex, rgbaToString, rgbToHex, rgbToHsv, + rgbToHsl, stringToRgba, }; }); -- 2.20.1