File Coverage

blib/lib/Graphics/ColorDeficiency.pm
Criterion Covered Total %
statement 68 71 95.7
branch 14 14 100.0
condition 3 3 100.0
subroutine 14 15 93.3
pod 10 13 76.9
total 109 116 93.9


line stmt bran cond sub pod time code
1             package Graphics::ColorDeficiency;
2              
3 4     4   10809 use Graphics::ColorObject;
  4         350842  
  4         256  
4 4     4   11960 use Graphics::ColorDeficiency::Data;
  4         46  
  4         4589  
5              
6             @ISA = ('Graphics::ColorObject');
7             $VERSION = 0.05;
8              
9             sub Clone {
10 0     0 1 0 my ($self) = @_;
11 0         0 my ($r,$g,$b) = $self->asRGB;
12 0         0 return Graphics::ColorDeficiency->newRGB($r, $g, $b);
13             }
14              
15             sub asProtanomaly {
16 3     3 1 3216 my ($self, $ratio) = @_;
17 3 100       12 $ratio = 0.5 unless defined $ratio;
18 3         10 my $temp = $self->asProtanopia;
19 3         581 return $self->asMix($temp, $ratio);
20             }
21              
22             sub asDeuteranomaly {
23 3     3 1 3755 my ($self, $ratio) = @_;
24 3 100       12 $ratio = 0.5 unless defined $ratio;
25 3         10 my $temp = $self->asDeutanopia;
26 3         492 return $self->asMix($temp, $ratio);
27             }
28              
29             sub asTritanomaly {
30 3     3 1 3176 my ($self, $ratio) = @_;
31 3 100       12 $ratio = 0.5 unless defined $ratio;
32 3         8 my $temp = $self->asTritanopia;
33 3         522 return $self->asMix($temp, $ratio);
34             }
35              
36             sub asProtanopia {
37 4     4 1 814 return shift->asHash(0);
38             }
39              
40             sub asDeutanopia {
41 4     4 1 1379 return shift->asHash(1);
42             }
43              
44             sub asTritanopia {
45 4     4 1 1390 return shift->asHash(2);
46             }
47              
48             sub asTypicalMonochrome {
49 5     5 1 860 my ($self) = @_;
50 5         31 my $val = $self->asGrey2;
51 5         972 my ($h1, $s1, $v1) = $self->asHSV;
52 5         824 my $temp = Graphics::ColorObject->newRGB($val, $val, $val);
53 5         4271 my ($h2, $s2, $v2) = $temp->asHSV;
54 5         840 $temp->setHSV($h2, $s2, ($v1+$v2)/2);
55 5         1134 return $temp;
56             }
57              
58             sub asAtypicalMonochrome {
59 4     4 1 5116 my ($self, $ratio) = @_;
60 4 100       17 $ratio = 0.2 unless defined $ratio;
61 4         9 my $temp = $self->asTypicalMonochrome;
62 4         18 return $self->asMix($temp, 1 - $ratio);
63             }
64              
65             sub asHash {
66 12     12 0 23 my ($self, $id) = @_;
67              
68 12         48 my ($r, $g, $b) = $self->asRGB();
69              
70 12         1631 my ($lo_r, $hi_r) = $self->getColorBounds($r);
71 12         35 my ($lo_r_rat, $hi_r_rat) = $self->getMixRatios($r, $hi_r, $lo_r);
72              
73 12         27 my ($lo_g, $hi_g) = $self->getColorBounds($g);
74 12         32 my ($lo_g_rat, $hi_g_rat) = $self->getMixRatios($g, $hi_g, $lo_g);
75              
76 12         26 my ($lo_b, $hi_b) = $self->getColorBounds($b);
77 12         27 my ($lo_b_rat, $hi_b_rat) = $self->getMixRatios($b, $hi_b, $lo_b);
78              
79 12         52 my $lo_col = Graphics::ColorObject->newRGB($lo_r, $lo_g, $lo_b);
80 12         2094 my $hi_col = Graphics::ColorObject->newRGB($hi_r, $hi_g, $hi_b);
81              
82 12         1960 my $from_lo = $Graphics::ColorDeficiency::Data::HASH->{substr(lc $lo_col->asHex,1)}[$id];
83 12         1730 my $from_hi = $Graphics::ColorDeficiency::Data::HASH->{substr(lc $hi_col->asHex,1)}[$id];
84              
85 12         1650 my ($f_l_r, $f_l_g, $f_l_b) = map{hex($_) / 255} ($from_lo =~ /../g);
  36         80  
86 12         53 my ($f_h_r, $f_h_g, $f_h_b) = map{hex($_) / 255} ($from_hi =~ /../g);
  36         62  
87              
88 12         33 my $r_out = ($f_l_r * $lo_r_rat) + ($f_h_r * $hi_r_rat);
89 12         23 my $g_out = ($f_l_g * $lo_g_rat) + ($f_h_g * $hi_g_rat);
90 12         20 my $b_out = ($f_l_b * $lo_b_rat) + ($f_h_b * $hi_b_rat);
91              
92 12         45 return Graphics::ColorObject->newRGB($r_out, $g_out, $b_out);
93             }
94              
95             sub asMix {
96 13     13 1 24 my ($self, $mix, $rat2) = @_;
97 13         22 my $rat1 = 1 - $rat2;
98 13         45 my ($r1, $g1, $b1) = $self->asRGB();
99 13         1673 my ($r2, $g2, $b2) = $mix->asRGB();
100 13         1651 return Graphics::ColorDeficiency->newRGB( ($r1*$rat1)+($r2*$rat2), ($g1*$rat1)+($g2*$rat2), ($b1*$rat1)+($b2*$rat2) );
101             }
102              
103             sub getColorBounds {
104 36     36 0 51 my ($self, $val) = @_;
105 36         43 $val *= 10;
106 36         52 my ($lo, $hi) = (0, 10);
107 36         91 for(my $i=0; $i<=10; $i+=2){
108 216 100       386 $lo = $i if $val >= $i;
109 216 100 100     780 $hi = $i if $val <= $i && $i < $hi;
110             }
111 36         83 return ($lo/10, $hi/10);
112             }
113              
114             sub getMixRatios {
115 36     36 0 72 my ($self, $val, $hi, $lo) = @_;
116              
117 36 100       98 return (0.5, 0.5) if ($hi == $val);
118              
119 12         20 $r1 = ($val - $lo) / 0x33;
120 12         26 return ($r1, 1-$r1);
121             }
122              
123             =head1 NAME
124              
125             Graphics::ColorDeficiency - Color Deficiency Simulation
126              
127             =head1 SYNOPSIS
128              
129             use Graphics::ColorDeficiency;
130              
131             my $col = Graphics::ColorDeficiency->newRGB(0.5, 0.7, 1);
132              
133             my $col2 = $col->asProtanopia;
134              
135             print $col2->asHex;
136              
137             =head1 DESCRIPTION
138              
139             This module allows easy transformation of colors for color deficiency
140             simulation. All the known and theorhetical color deficiencies are
141             represented here, with the exception of 4-cone vision (tetrachromatism).
142              
143             Each of the transformation methods returns a C object,
144             with the internal color values set. This can then be used to return the
145             color in many different formats (see the C manpage).
146              
147             =head1 METHODS
148              
149             =over 4
150              
151             =item C
152              
153             =item C
154              
155             =item C
156              
157             The three dichromat methods return a C object,
158             simulated for the three dichromatic vision modes.
159              
160             =item C
161              
162             =item C
163              
164             =item C
165              
166             The three anomalous trichromat methods return a C object,
167             simulated for the three anomalous trichromatic vision modes. The optional
168             C<$amount> agrument allows you to specify the severity of anomaly, ranging
169             from 0 (trichromatic) to 1 (dichromatic). If not specified, it defaults to
170             0.5.
171              
172             =item C
173              
174             Returns a C object in Typical Monochromatic (Rod
175             Monochromat) mode.
176              
177             =item C
178              
179             Returns a C object in Atypical Monochromatic (Cone
180             Monochromat) mode. The amount specified in C<$amount> can vary between 1
181             (trichromatic) and 0 (monochromatic). The default is 0.2 (four fifths gray).
182              
183             =item C
184              
185             Clones the current object, returning a C object
186             with the same color values as the current object.
187              
188             =item C
189              
190             Returns a new C, consisting of the current color
191             values, mixed with the values of the C<$color> object. C<$amount> specifies
192             the amount of the new color to mix in, from 0 (which is equal to
193             C<$self.Clone()>), up to 1 (which is equal to C<$color.Clone()>). The mix
194             is a linear RGB interpolation.
195              
196             This method is used internally.
197              
198             =back
199              
200             =head1 AUTHOR
201              
202             Copyright (C) 2003 Cal Henderson
203              
204             =head1 SEE ALSO
205              
206             L
207              
208             L
209              
210             =cut