| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
# OKHSL, Conveter under Copyright (c) 2021 Björn Ottosson, see LICENSE.OK |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package Graphics::Toolkit::Color::Space::Instance::OKHSL; |
|
5
|
16
|
|
|
16
|
|
269406
|
use v5.12; |
|
|
16
|
|
|
|
|
51
|
|
|
6
|
16
|
|
|
16
|
|
116
|
use warnings; |
|
|
16
|
|
|
|
|
23
|
|
|
|
16
|
|
|
|
|
697
|
|
|
7
|
16
|
|
|
16
|
|
763
|
use Graphics::Toolkit::Color::Space qw/spow/; |
|
|
16
|
|
|
|
|
24
|
|
|
|
16
|
|
|
|
|
936
|
|
|
8
|
|
|
|
|
|
|
use Graphics::Toolkit::Color::Space::Instance::Helper::OK |
|
9
|
16
|
|
|
16
|
|
7081
|
qw/toe toe_inv get_Cs oklab_to_linear_srgb linear_srgb_to_oklab/; |
|
|
16
|
|
|
|
|
31
|
|
|
|
16
|
|
|
|
|
9994
|
|
|
10
|
|
|
|
|
|
|
my $PI = 4 * atan2(1, 1); |
|
11
|
|
|
|
|
|
|
my $mid = 0.8; |
|
12
|
|
|
|
|
|
|
my $mid_inv = 1.25; |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub from_hsl { |
|
16
|
15
|
|
|
15
|
0
|
24
|
my ($hsl) = @_; |
|
17
|
15
|
100
|
|
|
|
35
|
return [0, 0, 0] if $hsl->[2] <= 0; # black |
|
18
|
14
|
50
|
|
|
|
48
|
return [1, 1, 1] if $hsl->[2] >= 1; # white |
|
19
|
|
|
|
|
|
|
|
|
20
|
14
|
|
|
|
|
46
|
my $L = toe_inv($hsl->[2]); |
|
21
|
14
|
|
|
|
|
50
|
my $a = cos(2 * $PI * $hsl->[0]); # Farbtonrichtung (Einheitsvektor) |
|
22
|
14
|
|
|
|
|
32
|
my $b = sin(2 * $PI * $hsl->[0]); |
|
23
|
14
|
|
|
|
|
32
|
my ($C_0, $C_mid, $C_max) = get_Cs($L, $a, $b); |
|
24
|
14
|
|
|
|
|
20
|
my $C; |
|
25
|
|
|
|
|
|
|
# Sattigung -> absolute Chroma (Vorwaerts-Interpolation, Inverse zum Hinweg) |
|
26
|
14
|
100
|
|
|
|
32
|
if ($hsl->[1] < $mid) { |
|
27
|
5
|
|
|
|
|
13
|
my $t = $hsl->[1] / $mid; |
|
28
|
5
|
|
|
|
|
6
|
my $k1 = $mid * $C_0; |
|
29
|
5
|
|
|
|
|
10
|
my $k2 = 1 - $k1 / $C_mid; |
|
30
|
5
|
|
|
|
|
6
|
my $den = 1 - $k2 * $t; |
|
31
|
5
|
50
|
33
|
|
|
13
|
$den = 1e-6 if $den < 1e-6 and $den >= 0; |
|
32
|
5
|
50
|
33
|
|
|
15
|
$den = -1e-6 if $den > -1e-6 and $den < 0; |
|
33
|
5
|
|
|
|
|
7
|
$C = $t * $k1 / $den; |
|
34
|
|
|
|
|
|
|
} |
|
35
|
|
|
|
|
|
|
else { |
|
36
|
9
|
|
|
|
|
19
|
my $t = ($hsl->[1] - $mid) / (1 - $mid); |
|
37
|
9
|
|
|
|
|
11
|
my $k0 = $C_mid; |
|
38
|
9
|
|
|
|
|
15
|
my $k1 = (1 - $mid) * $C_mid * $C_mid * $mid_inv * $mid_inv / $C_0; |
|
39
|
9
|
|
|
|
|
13
|
my $k2 = 1 - $k1 / ($C_max - $C_mid); |
|
40
|
9
|
|
|
|
|
12
|
my $den = 1 - $k2 * $t; |
|
41
|
9
|
50
|
33
|
|
|
16
|
$den = 1e-6 if $den < 1e-6 and $den >= 0; |
|
42
|
9
|
50
|
33
|
|
|
28
|
$den = -1e-6 if $den > -1e-6 and $den < 0; |
|
43
|
9
|
|
|
|
|
14
|
$C = $k0 + $t * $k1 / $den; |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
14
|
|
|
|
|
133
|
return oklab_to_linear_srgb([$L, $C * $a, $C * $b]); |
|
47
|
|
|
|
|
|
|
} |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub to_hsl { |
|
50
|
17
|
|
|
17
|
0
|
25
|
my ($rgb) = @_; # bereits LINEARES sRGB, Arrayref |
|
51
|
17
|
|
|
|
|
42
|
my $lab = linear_srgb_to_oklab($rgb); # roh, a/b um 0 zentriert |
|
52
|
17
|
|
|
|
|
52
|
my $C = spow($lab->[1]**2 + $lab->[2]**2, 1/2); # Chroma |
|
53
|
17
|
100
|
|
|
|
37
|
return [0, 0, toe($lab->[0])] if $C < 1e-9; # achromatisch: Hue undefiniert -> 0, keine Division durch 0 |
|
54
|
|
|
|
|
|
|
|
|
55
|
16
|
|
|
|
|
45
|
my $a = $lab->[1] / $C; # Farbtonrichtung (Einheitsvektor) |
|
56
|
16
|
|
|
|
|
21
|
my $b = $lab->[2] / $C; |
|
57
|
16
|
|
|
|
|
68
|
my $h = (0.5 + 0.5 * atan2(-$lab->[2], -$lab->[1]) / $PI);# Hue in Grad |
|
58
|
16
|
|
|
|
|
52
|
my ($C_0, $C_mid, $C_max) = get_Cs($lab->[0], $a, $b); |
|
59
|
16
|
|
|
|
|
21
|
my $s; |
|
60
|
16
|
100
|
|
|
|
24
|
if ($C < $C_mid) { |
|
61
|
2
|
|
|
|
|
4
|
my $k1 = $mid * $C_0; |
|
62
|
2
|
|
|
|
|
3
|
my $k2 = 1 - $k1 / $C_mid; |
|
63
|
2
|
|
|
|
|
3
|
my $t = $C / ($k1 + $k2 * $C); |
|
64
|
2
|
|
|
|
|
3
|
$s = $t * $mid; |
|
65
|
|
|
|
|
|
|
} |
|
66
|
|
|
|
|
|
|
else { |
|
67
|
14
|
|
|
|
|
18
|
my $k0 = $C_mid; |
|
68
|
14
|
|
|
|
|
25
|
my $k1 = (1 - $mid) * $C_mid * $C_mid * $mid_inv * $mid_inv / $C_0; |
|
69
|
14
|
|
|
|
|
18
|
my $k2 = 1 - $k1 / ($C_max - $C_mid); |
|
70
|
14
|
|
|
|
|
21
|
my $t = ($C - $k0) / ($k1 + $k2 * ($C - $k0)); |
|
71
|
14
|
|
|
|
|
19
|
$s = $mid + (1 - $mid) * $t; |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
|
|
74
|
16
|
|
|
|
|
34
|
return [$h, $s, toe($lab->[0])]; |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
Graphics::Toolkit::Color::Space->new( |
|
78
|
|
|
|
|
|
|
name => 'OKHSL', |
|
79
|
|
|
|
|
|
|
family => 'HSL', |
|
80
|
|
|
|
|
|
|
axis => [qw/hue saturation lightness/], |
|
81
|
|
|
|
|
|
|
type => [qw/angular linear linear/], |
|
82
|
|
|
|
|
|
|
range => [360, 1, 1], |
|
83
|
|
|
|
|
|
|
precision => 5, |
|
84
|
|
|
|
|
|
|
convert => {LinearRGB => [\&from_hsl, \&to_hsl]}, |
|
85
|
|
|
|
|
|
|
); |