Last active
October 4, 2019 18:02
-
-
Save SephReed/8c762f3434d683c66339f63342e8ae4b to your computer and use it in GitHub Desktop.
Incomplete snippet of code used for HSLum
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function rangeLimit(num: number, min: number, max: number) { | |
return Math.max(min, Math.min(num, max)); | |
} | |
export function rangeWrap(num: number, circumference: number) { | |
return ((num % 1) + 1) % 1; | |
} | |
const ratioR = 4; | |
const ratioG = 4; | |
const ratioB = 3; | |
const sum = ratioR + ratioG + ratioB; | |
const ColorResponse = { | |
r: ratioR / sum, | |
g: ratioG / sum, | |
b: ratioB / sum, | |
// b: .114, | |
// g: .587, | |
// r: .299, | |
}; | |
export { ColorResponse }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { IHSLA, IHSVA, IRGBA } from "../"; | |
import { HSVA as HsvaTool, RGBA as RgbaTool} from "../ColorTools"; | |
import { ColorResponse, rangeLimit, rangeWrap } from "./ColorMath"; | |
export default class HSLATool { | |
public static toHex(hsla: IHSLA): string { | |
return RgbaTool.toHex(this.toRGBA(hsla)); | |
} | |
public static toRGBA(hsla: IHSLA, mode: "fast" | "precise" = "precise"): IRGBA { | |
this.correctValues(hsla); | |
if (hsla.l <= 0) { | |
return { r: 0, g: 0, b: 0, a: hsla.a }; | |
} | |
if (hsla.l >= 1) { | |
return { r: 255, g: 255, b: 255, a: hsla.a }; | |
} | |
if (hsla.s === 0) { | |
return { | |
a: hsla.a, | |
b: Math.floor(255 * hsla.l), | |
g: Math.floor(255 * hsla.l), | |
r: Math.floor(255 * hsla.l), | |
}; | |
} | |
interface ILumaColor { | |
color: string; | |
value: number; | |
lumaFix: number; | |
} | |
const rgba = HsvaTool.toRGBA({ | |
h: hsla.h, | |
s: hsla.s, | |
v: 1, | |
}); | |
const max = {} as any as ILumaColor; | |
const mid = {} as any as ILumaColor; | |
const min = {} as any as ILumaColor; | |
const maxMidMin = [max, mid, min]; | |
([ | |
[`r`, rgba.r, ColorResponse.r], | |
[`g`, rgba.g, ColorResponse.g], | |
[`b`, rgba.b, ColorResponse.b], | |
] as Array<[string, number, number]>).sort((a, b) => b[1] - a[1]) | |
.forEach((item, i) => { | |
maxMidMin[i].color = item[0]; | |
maxMidMin[i].value = item[1]; | |
maxMidMin[i].lumaFix = item[2]; | |
}); | |
if (mode === "fast") { | |
let lumsAddedAtMaxScale = 0; | |
maxMidMin.forEach((item: ILumaColor) => { | |
lumsAddedAtMaxScale += (item.lumaFix * (item.value / max.value)); | |
}); | |
if (lumsAddedAtMaxScale >= hsla.l) { | |
const scale = hsla.l / lumsAddedAtMaxScale; | |
rgba.r = rgba.r * scale; | |
rgba.g = rgba.g * scale; | |
rgba.b = rgba.b * scale; | |
} else { | |
let remainder = hsla.l - lumsAddedAtMaxScale; | |
let lumaPerUnit = (mid.lumaFix + min.lumaFix) / 255; | |
const unitsToAdd = remainder / lumaPerUnit; | |
if (unitsToAdd <= 255 - rgba[mid.color]) { | |
rgba[mid.color] += unitsToAdd; | |
rgba[min.color] += unitsToAdd; | |
} else { | |
rgba[mid.color] = 255; | |
remainder = hsla.l - (max.lumaFix + mid.lumaFix); | |
lumaPerUnit = min.lumaFix / 255.0; | |
rgba[min.color] = remainder / lumaPerUnit; | |
} | |
} | |
RgbaTool.correctValues(rgba); | |
return rgba; | |
} else { | |
const ratioMid = mid.value / max.value; | |
const ratioMin = min.value / max.value; | |
const targetMax = Math.sqrt( | |
Math.pow(hsla.l, 2) | |
/ (max.lumaFix | |
+ (mid.lumaFix * Math.pow(ratioMid, 2)) | |
+ (min.lumaFix * Math.pow(ratioMin, 2)) | |
), | |
); | |
const scaledHue = {a: hsla.a} as any; | |
scaledHue[max.color] = targetMax * 255; | |
scaledHue[mid.color] = targetMax * ratioMid * 255; | |
scaledHue[min.color] = targetMax * ratioMin * 255; | |
RgbaTool.correctValues(scaledHue); | |
if (targetMax > 1) { | |
const targetWhiteLightLum = hsla.l - (max.lumaFix + (ratioMid * mid.lumaFix) + (ratioMin * min.lumaFix)); | |
// const lightToAdd = targetWhiteLightLum / (mid.lumaFix + min.lumaFix); | |
const currentLum = RgbaTool.getLuminosity(scaledHue); | |
const mixAmount = (hsla.l - currentLum) / (1 - currentLum); | |
scaledHue[mid.color] += (255 - scaledHue[mid.color]) * mixAmount; | |
scaledHue[min.color] += (255 - scaledHue[min.color]) * mixAmount; | |
} | |
// if (targetMax > 1.3 - overlap) { | |
// const targetWhiteLightLum = hsla.l - max.lumaFix | |
// - (mid.lumaFix * ratioMid) | |
// - (min.lumaFix * ratioMin) | |
// + .03 - (.12 * hsla.s); | |
// const targetWhiteAdd = Math.sqrt( | |
// Math.pow(targetWhiteLightLum, 2) | |
// / (mid.lumaFix + min.lumaFix), | |
// ); | |
// const whiteOut = {a: hsla.a} as any; | |
// whiteOut[max.color] = 255; | |
// whiteOut[mid.color] = (ratioMid + (targetWhiteAdd * (1 + hsla.s))) * 255; | |
// whiteOut[min.color] = (ratioMin + (targetWhiteAdd * (1 + hsla.s))) * 255; | |
// RgbaTool.correctValues(whiteOut); | |
// const mixAmount = (targetMax - (1 - overlap)) / overlap; | |
// if (mixAmount >= 1) { | |
// return whiteOut; | |
// } else { | |
// scaledHue.r += (scaledHue.r - whiteOut.r) * mixAmount; | |
// scaledHue.g += (scaledHue.g - whiteOut.g) * mixAmount; | |
// scaledHue.b += (scaledHue.b - whiteOut.b) * mixAmount; | |
// RgbaTool.correctValues(scaledHue); | |
// } | |
// } | |
RgbaTool.correctValues(scaledHue); | |
return scaledHue; | |
} | |
} | |
public static toHSVA(hsla: IHSLA): IHSVA { | |
throw new Error("Method not implemented."); | |
} | |
public static correctValues(hsla: IHSLA): void { | |
hsla.h = rangeWrap(hsla.h, 1); | |
hsla.s = rangeLimit(hsla.s, 0, 1); | |
hsla.l = rangeLimit(hsla.l, 0, 1); | |
hsla.a = hsla.a !== undefined ? rangeLimit(hsla.a, 0, 1) : 1; | |
} | |
public static getLuminosity(hsla: IHSLA): number { | |
return hsla.l; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment