From e218f6dcabbc98e81726fc1f4064e1e1747f60bb Mon Sep 17 00:00:00 2001 From: ginnyTheCat Date: Thu, 8 Oct 2020 17:19:28 +0200 Subject: [PATCH] Changed rainbow algorithm --- src/utils/colour.js | 67 ---------------------------------- src/utils/colour.ts | 87 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 67 deletions(-) delete mode 100644 src/utils/colour.js create mode 100644 src/utils/colour.ts diff --git a/src/utils/colour.js b/src/utils/colour.js deleted file mode 100644 index 2ec904c0d3..0000000000 --- a/src/utils/colour.js +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -export function hueToRGB(h, s, l) { - const c = s * (1 - Math.abs(2 * l - 1)); - const x = c * (1 - Math.abs((h / 60) % 2 - 1)); - const m = l - c / 2; - - let r = 0; - let g = 0; - let b = 0; - - if (0 <= h && h < 60) { - r = c; - g = x; - b = 0; - } else if (60 <= h && h < 120) { - r = x; - g = c; - b = 0; - } else if (120 <= h && h < 180) { - r = 0; - g = c; - b = x; - } else if (180 <= h && h < 240) { - r = 0; - g = x; - b = c; - } else if (240 <= h && h < 300) { - r = x; - g = 0; - b = c; - } else if (300 <= h && h < 360) { - r = c; - g = 0; - b = x; - } - - return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)]; -} - - -export function textToHtmlRainbow(str) { - const frequency = 360 / str.length; - - return Array.from(str).map((c, i) => { - const [r, g, b] = hueToRGB(i * frequency, 1.0, 0.5); - return '' + c + ''; - }).join(""); -} diff --git a/src/utils/colour.ts b/src/utils/colour.ts new file mode 100644 index 0000000000..5a170094a1 --- /dev/null +++ b/src/utils/colour.ts @@ -0,0 +1,87 @@ +/* +Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { number } from "prop-types"; + +export function textToHtmlRainbow(str: string): string { + const frequency = (2 * Math.PI) / str.length; + + return Array.from(str) + .map((c, i) => { + if (c === " ") { + return c; + } + const [a, b] = generateAB(i * frequency, 1); + const [red, green, blue] = labToRGB(75, a, b); + return ( + '' + + c + + "" + ); + }) + .join(""); +} + +function generateAB(hue: number, chroma: number): [number, number] { + const a = chroma * 127 * Math.cos(hue); + const b = chroma * 127 * Math.sin(hue); + + return [a, b]; +} + +function labToRGB(l: number, a: number, b: number): [number, number, number] { + // Convert CIELAB to CIEXYZ (D65) + var y = (l + 16) / 116; + const x = adjustXYZ(y + a / 500) * 0.9505; + const z = adjustXYZ(y - b / 200) * 1.089; + + y = adjustXYZ(y); + + // Linear transformation from CIEXYZ to RGB + const red = 3.24096994 * x - 1.53738318 * y - 0.49861076 * z; + const green = -0.96924364 * x + 1.8759675 * y + 0.04155506 * z; + const blue = 0.05563008 * x - 0.20397696 * y + 1.05697151 * z; + + return [adjustRGB(red), adjustRGB(green), adjustRGB(blue)]; +} + +function adjustXYZ(v: number): number { + if (v > 0.2069) { + return Math.pow(v, 3); + } + return 0.1284 * v - 0.01771; +} + +function gammaCorrection(v: number): number { + // Non-linear transformation to sRGB + if (v <= 0.0031308) { + return 12.92 * v; + } + return 1.055 * Math.pow(v, 1 / 2.4) - 0.055; +} + +function adjustRGB(v: number): number { + const corrected = gammaCorrection(v); + + // Limits number between 0 and 1 + const limited = Math.min(Math.max(corrected, 0), 1); + + return Math.round(limited * 255); +}