File Coverage

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


line stmt bran cond sub pod time code
1             package Convert::Color::HUSL;
2              
3 2     2   25226 use 5.008009;
  2         5  
4 2     2   6 use strict;
  2         2  
  2         26  
5 2     2   12 use warnings;
  2         2  
  2         39  
6 2     2   815 use parent qw/Convert::Color/;
  2         428  
  2         8  
7              
8 2     2   742 use Convert::Color::XYZ;
  2         2  
  2         36  
9 2     2   674 use Convert::Color::LUV;
  2         4  
  2         37  
10 2     2   654 use Convert::Color::LCh;
  2         3  
  2         43  
11 2     2   9 use List::Util qw/min/;
  2         1  
  2         85  
12 2     2   7 use Math::Trig qw/:pi/;
  2         2  
  2         228  
13              
14             BEGIN {
15 2     2   6 *MAT_R = *Convert::Color::XYZ::MAT_R;
16 2         2 *MAT_G = *Convert::Color::XYZ::MAT_G;
17 2         3 *MAT_B = *Convert::Color::XYZ::MAT_B;
18              
19 2         1 *KAPPA = *Convert::Color::LUV::KAPPA;
20 2         953 *EPS = *Convert::Color::LUV::EPS;
21             }
22              
23             our $VERSION = '1.000';
24              
25             __PACKAGE__->register_color_space('husl');
26              
27             sub new {
28 2049     2049 1 6252 my ($class, $h, $s, $l) = @_;
29 2049 100       2732 ($h, $s, $l) = split /,/s, $h unless defined $s;
30 2049         8070 bless [$h, $s, $l], $class
31             }
32              
33 1     1 1 9 sub H { shift->[0] }
34 1     1 1 17 sub S { shift->[1] }
35 1     1 1 5 sub L { shift->[2] }
36              
37 1     1 1 2 sub hsl { @{$_[0]} }
  1         8  
38              
39             sub _get_bounds {
40 3060     3060   2367 my ($l) = @_;
41 3060         3727 my $sub1 = ($l + 16) ** 3 / 1_560_896;
42 3060 100       3502 my $sub2 = $sub1 > EPS ? $sub1 : $l / KAPPA;
43 3060         2472 my @ret;
44              
45 3060         3610 for (MAT_R, MAT_G, MAT_B) {
46 9180         8672 my ($m1, $m2, $m3) = @$_;
47 9180         7763 for (0, 1) {
48 18360         13922 my $top1 = (284_517 * $m1 - 94_839 * $m3) * $sub2;
49 18360         18388 my $top2 = (838_422 * $m3 + 769_860 * $m2 + 731_718 * $m1) * $l * $sub2 - 769_860 * $_ * $l;
50 18360         14547 my $bottom = (632_260 * $m3 - 126_452 * $m2) * $sub2 + 126_452 * $_;
51 18360         23907 push @ret, [$top1 / $bottom, $top2 / $bottom]
52             }
53             }
54              
55             @ret
56 3060         5426 }
57              
58             sub _length_of_ray_until_intersect {
59 9180     9180   6130 my ($theta, $line) = @_;
60 9180         6401 my ($m, $n) = @$line;
61 9180         8475 my $len = $n / (sin ($theta) - $m * cos $theta);
62 9180 100       13119 return if $len < 0;
63 5043         5570 $len
64             }
65              
66             sub max_chroma_for_lh {
67 1530     1530 0 1215 my ($self, $l, $h) = @_;
68 1530         1196 my $hrad = $h / 180 * pi;
69             min map {
70 1530         1644 _length_of_ray_until_intersect $hrad, $_
  9180         7794  
71             } _get_bounds $l;
72             }
73              
74             sub convert_to_lch {
75 1024     1024 0 842 my ($self) = @_;
76 1024         824 my ($h, $s, $l) = @$self;
77 1024 100       1409 return Convert::Color::LCh->new(100, 0, $h) if $l > 99.9999999;
78 1022 100       1252 return Convert::Color::LCh->new(0, 0, $h) if $l < 0.00000001;
79 1020         1496 my $max = $self->max_chroma_for_lh($l, $h);
80 1020         1827 my $c = $max / 100 * $s;
81 1020         1810 Convert::Color::LCh->new($l, $c, $h)
82             }
83              
84             sub new_from_lch {
85 2048     2048 0 1639 my ($class, $lch) = @_;
86 2048         1636 my ($l, $c, $h) = @$lch;
87 2048 100       2581 return $class->new($h, 0, 100) if $l > 99.9999999;
88 2044 100       2540 return $class->new($h, 0, 0) if $l < 0.00000001;
89 2040         3195 my $max = $class->max_chroma_for_lh($l, $h);
90 2040         3398 my $s = $c / $max * 100;
91 2040         2806 $class->new($h, $s, $l)
92             }
93              
94 1024     1024 1 1186 sub rgb { shift->convert_to_lch->rgb }
95 2048     2048 0 570132 sub new_rgb { shift->new_from_lch(Convert::Color::LCh->new_rgb(@_)) }
96              
97             1;
98             __END__