1 | #------------------------------------------------------------------------------
|
---|
2 | # File: Reconyx.pm
|
---|
3 | #
|
---|
4 | # Description: Reconyx maker notes tags
|
---|
5 | #
|
---|
6 | # Revisions: 2011-01-11 - P. Harvey Created
|
---|
7 | #
|
---|
8 | # References: 1) RCNX_MN10.pdf (courtesy of Reconyx Inc.)
|
---|
9 | # 2) ultrafire_makernote.pdf (courtesy of Reconyx Inc.)
|
---|
10 | # 3) Reconyx private communication
|
---|
11 | #------------------------------------------------------------------------------
|
---|
12 |
|
---|
13 | package Image::ExifTool::Reconyx;
|
---|
14 |
|
---|
15 | use strict;
|
---|
16 | use vars qw($VERSION);
|
---|
17 |
|
---|
18 | $VERSION = '1.06';
|
---|
19 |
|
---|
20 | # info for Type2 version tags
|
---|
21 | my %versionInfo = (
|
---|
22 | Format => 'undef[7]',
|
---|
23 | ValueConv => 'sprintf("V%.2x.%.2x %.4x:%.2x:%.2x Rev.%s", unpack("CCvCCa", $val))',
|
---|
24 | ValueConvInv => q{
|
---|
25 | my @v = $val =~ /^V([0-9a-f]+)\.([0-9a-f]+) (\d{4}):(\d{2}):(\d{2})\s*Rev\.(\w)/i or return undef;
|
---|
26 | pack('CCvCCa', map(hex, @v[0..4]), $v[5]);
|
---|
27 | },
|
---|
28 | );
|
---|
29 |
|
---|
30 | # maker notes for Reconyx Hyperfire cameras (ref PH)
|
---|
31 | %Image::ExifTool::Reconyx::Main = (
|
---|
32 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
33 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
34 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
35 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
36 | TAG_PREFIX => 'Reconyx',
|
---|
37 | FORMAT => 'int16u',
|
---|
38 | WRITABLE => 1,
|
---|
39 | FIRST_ENTRY => 0,
|
---|
40 | NOTES => q{
|
---|
41 | The following tags are extracted from the maker notes of Reconyx Hyperfire
|
---|
42 | cameras such as the HC500, HC600 and PC900.
|
---|
43 | },
|
---|
44 | 0x00 => { #1
|
---|
45 | Name => 'MakerNoteVersion',
|
---|
46 | PrintConv => 'sprintf("0x%.4x", $val)',
|
---|
47 | Writable => 0, # (we use this for identification, 0xf101 --> rev 1.0)
|
---|
48 | PrintConvInv => 'hex $val',
|
---|
49 | },
|
---|
50 | 0x01 => { #1
|
---|
51 | Name => 'FirmwareVersion',
|
---|
52 | Format => 'int16u[3]',
|
---|
53 | PrintConv => '$val=~tr/ /./; $val',
|
---|
54 | Writable => 0, # (we use this for identification, 0x0003 --> ver 2 or 3)
|
---|
55 | },
|
---|
56 | 0x04 => { #1
|
---|
57 | Name => 'FirmwareDate',
|
---|
58 | Format => 'int16u[2]',
|
---|
59 | ValueConv => q{
|
---|
60 | my @v = split(' ',$val);
|
---|
61 | sprintf('%.4x:%.2x:%.2x', $v[0], $v[1]>>8, $v[1]&0xff);
|
---|
62 | },
|
---|
63 | ValueConvInv => q{
|
---|
64 | my @v = split(':', $val);
|
---|
65 | hex($v[0]) . ' ' . hex($v[1] . $v[2]);
|
---|
66 | },
|
---|
67 | },
|
---|
68 | 0x06 => {
|
---|
69 | Name => 'TriggerMode',
|
---|
70 | Format => 'string[2]',
|
---|
71 | PrintConv => {
|
---|
72 | C => 'CodeLoc Not Entered', #1
|
---|
73 | E => 'External Sensor', #1
|
---|
74 | M => 'Motion Detection',
|
---|
75 | T => 'Time Lapse',
|
---|
76 | },
|
---|
77 | },
|
---|
78 | 0x07 => {
|
---|
79 | Name => 'Sequence',
|
---|
80 | Format => 'int16u[2]',
|
---|
81 | PrintConv => '$val =~ s/ / of /; $val',
|
---|
82 | PrintConvInv => 'join(" ", $val=~/\d+/g)',
|
---|
83 | },
|
---|
84 | 0x09 => { #1
|
---|
85 | Name => 'EventNumber',
|
---|
86 | Format => 'int16u[2]',
|
---|
87 | ValueConv => 'my @v=split(" ",$val); ($v[0]<<16) + $v[1]',
|
---|
88 | ValueConvInv => '($val>>16) . " " . ($val&0xffff)',
|
---|
89 | },
|
---|
90 | 0x0b => {
|
---|
91 | Name => 'DateTimeOriginal',
|
---|
92 | Description => 'Date/Time Original',
|
---|
93 | Format => 'int16u[6]',
|
---|
94 | Groups => { 2 => 'Time' },
|
---|
95 | Priority => 0, # (not as reliable as EXIF)
|
---|
96 | Shift => 'Time',
|
---|
97 | ValueConv => q{
|
---|
98 | my @a = split ' ', $val;
|
---|
99 | # have seen these values written big-endian when everything else is little-endian
|
---|
100 | if ($a[0] & 0xff00 and not $a[0] & 0xff) {
|
---|
101 | $_ = ($_ >> 8) | (($_ & 0xff) << 8) foreach @a;
|
---|
102 | }
|
---|
103 | sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', @a[5,3,4,2,1,0]);
|
---|
104 | },
|
---|
105 | ValueConvInv => q{
|
---|
106 | my @a = ($val =~ /\d+/g);
|
---|
107 | return undef unless @a >= 6;
|
---|
108 | join ' ', @a[5,4,3,1,2,0];
|
---|
109 | },
|
---|
110 | PrintConv => '$self->ConvertDateTime($val)',
|
---|
111 | PrintConvInv => '$self->InverseDateTime($val)',
|
---|
112 | },
|
---|
113 | 0x12 => {
|
---|
114 | Name => 'MoonPhase',
|
---|
115 | Groups => { 2 => 'Time' },
|
---|
116 | PrintConv => {
|
---|
117 | 0 => 'New',
|
---|
118 | 1 => 'New Crescent',
|
---|
119 | 2 => 'First Quarter',
|
---|
120 | 3 => 'Waxing Gibbous',
|
---|
121 | 4 => 'Full',
|
---|
122 | 5 => 'Waning Gibbous',
|
---|
123 | 6 => 'Last Quarter',
|
---|
124 | 7 => 'Old Crescent',
|
---|
125 | },
|
---|
126 | },
|
---|
127 | 0x13 => {
|
---|
128 | Name => 'AmbientTemperatureFahrenheit',
|
---|
129 | Format => 'int16s',
|
---|
130 | PrintConv => '"$val F"',
|
---|
131 | PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val',
|
---|
132 | },
|
---|
133 | 0x14 => {
|
---|
134 | Name => 'AmbientTemperature',
|
---|
135 | Format => 'int16s',
|
---|
136 | PrintConv => '"$val C"',
|
---|
137 | PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val',
|
---|
138 | },
|
---|
139 | 0x15 => {
|
---|
140 | Name => 'SerialNumber',
|
---|
141 | Format => 'undef[30]',
|
---|
142 | RawConv => '$_ = $self->Decode($val, "UCS2"); s/\0.*//; $_',
|
---|
143 | RawConvInv => q{
|
---|
144 | $_ = $self->Encode($val, "UCS2");
|
---|
145 | $_ = substr($_, 0, 30) if length($_) > 30;
|
---|
146 | return $_;
|
---|
147 | },
|
---|
148 | },
|
---|
149 | 0x24 => 'Contrast', #1
|
---|
150 | 0x25 => 'Brightness', #1
|
---|
151 | 0x26 => 'Sharpness', #1
|
---|
152 | 0x27 => 'Saturation', #1
|
---|
153 | 0x28 => {
|
---|
154 | Name => 'InfraredIlluminator',
|
---|
155 | PrintConv => { 0 => 'Off', 1 => 'On' },
|
---|
156 | },
|
---|
157 | 0x29 => 'MotionSensitivity', #1
|
---|
158 | 0x2a => { #1
|
---|
159 | Name => 'BatteryVoltage',
|
---|
160 | ValueConv => '$val / 1000',
|
---|
161 | ValueConvInv => '$val * 1000',
|
---|
162 | PrintConv => '"$val V"',
|
---|
163 | PrintConvInv => '$val=~s/ ?V$//; $val',
|
---|
164 | },
|
---|
165 | 0x2b => {
|
---|
166 | Name => 'UserLabel',
|
---|
167 | Format => 'string[22]', #1 (but manual says 16-char limit)
|
---|
168 | },
|
---|
169 | );
|
---|
170 |
|
---|
171 | # maker notes for Reconyx UltraFire cameras (ref PH)
|
---|
172 | %Image::ExifTool::Reconyx::Type2 = (
|
---|
173 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
174 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
175 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
176 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
177 | TAG_PREFIX => 'Reconyx',
|
---|
178 | WRITABLE => 1,
|
---|
179 | FIRST_ENTRY => 0,
|
---|
180 | NOTES => 'Tags extracted from models such as the UltraFire.',
|
---|
181 | # 0x0a - int32u makernote ID 0x00020000 #2
|
---|
182 | # 0x0e - int16u makernote size #2
|
---|
183 | # 0x12 - int32u public structure ID 0x07f100001 #2
|
---|
184 | # 0x16 - int16u public structure size #2 (0x5d = start of public ID to end of UserLabel)
|
---|
185 | 0x18 => { Name => 'FirmwareVersion', %versionInfo },
|
---|
186 | 0x1f => { Name => 'Micro1Version', %versionInfo }, #2
|
---|
187 | 0x26 => { Name => 'BootLoaderVersion', %versionInfo }, #2
|
---|
188 | 0x2d => { Name => 'Micro2Version', %versionInfo }, #2
|
---|
189 | 0x34 => {
|
---|
190 | Name => 'TriggerMode',
|
---|
191 | Format => 'undef[1]',
|
---|
192 | PrintConv => {
|
---|
193 | M => 'Motion Detection',
|
---|
194 | T => 'Time Lapse',
|
---|
195 | P => 'Point and Shoot', #2
|
---|
196 | },
|
---|
197 | },
|
---|
198 | 0x35 => {
|
---|
199 | Name => 'Sequence',
|
---|
200 | Format => 'int8u[2]',
|
---|
201 | PrintConv => '$val =~ s/ / of /; $val',
|
---|
202 | PrintConvInv => 'join(" ", $val=~/\d+/g)',
|
---|
203 | },
|
---|
204 | 0x37 => { #2
|
---|
205 | Name => 'EventNumber',
|
---|
206 | Format => 'int32u',
|
---|
207 | },
|
---|
208 | 0x3b => {
|
---|
209 | Name => 'DateTimeOriginal',
|
---|
210 | Description => 'Date/Time Original',
|
---|
211 | Format => 'int8u[7]',
|
---|
212 | Groups => { 2 => 'Time' },
|
---|
213 | Priority => 0, # (not as reliable as EXIF)
|
---|
214 | Shift => 'Time',
|
---|
215 | ValueConv => q{
|
---|
216 | my @a = split ' ', $val;
|
---|
217 | $a[5] += pop(@a) * 256;
|
---|
218 | sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', reverse @a);
|
---|
219 | },
|
---|
220 | ValueConvInv => q{
|
---|
221 | my @a = ($val =~ /\d+/g);
|
---|
222 | return undef unless @a >= 6;
|
---|
223 | unshift @a, ($a[0] >> 8);
|
---|
224 | $a[1] -= $a[0] * 256;
|
---|
225 | join ' ', @a[6,5,4,3,2,1,0];
|
---|
226 | },
|
---|
227 | PrintConv => '$self->ConvertDateTime($val)',
|
---|
228 | PrintConvInv => '$self->InverseDateTime($val)',
|
---|
229 | },
|
---|
230 | 0x42 => { #2
|
---|
231 | Name => 'DayOfWeek',
|
---|
232 | Groups => { 2 => 'Time' },
|
---|
233 | PrintConv => {
|
---|
234 | 0 => 'Sunday',
|
---|
235 | 1 => 'Monday',
|
---|
236 | 2 => 'Tuesday',
|
---|
237 | 3 => 'Wednesday',
|
---|
238 | 4 => 'Thursday',
|
---|
239 | 5 => 'Friday',
|
---|
240 | 6 => 'Saturday',
|
---|
241 | },
|
---|
242 | },
|
---|
243 | 0x43 => {
|
---|
244 | Name => 'MoonPhase',
|
---|
245 | Groups => { 2 => 'Time' },
|
---|
246 | PrintConv => {
|
---|
247 | 0 => 'New',
|
---|
248 | 1 => 'New Crescent',
|
---|
249 | 2 => 'First Quarter',
|
---|
250 | 3 => 'Waxing Gibbous',
|
---|
251 | 4 => 'Full',
|
---|
252 | 5 => 'Waning Gibbous',
|
---|
253 | 6 => 'Last Quarter',
|
---|
254 | 7 => 'Old Crescent',
|
---|
255 | },
|
---|
256 | },
|
---|
257 | 0x44 => {
|
---|
258 | Name => 'AmbientTemperatureFahrenheit',
|
---|
259 | Format => 'int16s',
|
---|
260 | PrintConv => '"$val F"',
|
---|
261 | PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val',
|
---|
262 | },
|
---|
263 | 0x46 => {
|
---|
264 | Name => 'AmbientTemperature',
|
---|
265 | Format => 'int16s',
|
---|
266 | PrintConv => '"$val C"',
|
---|
267 | PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val',
|
---|
268 | },
|
---|
269 | 0x48 => {
|
---|
270 | Name => 'Illumination',
|
---|
271 | PrintConv => { 0 => 'Off', 1 => 'On' },
|
---|
272 | },
|
---|
273 | 0x49 => {
|
---|
274 | Name => 'BatteryVoltage',
|
---|
275 | Format => 'int16u',
|
---|
276 | ValueConv => '$val / 1000',
|
---|
277 | ValueConvInv => '$val * 1000',
|
---|
278 | PrintConv => '"$val V"',
|
---|
279 | PrintConvInv => '$val=~s/ ?V$//; $val',
|
---|
280 | },
|
---|
281 | 0x4b => {
|
---|
282 | Name => 'SerialNumber',
|
---|
283 | Format => 'string[15]',
|
---|
284 | },
|
---|
285 | 0x5a => {
|
---|
286 | Name => 'UserLabel',
|
---|
287 | Format => 'string[21]',
|
---|
288 | },
|
---|
289 | );
|
---|
290 |
|
---|
291 | # maker notes for Reconyx HF2 PRO cameras (ref 3)
|
---|
292 | %Image::ExifTool::Reconyx::Type3 = (
|
---|
293 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
294 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
295 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
296 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
297 | TAG_PREFIX => 'Reconyx',
|
---|
298 | WRITABLE => 1,
|
---|
299 | FIRST_ENTRY => 0,
|
---|
300 | NOTES => 'Tags extracted from models such as the HF2 PRO.',
|
---|
301 | # 0x0a => { Name => 'StructureVersion', Format => 'int16u' },
|
---|
302 | # 0x0c => { Name => 'ParentFileSize', Format => 'int32u' },
|
---|
303 | 0x10 => { Name => 'FileNumber', Format => 'int16u' },
|
---|
304 | 0x12 => { Name => 'DirectoryNumber', Format => 'int16u' },
|
---|
305 | # 0x14 => { Name => 'DirCreateDate', Format => 'int16u' },
|
---|
306 | # 0x16 => { Name => 'DirCreateTime', Format => 'int16u' },
|
---|
307 | # 0x18 - int16[8] SDCardLabel
|
---|
308 | # 0x28 => { Name => 'MakerNoteVersion', Format => 'int16u' },
|
---|
309 | 0x2a => {
|
---|
310 | Name => 'FirmwareVersion',
|
---|
311 | Format => 'int16u[3]',
|
---|
312 | ValueConv => 'my @a = split " ",$val; sprintf("%d.%d%c",@a)',
|
---|
313 | ValueConvInv => '$val=~/(\d+)\.(\d+)([a-zA-Z])/ ? "$1 $2 ".ord($3) : undef',
|
---|
314 | },
|
---|
315 | 0x30 => {
|
---|
316 | Name => 'FirmwareDate',
|
---|
317 | Format => 'int16u[2]',
|
---|
318 | ValueConv => 'my ($y,$d) = split " ", $val; sprintf("%.4x:%.2x:%.2x",$y,$d>>8,$d&0xff)',
|
---|
319 | ValueConvInv => 'my @a=split ":", $val; hex($a[0])." ".hex($a[1].$a[2])',
|
---|
320 | },
|
---|
321 | 0x34 => {
|
---|
322 | Name => 'TriggerMode', #PH (NC) (called EventType in the Reconyx code)
|
---|
323 | Format => 'string[2]',
|
---|
324 | PrintConv => {
|
---|
325 | M => 'Motion Detection', # (seen this one only)
|
---|
326 | T => 'Time Lapse', # (NC)
|
---|
327 | P => 'Point and Shoot', # (NC)
|
---|
328 | },
|
---|
329 | },
|
---|
330 | 0x36 => {
|
---|
331 | Name => 'Sequence',
|
---|
332 | Format => 'int16u[2]',
|
---|
333 | PrintConv => '$val =~ s/ / of /; $val',
|
---|
334 | PrintConvInv => 'join(" ", $val=~/\d+/g)',
|
---|
335 | },
|
---|
336 | 0x3a => {
|
---|
337 | Name => 'EventNumber',
|
---|
338 | Format => 'int16u[2]',
|
---|
339 | ValueConv => 'my @a=split " ",$val;($a[0]<<16)+$a[1]',
|
---|
340 | ValueConvInv => '($val >> 16) . " " . ($val & 0xffff)',
|
---|
341 | },
|
---|
342 | 0x3e => {
|
---|
343 | Name => 'DateTimeOriginal',
|
---|
344 | Description => 'Date/Time Original',
|
---|
345 | Format => 'int16u[6]',
|
---|
346 | Groups => { 2 => 'Time' },
|
---|
347 | Priority => 0, # (not as reliable as EXIF)
|
---|
348 | Shift => 'Time',
|
---|
349 | ValueConv => q{
|
---|
350 | my @a = split ' ', $val;
|
---|
351 | sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', reverse @a);
|
---|
352 | },
|
---|
353 | ValueConvInv => q{
|
---|
354 | my @a = ($val =~ /\d+/g);
|
---|
355 | return undef unless @a >= 6;
|
---|
356 | join ' ', @a[6,5,4,3,2,1,0];
|
---|
357 | },
|
---|
358 | PrintConv => '$self->ConvertDateTime($val)',
|
---|
359 | PrintConvInv => '$self->InverseDateTime($val)',
|
---|
360 | },
|
---|
361 | 0x4a => { #2
|
---|
362 | Name => 'DayOfWeek',
|
---|
363 | Groups => { 2 => 'Time' },
|
---|
364 | Format => 'int16u',
|
---|
365 | PrintConv => {
|
---|
366 | 0 => 'Sunday',
|
---|
367 | 1 => 'Monday',
|
---|
368 | 2 => 'Tuesday',
|
---|
369 | 3 => 'Wednesday',
|
---|
370 | 4 => 'Thursday',
|
---|
371 | 5 => 'Friday',
|
---|
372 | 6 => 'Saturday',
|
---|
373 | },
|
---|
374 | },
|
---|
375 | 0x4c => {
|
---|
376 | Name => 'MoonPhase',
|
---|
377 | Groups => { 2 => 'Time' },
|
---|
378 | Format => 'int16u',
|
---|
379 | PrintConv => {
|
---|
380 | 0 => 'New',
|
---|
381 | 1 => 'New Crescent',
|
---|
382 | 2 => 'First Quarter',
|
---|
383 | 3 => 'Waxing Gibbous',
|
---|
384 | 4 => 'Full',
|
---|
385 | 5 => 'Waning Gibbous',
|
---|
386 | 6 => 'Last Quarter',
|
---|
387 | 7 => 'Old Crescent',
|
---|
388 | },
|
---|
389 | },
|
---|
390 | 0x4e => {
|
---|
391 | Name => 'AmbientTemperatureFahrenheit',
|
---|
392 | Format => 'int16s',
|
---|
393 | PrintConv => '"$val F"',
|
---|
394 | PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val',
|
---|
395 | },
|
---|
396 | 0x50 => {
|
---|
397 | Name => 'AmbientTemperature',
|
---|
398 | Format => 'int16s',
|
---|
399 | PrintConv => '"$val C"',
|
---|
400 | PrintConvInv => '$val=~/(-?\d+)/ ? $1 : $val',
|
---|
401 | },
|
---|
402 | 0x52 => { Name => 'Contrast', Format => 'int16u' },
|
---|
403 | 0x54 => { Name => 'Brightness', Format => 'int16u' },
|
---|
404 | 0x56 => { Name => 'Sharpness', Format => 'int16u' },
|
---|
405 | 0x58 => { Name => 'Saturation', Format => 'int16u' },
|
---|
406 | 0x5a => { Name => 'Flash', Format => 'int16u', PrintConv => { 0 => 'Off', 1 => 'On' } },
|
---|
407 | 0x5c => { Name => 'AmbientInfrared', Format => 'int16u' },
|
---|
408 | 0x5e => { Name => 'AmbientLight', Format => 'int16u' },
|
---|
409 | 0x60 => { Name => 'MotionSensitivity', Format => 'int16u' },
|
---|
410 | 0x62 => { Name => 'BatteryVoltage', Format => 'int16u' },
|
---|
411 | 0x64 => { Name => 'BatteryVoltageAvg', Format => 'int16u' },
|
---|
412 | 0x66 => { Name => 'BatteryType', Format => 'int16u' },
|
---|
413 | 0x68 => { Name => 'UserLabel', Format => 'string[22]' },
|
---|
414 | 0x7e => { Name => 'SerialNumber', Format => 'unicode[15]' },
|
---|
415 | );
|
---|
416 |
|
---|
417 | __END__
|
---|
418 |
|
---|
419 | =head1 NAME
|
---|
420 |
|
---|
421 | Image::ExifTool::Reconyx - Reconyx maker notes tags
|
---|
422 |
|
---|
423 | =head1 SYNOPSIS
|
---|
424 |
|
---|
425 | This module is loaded automatically by Image::ExifTool when required.
|
---|
426 |
|
---|
427 | =head1 DESCRIPTION
|
---|
428 |
|
---|
429 | This module contains definitions required by Image::ExifTool to interpret
|
---|
430 | maker notes in images from Reconyx cameras.
|
---|
431 |
|
---|
432 | =head1 AUTHOR
|
---|
433 |
|
---|
434 | Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
|
---|
435 |
|
---|
436 | This library is free software; you can redistribute it and/or modify it
|
---|
437 | under the same terms as Perl itself.
|
---|
438 |
|
---|
439 | =head1 SEE ALSO
|
---|
440 |
|
---|
441 | L<Image::ExifTool::TagNames/Reconyx Tags>,
|
---|
442 | L<Image::ExifTool(3pm)|Image::ExifTool>
|
---|
443 |
|
---|
444 | =cut
|
---|