-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAPCA.ts
More file actions
86 lines (71 loc) · 2.3 KB
/
APCA.ts
File metadata and controls
86 lines (71 loc) · 2.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
// APCA code from https://github.com/Myndex/apca-w3/blob/c012257167d822f91bc417120bdb82e1b854b4a4/src/apca-w3.js
const exp = (c: number) => (c / 255.0) ** SA98G.mainTRC;
const hexToY = (colorHex: string) => {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(colorHex)!;
const r = parseInt(result[1], 16);
const g = parseInt(result[2], 16);
const b = parseInt(result[3], 16);
return SA98G.sRco * exp(r)
+ SA98G.sGco * exp(g)
+ SA98G.sBco * exp(b);
};
const contrast = (fg: number, bg: number): number => {
if (Math.min(fg, bg) < 0.0 || Math.max(fg, bg) > 1.1)
return 0.0;
if (fg <= SA98G.blkThrs)
fg += (SA98G.blkThrs - fg) ** SA98G.blkClmp;
if (bg <= SA98G.blkThrs)
bg += (SA98G.blkThrs - bg) ** SA98G.blkClmp;
if (Math.abs(bg - fg) < SA98G.deltaYmin)
return 0.0;
let outputContrast: number;
if (bg > fg) {
const sapc = (bg ** SA98G.normBG - fg ** SA98G.normTXT) * SA98G.scaleBoW;
outputContrast = sapc < SA98G.loClip
? 0.0
: sapc - SA98G.loBoWoffset;
} else {
const sapc = (bg ** SA98G.revBG - fg ** SA98G.revTXT) * SA98G.scaleWoB;
outputContrast = sapc > -SA98G.loClip
? 0.0
: sapc + SA98G.loWoBoffset;
}
return outputContrast * 100;
};
const SA98G = {
mainTRC: 2.4, // 2.4 exponent for emulating actual monitor perception
// For reverseAPCA
get mainTRCencode() { return 1 / this.mainTRC; },
// sRGB coefficients
sRco: 0.2126729,
sGco: 0.7151522,
sBco: 0.0721750,
// G-4g constants for use with 2.4 exponent
normBG: 0.56,
normTXT: 0.57,
revTXT: 0.62,
revBG: 0.65,
// G-4g Clamps and Scalers
blkThrs: 0.022,
blkClmp: 1.414,
scaleBoW: 1.14,
scaleWoB: 1.14,
loBoWoffset: 0.027,
loWoBoffset: 0.027,
deltaYmin: 0.0005,
loClip: 0.1,
};
export const getFgFor = (roleHex: string) => {
const bg = hexToY(roleHex);
const blackContrast = Math.abs(contrast(0, bg));
const whiteContrast = Math.abs(contrast(1, bg));
if (blackContrast > whiteContrast)
return "#000000";
else
return "#FFFFFF";
};