File Coverage

lib/Graphics/Toolkit/Color/Calculator.pm
Criterion Covered Total %
statement 90 120 75.0
branch 53 74 71.6
condition 11 18 61.1
subroutine 9 24 37.5
pod 0 19 0.0
total 163 255 63.9


line stmt bran cond sub pod time code
1              
2             # methods to compute one related color
3              
4             package Graphics::Toolkit::Color::Calculator;
5 7     7   213305 use v5.12;
  7         20  
6 7     7   27 use warnings;
  7         10  
  7         367  
7 7     7   451 use Graphics::Toolkit::Color::Space::Util qw/is_nr spow/;
  7         11  
  7         466  
8 7     7   2530 use Graphics::Toolkit::Color::Values;
  7         18  
  7         10341  
9              
10             sub apply_gamma {
11 9     9 0 1494 my ($color_values, $gamma, $color_space) = @_;
12 9         33 my $gamma_array = '';
13 9 50       18 return "need a color space as third argument" if ref $color_space ne 'Graphics::Toolkit::Color::Space';
14 9 100       20 if (ref $gamma eq 'HASH'){
15 3         10 ($gamma_array, my $deduced_space_name) =
16             Graphics::Toolkit::Color::Space::Hub::deformat_search_partial_hash( $gamma, $color_space->name );
17 3 100       11 return 'axis names: '.join(', ', keys %$gamma).' do not correlate to the selected color space: '.
18             ($color_space->name).'!' unless ref $gamma_array;
19             }
20 8 100       15 $gamma_array = [ ($gamma) x $color_space->axis_count] if is_nr( $gamma );
21 8 50 33     16 $gamma_array = $gamma if not defined $gamma_array and ref $gamma eq 'ARRAY';
22 8 50       21 return 'got badly formatted gamma value' if ref $gamma_array ne 'ARRAY';
23            
24 8         16 my $tuple = $color_values->normalized( $color_space->name );
25 8         22 for my $axis_nr ($color_space->basis->axis_iterator){
26 24 100       44 $tuple->[$axis_nr] = spow($tuple->[$axis_nr], $gamma_array->[$axis_nr]) if exists $gamma_array->[$axis_nr];
27             }
28 8         15 return $color_values->new_from_tuple( $tuple, $color_space->name, 'normal' );
29             }
30              
31             sub set_value { # .values, %newval -- ~space_name --> _
32 13     13 0 2084 my ($color_values, $partial_hash, $preselected_space_name) = @_;
33 13         36 my ($new_values, $deduced_space_name) =
34             Graphics::Toolkit::Color::Space::Hub::deformat_search_partial_hash( $partial_hash, $preselected_space_name );
35 13 100       23 unless (ref $new_values){
36 4         17 my $help_start = 'axis names: '.join(', ', keys %$partial_hash).' do not correlate to ';
37 4 100       18 return (defined $preselected_space_name) ? $help_start.'the selected color space: '.$preselected_space_name.'!'
38             : $help_start.'any supported color space!';
39             }
40 9         29 my $tuple = $color_values->shaped( $deduced_space_name );
41 9         19 my $color_space = Graphics::Toolkit::Color::Space::Hub::get_space( $deduced_space_name );
42 9         17 for my $pos ($color_space->basis->axis_iterator) {
43 27 100       49 $tuple->[$pos] = $new_values->[$pos] if defined $new_values->[$pos];
44             }
45 9         18 return $color_values->new_from_tuple( $tuple, $color_space->name );
46             }
47              
48             sub add_value { # .values, %newval -- ~space_name --> _
49 13     13 0 1732 my ($color_values, $partial_hash, $preselected_space_name) = @_;
50 13         39 my ($new_values, $deduced_space_name) =
51             Graphics::Toolkit::Color::Space::Hub::deformat_search_partial_hash( $partial_hash, $preselected_space_name );
52 13 100       37 unless (ref $new_values){
53 5         17 my $help_start = 'axis names: '.join(', ', keys %$partial_hash).' do not correlate to ';
54 5 100       24 return (defined $preselected_space_name) ? $help_start.'the selected color space: '.$preselected_space_name.'!'
55             : $help_start.'any supported color space!';
56             }
57 8         28 my $tuple = $color_values->shaped( $deduced_space_name );
58 8         18 my $color_space = Graphics::Toolkit::Color::Space::Hub::get_space( $deduced_space_name );
59 8         16 for my $pos ($color_space->basis->axis_iterator) {
60 24 100       45 $tuple->[$pos] += $new_values->[$pos] if defined $new_values->[$pos];
61             }
62 8         31 return $color_values->new_from_tuple( $tuple, $color_space->name );
63             }
64              
65              
66             sub derive {
67 0     0 0 0 my ($color_values, $mult, $add, $set, $raw, $space_name) = @_;
68             }
69              
70              
71             #### light designer API ################################################
72             sub _clear_values_amount_space_name {
73 0     0   0 my ($color_values, $amount, $space_name, @more) = @_;
74 0 0       0 return "need a G::T::Color::Values object as first argument"
75             unless ref $color_values eq 'Graphics::Toolkit::Color::Values';
76 0 0       0 return "need a numeric amount between 0 and 1 as first argument" unless defined $amount;
77 0         0 my $color_space = Graphics::Toolkit::Color::Space::Hub::try_get_space( $space_name );
78 0 0       0 return "$space_name is not a known color space" unless ref $color_space;
79 0         0 return ($color_values, $amount, $color_space, @more);
80             }
81              
82 0     0 0 0 sub lighten { add_axis_value( @_, 'lightness') }
83             sub darken {
84 0     0 0 0 my ($color_values, $amount, $color_space) = @_;
85 0         0 add_axis_value($color_values, -$amount, $color_space, 'lightness');
86             }
87 0     0 0 0 sub saturate { add_axis_value( @_, 'saturation') }
88             sub desaturate {
89 0     0 0 0 my ($color_values, $amount, $color_space) = @_;
90 0         0 add_axis_value($color_values, -$amount, $color_space, 'saturation');
91             }
92             sub add_axis_value {
93 0     0 0 0 my ($color_values, $amount, $color_space, $axis_name) = _clear_values_amount_space_name(@_);
94 0 0       0 return $color_values unless ref $color_values;
95 0         0 my $axis_nr = $color_space->pos_from_axis_role( $axis_name );
96 0 0       0 return "color space: '".$color_space->name."' has no $axis_name axis" unless defined $axis_nr;
97 0         0 my $tuple = $color_values->normalized( $color_space->name );
98 0         0 $tuple->[$axis_nr] += $amount;
99 0         0 return $color_values->new_from_tuple( $tuple, $color_space->name, 'normal' );
100             }
101              
102 0     0 0 0 sub tint { mix_with(@_, [255 ,255 ,255 ]) } # white
103 0     0 0 0 sub tone { mix_with(@_, [127.5,127.5,127.5]) } # grey50
104 0     0 0 0 sub shade { mix_with(@_, [ 0, 0, 0 ]) } # black
105             sub mix_with {
106 0     0 0 0 my ($color_values, $amount, $color_space, $tuple) = _clear_values_amount_space_name(@_);
107 0 0       0 return $color_values unless ref $color_values;
108 0         0 return mix( $color_values, [Graphics::Toolkit::Color::Values->new_from_tuple( $tuple )], $amount, $color_space);
109             }
110              
111             sub brightness {
112 0     0 0 0 my ($color_values, $mult, $add, $set, $space_name) = @_;
113              
114             }
115              
116             sub saturation {
117 0     0 0 0 my ($color_values, $mult, $add, $set, $space_name) = @_;
118              
119             }
120              
121             sub contrast {
122 0     0 0 0 my ($color_values, $mult, $add, $set, $space_name) = @_;
123              
124             }
125              
126             sub vibrance {
127 0     0 0 0 my ($color_values, $mult, $add, $set, $space_name) = @_;
128              
129             }
130              
131             #### deep designer methods #############################################
132             sub mix { # .base_color_vals, @.added_volor_vals, @+|+add_amount, .space --> .color_values
133 79     79 0 418 my ($base_color, $added_color, $add_amount, $color_space ) = @_;
134 79 50       178 return "need color value object as first argument !\n" unless ref $base_color eq 'Graphics::Toolkit::Color::Values';
135 79 50       139 return "second argument has to be an ARRAY !\n" unless ref $added_color eq 'ARRAY';
136 79 50       147 return "need a color space object !\n" unless ref $color_space eq 'Graphics::Toolkit::Color::Space';
137              
138 79         102 my $color_count = @$added_color + 1;
139 79 100       138 $add_amount = 1 / $color_count unless defined $add_amount;
140 79 100       222 $add_amount = [($add_amount) x ($color_count - 1)] unless ref $add_amount eq 'ARRAY';
141 79 100       142 return "ARRAY of mix amounts needs a value for every color !\n" unless @$add_amount == $color_count - 1;
142 77         86 my $mix_sum = 0;
143 77         187 $mix_sum += $_ for @$add_amount;
144 77 100       125 if ($mix_sum > 1){
145 4         11 for my $reciepe_index (0 .. $#$add_amount){
146 7         13 $add_amount->[$reciepe_index] = $add_amount->[$reciepe_index] / $mix_sum;
147             }
148             } else {
149 73         167 push @$add_amount, 1 - $mix_sum;
150 73         99 push @$added_color, $base_color;
151             }
152            
153 77         207 my $result_values = [(0) x $color_space->axis_count];
154 77         171 for my $color_nr (0 .. $#$added_color){
155 158         311 my $tuple = $added_color->[$color_nr]->shaped( $color_space->name );
156 158         781 $result_values->[$_] += $tuple->[$_] * $add_amount->[$color_nr] for 0 .. $#$tuple;
157             }
158 77         158 return $base_color->new_from_tuple( $result_values, $color_space->name );
159             }
160              
161             sub invert {
162 25     25 0 354 my ($color_values, $only, $color_space, $default_color_space ) = @_;
163 25 100 100     91 $only = [$only] if defined $only and not ref $only; # selected axes
164 25 50 66     75 return "need argument only as axis name (short or long) or as ARRAY of names!"
165             if defined $only and ref $only ne 'ARRAY';
166 25 100       52 if (defined $only){
167 9         22 my %partial_hash = map { $_ => 1 } @$only;
  12         38  
168 9 100       35 my $preselected_space_name = defined($color_space) ? $color_space->name : undef;
169 9         30 my ($new_values, $deduced_space_name) =
170             Graphics::Toolkit::Color::Space::Hub::deformat_search_partial_hash( \%partial_hash, $preselected_space_name );
171 9 50 66     28 return "could not find any color space that contains the axes: ". join(', ', @$only).' !'
172             if not defined $deduced_space_name and not defined $color_space;
173 8 50 33     22 return "axes ". join(', ', @$only) . 'do not match color space '.$color_space->name.' !'
174             if not defined $deduced_space_name and ref $color_space;
175 8         13 $color_space = Graphics::Toolkit::Color::Space::Hub::get_space( $deduced_space_name );
176             }
177 24   66     50 $color_space //= $default_color_space;
178            
179 24 100       61 my $selected_axis = (defined $only) ? [ ] : [$color_space->basis->axis_iterator];
180 24 100       43 if (defined $only) {
181 8         14 for my $axis_name (@$only){
182 11         38 my $pos = $color_space->pos_from_axis_role( $axis_name );
183 11         19 $selected_axis->[$pos] = $pos;
184             }
185             }
186 24         47 my $tuple = $color_values->normalized( $color_space->name );
187 24         56 for my $axis_nr ($color_space->basis->axis_iterator){
188 72 100       102 next unless defined $selected_axis->[$axis_nr];
189 59 100       84 if ($color_space->shape->is_axis_euclidean( $axis_nr )){
190 50         89 $tuple->[$axis_nr] = 0.5 - ($tuple->[$axis_nr] - 0.5);
191             } else {
192 9         21 $tuple->[$axis_nr]++ while $tuple->[$axis_nr] < 0;
193 9         20 $tuple->[$axis_nr]-- while $tuple->[$axis_nr] > 1;
194 9 100       27 $tuple->[$axis_nr] = ($tuple->[$axis_nr] < 0.5)
195             ? $tuple->[$axis_nr] + 0.5
196             : $tuple->[$axis_nr] - 0.5;
197             }
198             }
199 24         49 return $color_values->new_from_tuple( $tuple, $color_space->name, 'normal' );
200             }
201            
202             1;