File Coverage

blib/lib/Convert/Color/HSLuv.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::HSLuv;
2              
3 2     2   681 use 5.008009;
  2         4  
4 2     2   8 use strict;
  2         1  
  2         32  
5 2     2   6 use warnings;
  2         1  
  2         46  
6 2     2   7 use parent qw/Convert::Color/;
  2         1  
  2         15  
7              
8 2     2   710 use Convert::Color::XYZ;
  2         3  
  2         36  
9 2     2   639 use Convert::Color::LUV;
  2         4  
  2         37  
10 2     2   643 use Convert::Color::LCh;
  2         4  
  2         52  
11 2     2   12 use List::Util qw/min/;
  2         2  
  2         94  
12 2     2   7 use Math::Trig qw/:pi/;
  2         3  
  2         232  
13              
14             BEGIN {
15 2     2   5 *MAT_R = *Convert::Color::XYZ::MAT_R;
16 2         3 *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         991 *EPS = *Convert::Color::LUV::EPS;
21             }
22              
23             our $VERSION = '1.000001';
24              
25             __PACKAGE__->register_color_space('hsluv');
26              
27             sub new {
28 2049     2049 1 8941 my ($class, $h, $s, $l) = @_;
29 2049 100       2993 ($h, $s, $l) = split /,/s, $h unless defined $s;
30 2049         9017 bless [$h, $s, $l], $class
31             }
32              
33 1     1 1 13 sub H { shift->[0] }
34 1     1 1 5 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   2143 my ($l) = @_;
41 3060         4468 my $sub1 = ($l + 16) ** 3 / 1_560_896;
42 3060 100       3670 my $sub2 = $sub1 > EPS ? $sub1 : $l / KAPPA;
43 3060         2011 my @ret;
44              
45 3060         3104 for (MAT_R, MAT_G, MAT_B) {
46 9180         6958 my ($m1, $m2, $m3) = @$_;
47 9180         6898 for (0, 1) {
48 18360         14085 my $top1 = (284_517 * $m1 - 94_839 * $m3) * $sub2;
49 18360         16820 my $top2 = (838_422 * $m3 + 769_860 * $m2 + 731_718 * $m1) * $l * $sub2 - 769_860 * $_ * $l;
50 18360         14545 my $bottom = (632_260 * $m3 - 126_452 * $m2) * $sub2 + 126_452 * $_;
51 18360         23011 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   6061 my ($theta, $line) = @_;
60 9180         5988 my ($m, $n) = @$line;
61 9180         8033 my $len = $n / (sin ($theta) - $m * cos $theta);
62 9180 100       13027 return if $len < 0;
63 5043         6058 $len
64             }
65              
66             sub max_chroma_for_lh {
67 1530     1530 0 1240 my ($self, $l, $h) = @_;
68 1530         1396 my $hrad = $h / 180 * pi;
69             min map {
70 1530         1565 _length_of_ray_until_intersect $hrad, $_
  9180         7930  
71             } _get_bounds $l;
72             }
73              
74             sub convert_to_lch {
75 1024     1024 0 786 my ($self) = @_;
76 1024         927 my ($h, $s, $l) = @$self;
77 1024 100       1385 return Convert::Color::LCh->new(100, 0, $h) if $l > 99.9999999;
78 1022 100       1227 return Convert::Color::LCh->new(0, 0, $h) if $l < 0.00000001;
79 1020         1351 my $max = $self->max_chroma_for_lh($l, $h);
80 1020         1448 my $c = $max / 100 * $s;
81 1020         1739 Convert::Color::LCh->new($l, $c, $h)
82             }
83              
84             sub new_from_lch {
85 2048     2048 0 14873 my ($class, $lch) = @_;
86 2048         2078 my ($l, $c, $h) = @$lch;
87 2048 100       2964 return $class->new($h, 0, 100) if $l > 99.9999999;
88 2044 100       2482 return $class->new($h, 0, 0) if $l < 0.00000001;
89 2040         3265 my $max = $class->max_chroma_for_lh($l, $h);
90 2040         3125 my $s = $c / $max * 100;
91 2040         2626 $class->new($h, $s, $l)
92             }
93              
94 1024     1024 1 12264 sub rgb { shift->convert_to_lch->rgb }
95 2048     2048 0 478832 sub new_rgb { shift->new_from_lch(Convert::Color::LCh->new_rgb(@_)) }
96              
97             1;
98             __END__