File Coverage

blib/lib/Convert/Color/HUSL.pm
Criterion Covered Total %
statement 77 77 100.0
branch 14 14 100.0
condition n/a
subroutine 22 22 100.0
pod 6 10 60.0
total 119 123 96.7


line stmt bran cond sub pod time code
1             package Convert::Color::HUSL;
2              
3 2     2   36915 use 5.008009;
  2         6  
  2         66  
4 2     2   6 use strict;
  2         2  
  2         52  
5 2     2   15 use warnings;
  2         2  
  2         46  
6 2     2   865 use parent qw/Convert::Color/;
  2         490  
  2         10  
7              
8 2     2   797 use Convert::Color::XYZ;
  2         4  
  2         42  
9 2     2   715 use Convert::Color::LUV;
  2         3  
  2         48  
10 2     2   700 use Convert::Color::LCh;
  2         5  
  2         62  
11 2     2   18 use List::Util qw/min/;
  2         3  
  2         114  
12 2     2   9 use Math::Trig qw/:pi/;
  2         2  
  2         267  
13              
14             BEGIN {
15 2     2   6 *MAT_R = *Convert::Color::XYZ::MAT_R;
16 2         4 *MAT_G = *Convert::Color::XYZ::MAT_G;
17 2         2 *MAT_B = *Convert::Color::XYZ::MAT_B;
18              
19 2         2 *KAPPA = *Convert::Color::LUV::KAPPA;
20 2         1124 *EPS = *Convert::Color::LUV::EPS;
21             }
22              
23             our $VERSION = '0.002001';
24              
25             __PACKAGE__->register_color_space('husl');
26              
27             sub new {
28 2049     2049 1 8026 my ($class, $h, $s, $l) = @_;
29 2049 100       3358 ($h, $s, $l) = split /,/s, $h unless defined $s;
30 2049         10747 bless [$h, $s, $l], $class
31             }
32              
33 1     1 1 19 sub H { shift->[0] }
34 1     1 1 6 sub S { shift->[1] }
35 1     1 1 7 sub L { shift->[2] }
36              
37 1     1 1 2 sub hsl { @{$_[0]} }
  1         11  
38              
39             sub _get_bounds {
40 3060     3060   2594 my ($l) = @_;
41 3060         5448 my $sub1 = ($l + 16) ** 3 / 1_560_896;
42 3060 100       4239 my $sub2 = $sub1 > EPS ? $sub1 : $l / KAPPA;
43 3060         2372 my @ret;
44              
45 3060         3956 for (MAT_R, MAT_G, MAT_B) {
46 9180         9737 my ($m1, $m2, $m3) = @$_;
47 9180         8517 for (0, 1) {
48 18360         17049 my $top1 = (284_517 * $m1 - 94_839 * $m3) * $sub2;
49 18360         21795 my $top2 = (838_422 * $m3 + 769_860 * $m2 + 731_718 * $m1) * $l * $sub2 - 769_860 * $_ * $l;
50 18360         19231 my $bottom = (632_260 * $m3 - 126_452 * $m2) * $sub2 + 126_452 * $_;
51 18360         33599 push @ret, [$top1 / $bottom, $top2 / $bottom]
52             }
53             }
54              
55             @ret
56 3060         7390 }
57              
58             sub _length_of_ray_until_intersect {
59 9180     9180   7538 my ($theta, $line) = @_;
60 9180         8048 my ($m, $n) = @$line;
61 9180         11089 my $len = $n / (sin ($theta) - $m * cos $theta);
62 9180 100       15570 return if $len < 0;
63 5043         7207 $len
64             }
65              
66             sub max_chroma_for_lh {
67 1530     1530 0 1553 my ($self, $l, $h) = @_;
68 1530         1834 my $hrad = $h / 180 * pi;
69 9180         10038 min map {
70 1530         2120 _length_of_ray_until_intersect $hrad, $_
71             } _get_bounds $l;
72             }
73              
74             sub convert_to_lch {
75 1024     1024 0 866 my ($self) = @_;
76 1024         1188 my ($h, $s, $l) = @$self;
77 1024 100       1657 return Convert::Color::LCh->new(100, 0, $h) if $l > 99.9999999;
78 1022 100       1486 return Convert::Color::LCh->new(0, 0, $h) if $l < 0.00000001;
79 1020         2422 my $max = $self->max_chroma_for_lh($l, $h);
80 1020         2011 my $c = $max / 100 * $s;
81 1020         2335 Convert::Color::LCh->new($l, $c, $h)
82             }
83              
84             sub new_from_lch {
85 2048     2048 0 1981 my ($class, $lch) = @_;
86 2048         2158 my ($l, $c, $h) = @$lch;
87 2048 100       3470 return $class->new($h, 0, 100) if $l > 99.9999999;
88 2044 100       2984 return $class->new($h, 0, 0) if $l < 0.00000001;
89 2040         4092 my $max = $class->max_chroma_for_lh($l, $h);
90 2040         4134 my $s = $c / $max * 100;
91 2040         3388 $class->new($h, $s, $l)
92             }
93              
94 1024     1024 1 1707 sub rgb { shift->convert_to_lch->rgb }
95 2048     2048 0 592652 sub new_rgb { shift->new_from_lch(Convert::Color::LCh->new_rgb(@_)) }
96              
97             1;
98             __END__