File Coverage

blib/lib/Convert/Color/HUSL.pm
Criterion Covered Total %
statement 64 77 83.1
branch 9 14 64.2
condition n/a
subroutine 16 22 72.7
pod 6 10 60.0
total 95 123 77.2


line stmt bran cond sub pod time code
1             package Convert::Color::HUSL;
2              
3 1     1   5886 use 5.008009;
  1         5  
  1         32  
4 1     1   4 use strict;
  1         1  
  1         22  
5 1     1   10 use warnings;
  1         1  
  1         25  
6 1     1   399 use parent qw/Convert::Color/;
  1         275  
  1         6  
7              
8 1     1   480 use Convert::Color::XYZ;
  1         3  
  1         20  
9 1     1   340 use Convert::Color::LUV;
  1         2  
  1         21  
10 1     1   348 use Convert::Color::LCh;
  1         2  
  1         28  
11 1     1   7 use List::Util qw/min/;
  1         1  
  1         53  
12 1     1   3 use Math::Trig qw/:pi/;
  1         2  
  1         127  
13              
14             BEGIN {
15 1     1   3 *MAT_R = *Convert::Color::XYZ::MAT_R;
16 1         2 *MAT_G = *Convert::Color::XYZ::MAT_G;
17 1         1 *MAT_B = *Convert::Color::XYZ::MAT_B;
18              
19 1         1 *KAPPA = *Convert::Color::LUV::KAPPA;
20 1         531 *EPS = *Convert::Color::LUV::EPS;
21             }
22              
23             our $VERSION = '0.002';
24              
25             __PACKAGE__->register_color_space('husl');
26              
27             sub new {
28 8192     8192 1 8406 my ($class, $h, $s, $l) = @_;
29 8192 50       14308 ($h, $s, $l) = split /,/s, $h unless defined $s;
30 8192         49932 bless [$h, $s, $l], $class
31             }
32              
33 0     0 1 0 sub H { shift->[0] }
34 0     0 1 0 sub S { shift->[1] }
35 0     0 1 0 sub L { shift->[2] }
36              
37 0     0 1 0 sub hsl { @{$_[0]} }
  0         0  
38              
39             sub _get_bounds {
40 8188     8188   7136 my ($l) = @_;
41 8188         14154 my $sub1 = ($l + 16) ** 3 / 1_560_896;
42 8188 100       11206 my $sub2 = $sub1 > EPS ? $sub1 : $l / KAPPA;
43 8188         6355 my @ret;
44              
45 8188         11973 for (MAT_R, MAT_G, MAT_B) {
46 24564         24193 my ($m1, $m2, $m3) = @$_;
47 24564         21687 for (0, 1) {
48 49128         46755 my $top1 = (284_517 * $m1 - 94_839 * $m3) * $sub2;
49 49128         62852 my $top2 = (838_422 * $m3 + 769_860 * $m2 + 731_718 * $m1) * $l * $sub2 - 769_860 * $_ * $l;
50 49128         47542 my $bottom = (632_260 * $m3 - 126_452 * $m2) * $sub2 + 126_452 * $_;
51 49128         94913 push @ret, [$top1 / $bottom, $top2 / $bottom]
52             }
53             }
54              
55             @ret
56 8188         21987 }
57              
58             sub _length_of_ray_until_intersect {
59 24564     24564   19785 my ($theta, $line) = @_;
60 24564         20300 my ($m, $n) = @$line;
61 24564         30885 my $len = $n / (sin ($theta) - $m * cos $theta);
62 24564 100       41582 return if $len < 0;
63 13441         19871 $len
64             }
65              
66             sub max_chroma_for_lh {
67 4094     4094 0 4470 my ($self, $l, $h) = @_;
68 4094         4438 my $hrad = $h / 180 * pi;
69 24564         26916 min map {
70 4094         5534 _length_of_ray_until_intersect $hrad, $_
71             } _get_bounds $l;
72             }
73              
74             sub convert_to_lch {
75 0     0 0 0 my ($self) = @_;
76 0         0 my ($h, $s, $l) = @$self;
77 0 0       0 return Convert::Color::LCh->new(100, 0, $h) if $l > 99.9999999;
78 0 0       0 return Convert::Color::LCh->new(0, 0, $h) if $l < 0.00000001;
79 0         0 my $max = $self->max_chroma_for_lh($l, $h);
80 0         0 my $c = $max / 100 * $s;
81 0         0 Convert::Color::LCh->new($l, $c, $h)
82             }
83              
84             sub new_from_lch {
85 8192     8192 0 9348 my ($class, $lch) = @_;
86 8192         8920 my ($l, $c, $h) = @$lch;
87 8192 100       13477 return $class->new($h, 0, 100) if $l > 99.9999999;
88 8190 100       11904 return $class->new($h, 0, 0) if $l < 0.00000001;
89 8188         16145 my $max = $class->max_chroma_for_lh($l, $h);
90 8188         16478 my $s = $c / $max * 100;
91 8188         14323 $class->new($h, $s, $l)
92             }
93              
94 0     0 1 0 sub rgb { shift->convert_to_lch->rgb }
95 8192     8192 0 2749257 sub new_rgb { shift->new_from_lch(Convert::Color::LCh->new_rgb(@_)) }
96              
97             1;
98             __END__