File Coverage

blib/lib/ICC/Profile/clrt.pm
Criterion Covered Total %
statement 23 79 29.1
branch 4 28 14.2
condition 0 21 0.0
subroutine 6 12 50.0
pod 1 6 16.6
total 34 146 23.2


line stmt bran cond sub pod time code
1             package ICC::Profile::clrt;
2              
3 2     2   79274 use strict;
  2         10  
  2         47  
4 2     2   8 use Carp;
  2         3  
  2         119  
5              
6             our $VERSION = 0.12;
7              
8             # revised 2018-08-07
9             #
10             # Copyright © 2004-2020 by William B. Birkett
11              
12             # inherit from Shared
13 2     2   358 use parent qw(ICC::Shared);
  2         232  
  2         9  
14              
15             # create new clrt tag object
16             # parameters: ([ref_to_A2B1_tag, [ref_to_array_of_colorant_names]])
17             # returns: (ref_to_object)
18             sub new {
19              
20             # get object class
21 1     1 0 860 my $class = shift();
22            
23             # create empty clrt object
24 1         3 my $self = [
25             {}, # object header
26             [] # colorant array
27             ];
28              
29             # if parameter supplied
30 1 50       4 if (@_) {
31            
32             # new colorant tag from xCLR A2B1 tag
33 0         0 _newICCclrt($self, @_);
34            
35             }
36              
37             # bless object
38 1         3 bless($self, $class);
39            
40             # return object reference
41 1         2 return($self);
42              
43             }
44              
45             # create clrt tag object from ICC profile
46             # parameters: (ref_to_parent_object, file_handle, ref_to_tag_table_entry)
47             # returns: (ref_to_object)
48             sub new_fh {
49              
50             # get object class
51 0     0 0 0 my $class = shift();
52              
53             # create empty clrt object
54 0         0 my $self = [
55             {}, # object header
56             [] # colorant array
57             ];
58              
59             # verify 3 parameters
60 0 0       0 (@_ == 3) or croak('wrong number of parameters');
61              
62             # read clrt data from profile
63 0         0 _readICCclrt($self, @_);
64              
65             # bless object
66 0         0 bless($self, $class);
67              
68             # return object reference
69 0         0 return($self);
70              
71             }
72              
73             # writes clrt tag object to ICC profile
74             # parameters: (ref_to_parent_object, file_handle, ref_to_tag_table_entry)
75             sub write_fh {
76              
77             # verify 4 parameters
78 0 0   0 0 0 (@_ == 4) or croak('wrong number of parameters');
79              
80             # write text data to profile
81 0         0 goto &_writeICCclrt;
82              
83             }
84              
85             # get tag size (for writing to profile)
86             # returns: (tag_size)
87             sub size {
88            
89             # get parameters
90 1     1 0 836 my ($self) = @_;
91            
92             # return size
93 1         2 return(12 + @{$self->[1]} * 38);
  1         5  
94            
95             }
96              
97             # get colorant table entry reference(s)
98             # parameters: (channel)
99             # returns: (ref_to_color_table_entry)
100             # parameters: (list_of_channels)
101             # returns: (list_of_refs_to_color_table_entries)
102             sub channel {
103              
104             # get object reference
105 2     2 0 1046 my $self = shift();
106            
107             # if parameters
108 2 50       7 if (@_) {
109            
110             # if list is wanted
111 2 100       5 if (wantarray) {
112            
113             # return list of colorant table references
114 1         3 return(map {$self->[1][$_]} @_);
  4         8  
115            
116             # single value wanted
117             } else {
118            
119             # return single colorant table reference
120 1         4 return($self->[1][$_[0]]);
121            
122             }
123            
124             }
125            
126             }
127              
128             # print object contents to string
129             # format is an array structure
130             # parameter: ([format])
131             # returns: (string)
132             sub sdump {
133              
134             # get parameters
135 0     0 1   my ($self, $p) = @_;
136              
137             # local variables
138 0           my ($s, $fmt);
139              
140             # resolve parameter to an array reference
141 0 0         $p = defined($p) ? ref($p) eq 'ARRAY' ? $p : [$p] : [];
    0          
142              
143             # get format string
144 0 0 0       $fmt = defined($p->[0]) && ! ref($p->[0]) ? $p->[0] : 'undef';
145              
146             # set string to object ID
147 0           $s = sprintf("'%s' object, (0x%x)\n", ref($self), $self);
148              
149             # return
150 0           return($s);
151              
152             }
153              
154             # new colorant tag from xCLR A2B1 tag
155             # parameters: (ref_to_object, ref_to_A2B1_tag, [ref_to_array_of_colorant_names])
156             sub _newICCclrt {
157            
158             # get parameters
159 0     0     my ($self, $tag, $name) = @_;
160            
161             # local variables
162 0           my ($type, $csi, $cso);
163 0           my ($cnt, $max, @in, @out);
164            
165             # get tag type
166 0           $type = ref($tag);
167            
168             # get input colorspace
169 0           $csi = $tag->[0]{'input_cs'};
170            
171             # get output colorspace
172 0           $cso = $tag->[0]{'output_cs'};
173            
174             # if allowable tag type
175 0 0 0       if (($type eq 'ICC::Profile::mft1' || $type eq 'ICC::Profile::mft2' || $type eq 'ICC::Profile::mAB_') &&
      0        
      0        
      0        
176             ($csi =~ m|^([2-9A-F])CLR$|) && ($cso eq 'Lab ' || $cso eq 'XYZ ')) {
177            
178             # get count from match
179 0           $cnt = hex($1);
180            
181             # get maximum colorant value
182 0 0         $max = $type eq 'ICC::Profile::mft1' ? 255 : 65535;
183            
184             # set transform mask
185 0           $tag->[6] = 0x0f;
186            
187             # for each colorant
188 0           for my $i (0 .. $cnt - 1) {
189            
190             # for each input
191 0           for my $j (0 .. $cnt - 1) {
192            
193             # set input
194 0 0         $in[$j] = $i == $j ? 1 : 0;
195            
196             }
197            
198             # if name array supplied
199 0 0         if (defined($name->[$i])) {
200            
201             # set the colorant name
202 0           $self->[1][$i][0] = $name->[$i];
203            
204             } else {
205            
206             # set the colorant name
207 0           $self->[1][$i][0] = sprintf('colorant_%x', $i + 1);
208            
209             }
210            
211             # transform color value
212 0           @{$self->[1][$i]}[1 .. 3] = map {$_ * $max} $tag->transform(@in);
  0            
  0            
213            
214             }
215            
216             # set the PCS ('Lab ' or 'XYZ ')
217 0           $self->[0]{'pcs'} = $cso;
218            
219             # set the output bit depth
220 0 0 0       $self->[0]{'output_bits'} = ($cso eq 'Lab ' && $type eq 'ICC::Profile::mft1') ? 8 : 16;
221            
222             # set the 16-bit Lab legacy flag
223 0 0 0       $self->[0]{'legacy'} = ($cso eq 'Lab ' && $type eq 'ICC::Profile::mft2') ? 1 : 0;
224            
225             } else {
226            
227             # message
228 0           carp('wrong tag type');
229            
230             }
231            
232             }
233              
234             # read clrt tag from ICC profile
235             # parameters: (ref_to_object, ref_to_parent_object, file_handle, ref_to_tag_table_entry)
236             sub _readICCclrt {
237              
238             # get parameters
239 0     0     my ($self, $parent, $fh, $tag) = @_;
240              
241             # local variables
242 0           my ($buf, $cnt);
243              
244             # save tag signature
245 0           $self->[0]{'signature'} = $tag->[0];
246              
247             # save profile connection space ('Lab ' or 'XYZ ')
248 0           $self->[0]{'pcs'} = $parent->[1][5];
249              
250             # seek start of tag
251 0           seek($fh, $tag->[1], 0);
252              
253             # read signature and color count
254 0           read($fh, $buf, 12);
255              
256             # unpack colorant count
257 0           $cnt = unpack('x8 N', $buf);
258              
259             # for each colorant
260 0           for my $i (0 .. $cnt - 1) {
261            
262             # read colorant record
263 0           read($fh, $buf, 38);
264            
265             # unpack colorant values
266 0           $self->[1][$i] = [unpack('Z32 n3', $buf)];
267            
268             }
269            
270             }
271              
272             # write clrt tag to ICC profile
273             # parameters: (ref_to_object, ref_to_parent_object, file_handle, ref_to_tag_table_entry)
274             sub _writeICCclrt {
275              
276             # get parameters
277 0     0     my ($self, $parent, $fh, $tag) = @_;
278              
279             # seek start of tag
280 0           seek($fh, $tag->[1], 0);
281              
282             # write type signature and colorant count
283 0           print $fh pack('a4 x4 N', 'clrt', scalar(@{$self->[1]}));
  0            
284              
285             # for each colorant record
286 0           for my $rec (@{$self->[1]}) {
  0            
287            
288             # write colorant values
289 0           print $fh pack('Z32 n3', @{$rec});
  0            
290            
291             }
292            
293             }
294              
295             1;