source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/MWG.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

  • Property svn:executable set to *
File size: 22.1 KB
Line 
1#------------------------------------------------------------------------------
2# File: MWG.pm
3#
4# Description: Metadata Working Group support
5#
6# Revisions: 2009/10/21 - P. Harvey Created
7#
8# References: 1) http://www.metadataworkinggroup.org/
9#------------------------------------------------------------------------------
10
11package Image::ExifTool::MWG;
12
13use strict;
14use vars qw($VERSION);
15use Image::ExifTool qw(:DataAccess :Utils);
16use Image::ExifTool::Exif;
17
18$VERSION = '1.08';
19
20# enable MWG strict mode by default
21# (causes non-standard EXIF, IPTC and XMP to be ignored)
22$Image::ExifTool::MWG::strict = 1 unless defined $Image::ExifTool::MWG::strict;
23
24sub RecoverTruncatedIPTC($$$);
25sub ListToString($);
26sub StringToList($$);
27sub OverwriteStringList($$$$);
28
29# MWG Composite tags
30%Image::ExifTool::MWG::Composite = (
31 GROUPS => { 0 => 'Composite', 1 => 'MWG', 2 => 'Image' },
32 VARS => { NO_ID => 1 },
33 NOTES => q{
34 The Metadata Working Group (MWG) recommendations provide a set of rules to
35 allow certain overlapping EXIF, IPTC and XMP tags to be reconciled when
36 reading, and synchronized when writing. The ExifTool MWG module is designed
37 to aid in the implementation of these recommendations. (See
38 L<http://www.metadataworkinggroup.org/> for the complete MWG technical
39 specifications.)
40
41 The table below lists special Composite tags which are used to access other
42 tags based on the MWG 2.0 recommendations. These tags are only accessible
43 when the MWG module is loaded. The MWG module is loaded automatically by
44 the exiftool application if MWG is specified as a group for any tag on the
45 command line, or manually with the C<-use MWG> option. Via the API, the MWG
46 module is loaded with "C<use Image::ExifTool::MWG>".
47
48 When reading, the value of each MWG tag is B<Derived From> the specified
49 tags based on the MWG guidelines. When writing, the appropriate associated
50 tags are written. The value of the IPTCDigest tag is updated automatically
51 when the IPTC is changed if either the IPTCDigest tag didn't exist
52 beforehand or its value agreed with the original IPTC digest (indicating
53 that the XMP is synchronized with the IPTC). IPTC information is written
54 only if the original file contained IPTC.
55
56 Loading the MWG module activates "strict MWG conformance mode", which has
57 the effect of causing EXIF, IPTC and XMP in non-standard locations to be
58 ignored when reading, as per the MWG recommendations. Instead, a "Warning"
59 tag is generated when non-standard metadata is encountered. This feature
60 may be disabled by setting C<$Image::ExifTool::MWG::strict = 0> in the
61 ExifTool config file (or from your Perl script when using the API). Note
62 that the behaviour when writing is not changed: ExifTool always creates new
63 records only in the standard location, but writes new tags to any
64 EXIF/IPTC/XMP records that exist.
65
66 A complication of the specification is that although the MWG:Creator
67 property may consist of multiple values, the associated EXIF tag
68 (EXIF:Artist) is only a simple string. To resolve this discrepancy the MWG
69 recommends a technique which allows a list of values to be stored in a
70 string by using a semicolon-space separator (with quotes around values if
71 necessary). When the MWG module is loaded, ExifTool automatically
72 implements this policy and changes EXIF:Artist to a list-type tag.
73 },
74 Keywords => {
75 Flags => ['Writable','List'],
76 Desire => {
77 0 => 'IPTC:Keywords', # (64-character limit)
78 1 => 'XMP-dc:Subject',
79 2 => 'CurrentIPTCDigest',
80 3 => 'IPTCDigest',
81 },
82 ValueConv => q{
83 return $val[1] if not defined $val[2] or (defined $val[1] and
84 (not defined $val[3] or $val[2] eq $val[3]));
85 return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $val[1], 64);
86 },
87 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
88 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
89 WriteAlso => {
90 # only write Keywords if IPTC exists (ie. set EditGroup option)
91 'IPTC:Keywords' => '$opts{EditGroup} = 1; $val',
92 'XMP-dc:Subject' => '$val',
93 },
94 },
95 Description => {
96 Writable => 1,
97 Desire => {
98 0 => 'EXIF:ImageDescription',
99 1 => 'IPTC:Caption-Abstract', # (2000-character limit)
100 2 => 'XMP-dc:Description',
101 3 => 'CurrentIPTCDigest',
102 4 => 'IPTCDigest',
103 },
104 ValueConv => q{
105 return $val[0] if defined $val[0] and $val[0] !~ /^ *$/;
106 return $val[2] if not defined $val[3] or (defined $val[2] and
107 (not defined $val[4] or $val[3] eq $val[4]));
108 return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[1], $val[2], 2000);
109 },
110 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
111 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
112 WriteAlso => {
113 'EXIF:ImageDescription' => '$val',
114 'IPTC:Caption-Abstract' => '$opts{EditGroup} = 1; $val',
115 'XMP-dc:Description' => '$val',
116 },
117 },
118 DateTimeOriginal => {
119 Description => 'Date/Time Original',
120 Groups => { 2 => 'Time' },
121 Notes => '"creation date of the intellectual content being shown" - MWG',
122 Writable => 1,
123 Desire => {
124 0 => 'EXIF:DateTimeOriginal',
125 1 => 'EXIF:SubSecTimeOriginal',
126 2 => 'IPTC:DateCreated',
127 3 => 'IPTC:TimeCreated',
128 4 => 'XMP-photoshop:DateCreated',
129 5 => 'CurrentIPTCDigest',
130 6 => 'IPTCDigest',
131 },
132 ValueConv => q{
133 if (defined $val[0] and $val[0] !~ /^[: ]*$/) {
134 return ($val[1] and $val[1] !~ /^ *$/) ? "$val[0].$val[1]" : $val[0];
135 }
136 return $val[4] if not defined $val[5] or (defined $val[4] and
137 (not defined $val[6] or $val[5] eq $val[6]));
138 return $val[3] ? "$val[2] $val[3]" : $val[2] if $val[2];
139 return undef;
140 },
141 PrintConv => '$self->ConvertDateTime($val)',
142 PrintConvInv => '$self->InverseDateTime($val,undef,1)',
143 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
144 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
145 WriteAlso => {
146 # set EXIF date/time values according to PrintConv option instead
147 # of defaulting to Type=ValueConv to allow reformatting to be applied
148 'EXIF:DateTimeOriginal' => 'delete $opts{Type}; $val',
149 'EXIF:SubSecTimeOriginal' => 'delete $opts{Type}; $val',
150 'IPTC:DateCreated' => '$opts{EditGroup} = 1; $val',
151 'IPTC:TimeCreated' => '$opts{EditGroup} = 1; $val',
152 'XMP-photoshop:DateCreated' => '$val',
153 },
154 },
155 CreateDate => {
156 Groups => { 2 => 'Time' },
157 Notes => '"creation date of the digital representation" - MWG',
158 Writable => 1,
159 Desire => {
160 0 => 'EXIF:CreateDate',
161 1 => 'EXIF:SubSecTimeDigitized',
162 2 => 'IPTC:DigitalCreationDate',
163 3 => 'IPTC:DigitalCreationTime',
164 4 => 'XMP-xmp:CreateDate',
165 5 => 'CurrentIPTCDigest',
166 6 => 'IPTCDigest',
167 },
168 ValueConv => q{
169 if (defined $val[0] and $val[0] !~ /^[: ]*$/) {
170 return ($val[1] and $val[1] !~ /^ *$/) ? "$val[0].$val[1]" : $val[0];
171 }
172 return $val[4] if not defined $val[5] or (defined $val[4] and
173 (not defined $val[6] or $val[5] eq $val[6]));
174 return $val[3] ? "$val[2] $val[3]" : $val[2] if $val[2];
175 return undef;
176 },
177 PrintConv => '$self->ConvertDateTime($val)',
178 PrintConvInv => '$self->InverseDateTime($val,undef,1)',
179 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
180 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
181 WriteAlso => {
182 'EXIF:CreateDate' => 'delete $opts{Type}; $val',
183 'EXIF:SubSecTimeDigitized' => 'delete $opts{Type}; $val',
184 'IPTC:DigitalCreationDate' => '$opts{EditGroup} = 1; $val',
185 'IPTC:DigitalCreationTime' => '$opts{EditGroup} = 1; $val',
186 'XMP-xmp:CreateDate' => '$val',
187 },
188 },
189 ModifyDate => {
190 Groups => { 2 => 'Time' },
191 Notes => '"modification date of the digital image file" - MWG',
192 Writable => 1,
193 Desire => {
194 0 => 'EXIF:ModifyDate',
195 1 => 'EXIF:SubSecTime',
196 2 => 'XMP-xmp:ModifyDate',
197 3 => 'CurrentIPTCDigest',
198 4 => 'IPTCDigest',
199 },
200 ValueConv => q{
201 if (defined $val[0] and $val[0] !~ /^[: ]*$/) {
202 return ($val[1] and $val[1] !~ /^ *$/) ? "$val[0].$val[1]" : $val[0];
203 }
204 return $val[2] if not defined $val[3] or not defined $val[4] or $val[3] eq $val[4];
205 return undef;
206 },
207 PrintConv => '$self->ConvertDateTime($val)',
208 PrintConvInv => '$self->InverseDateTime($val,undef,1)',
209 # return empty string from check routines so this tag will never be set
210 # (only WriteAlso tags are written), the only difference is a -v2 message
211 DelCheck => '""',
212 WriteCheck => '""',
213 WriteAlso => {
214 'EXIF:ModifyDate' => 'delete $opts{Type}; $val',
215 'EXIF:SubSecTime' => 'delete $opts{Type}; $val',
216 'XMP-xmp:ModifyDate' => '$val',
217 },
218 },
219 Orientation => {
220 Writable => 1,
221 Require => 'EXIF:Orientation',
222 ValueConv => '$val',
223 PrintConv => \%Image::ExifTool::Exif::orientation,
224 DelCheck => '""',
225 WriteCheck => '""',
226 WriteAlso => {
227 'EXIF:Orientation' => '$val',
228 },
229 },
230 Rating => {
231 Writable => 1,
232 Require => 'XMP-xmp:Rating',
233 ValueConv => '$val',
234 DelCheck => '""',
235 WriteCheck => '""',
236 WriteAlso => {
237 'XMP-xmp:Rating' => '$val',
238 },
239 },
240 Copyright => {
241 Groups => { 2 => 'Author' },
242 Writable => 1,
243 Desire => {
244 0 => 'EXIF:Copyright',
245 1 => 'IPTC:CopyrightNotice', # (128-character limit)
246 2 => 'XMP-dc:Rights',
247 3 => 'CurrentIPTCDigest',
248 4 => 'IPTCDigest',
249 },
250 ValueConv => q{
251 return $val[0] if defined $val[0] and $val[0] !~ /^ *$/;
252 return $val[2] if not defined $val[3] or (defined $val[2] and
253 (not defined $val[4] or $val[3] eq $val[4]));
254 return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[1], $val[2], 128);
255 },
256 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
257 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
258 WriteAlso => {
259 'EXIF:Copyright' => '$val',
260 'IPTC:CopyrightNotice' => '$opts{EditGroup} = 1; $val',
261 'XMP-dc:Rights' => '$val',
262 },
263 },
264 Creator => {
265 Groups => { 2 => 'Author' },
266 Flags => ['Writable','List'],
267 Desire => {
268 0 => 'EXIF:Artist',
269 1 => 'IPTC:By-line', # (32-character limit)
270 2 => 'XMP-dc:Creator',
271 3 => 'CurrentIPTCDigest',
272 4 => 'IPTCDigest',
273 },
274 ValueConv => q{
275 return $val[0] if defined $val[0] and $val[0] !~ /^ *$/;
276 return $val[2] if not defined $val[3] or (defined $val[2] and
277 (not defined $val[4] or $val[3] eq $val[4]));
278 return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[1], $val[2], 32);
279 },
280 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
281 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
282 WriteAlso => {
283 'EXIF:Artist' => '$val',
284 'IPTC:By-line' => '$opts{EditGroup} = 1; $val',
285 'XMP-dc:Creator' => '$val',
286 },
287 },
288 Country => {
289 Groups => { 2 => 'Location' },
290 Writable => 1,
291 Desire => {
292 0 => 'IPTC:Country-PrimaryLocationName', # (64-character limit)
293 1 => 'XMP-photoshop:Country',
294 2 => 'CurrentIPTCDigest',
295 3 => 'IPTCDigest',
296 },
297 ValueConv => q{
298 return $val[1] if not defined $val[2] or (defined $val[1] and
299 (not defined $val[3] or $val[2] eq $val[3]));
300 return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $val[1], 64);
301 },
302 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
303 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
304 WriteAlso => {
305 'IPTC:Country-PrimaryLocationName' => '$opts{EditGroup} = 1; $val',
306 'XMP-photoshop:Country' => '$val',
307 },
308 },
309 State => {
310 Groups => { 2 => 'Location' },
311 Writable => 1,
312 Desire => {
313 0 => 'IPTC:Province-State', # (32-character limit)
314 1 => 'XMP-photoshop:State',
315 2 => 'CurrentIPTCDigest',
316 3 => 'IPTCDigest',
317 },
318 ValueConv => q{
319 return $val[1] if not defined $val[2] or (defined $val[1] and
320 (not defined $val[3] or $val[2] eq $val[3]));
321 return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $val[1], 32);
322 },
323 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
324 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
325 WriteAlso => {
326 'IPTC:Province-State' => '$opts{EditGroup} = 1; $val',
327 'XMP-photoshop:State' => '$val',
328 },
329 },
330 City => {
331 Groups => { 2 => 'Location' },
332 Writable => 1,
333 Desire => {
334 0 => 'IPTC:City', # (32-character limit)
335 1 => 'XMP-photoshop:City',
336 2 => 'CurrentIPTCDigest',
337 3 => 'IPTCDigest',
338 },
339 ValueConv => q{
340 return $val[1] if not defined $val[2] or (defined $val[1] and
341 (not defined $val[3] or $val[2] eq $val[3]));
342 return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $val[1], 32);
343 },
344 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
345 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
346 WriteAlso => {
347 'IPTC:City' => '$opts{EditGroup} = 1; $val',
348 'XMP-photoshop:City' => '$val',
349 },
350 },
351 Location => {
352 Groups => { 2 => 'Location' },
353 Writable => 1,
354 Desire => {
355 0 => 'IPTC:Sub-location', # (32-character limit)
356 1 => 'XMP-iptcCore:Location',
357 2 => 'CurrentIPTCDigest',
358 3 => 'IPTCDigest',
359 },
360 ValueConv => q{
361 return $val[1] if not defined $val[2] or (defined $val[1] and
362 (not defined $val[3] or $val[2] eq $val[3]));
363 return Image::ExifTool::MWG::RecoverTruncatedIPTC($val[0], $val[1], 32);
364 },
365 DelCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
366 WriteCheck => 'Image::ExifTool::MWG::ReconcileIPTCDigest($self)',
367 WriteAlso => {
368 'IPTC:Sub-location' => '$opts{EditGroup} = 1; $val',
369 'XMP-iptcCore:Location' => '$val',
370 },
371 },
372);
373
374unless ($Image::ExifTool::documentOnly) {
375 # add our composite tags
376 Image::ExifTool::AddCompositeTags('Image::ExifTool::MWG');
377 # must also add to lookup so we can write them
378 # (since MWG tags aren't in the tag lookup by default)
379 Image::ExifTool::AddTagsToLookup(\%Image::ExifTool::MWG::Composite,
380 'Image::ExifTool::Composite');
381}
382
383# modify EXIF:Artist to behave as a List-type tag
384{
385 my $artist = $Image::ExifTool::Exif::Main{0x13b};
386 $$artist{List} = 1;
387 $$artist{IsOverwriting} = \&OverwriteStringList;
388 $$artist{RawConv} = \&StringToList;
389}
390
391#------------------------------------------------------------------------------
392# Change a list of values to a string using MWG rules
393# Inputs: 0)reference to list of values
394# Returns: string of values (and may reformat list entries)
395sub ListToString($)
396{
397 my $vals = shift;
398 foreach (@$vals) {
399 # double all quotes in value and quote the value if it begins
400 # with a quote or contains a semicolon-space separator
401 if (/^"/ or /; /) {
402 s/"/""/g; # double all quotes
403 $_ = qq{"$_"}; # quote the value
404 }
405 }
406 return join('; ', @$vals);
407}
408
409#------------------------------------------------------------------------------
410# Change a string value to a list of values using MWG rules
411# Inputs: 0) string of values, 1) ExifTool ref
412# Returns: value or list reference if more than one value
413# Notes: Sets Warning tag on error
414sub StringToList($$)
415{
416 my ($str, $exifTool) = @_;
417 my (@vals, $inQuotes);
418 my @t = split '; ', $str, -1;
419 foreach (@t) {
420 my $wasQuotes = $inQuotes;
421 $inQuotes = 1 if not $inQuotes and s/^"//;
422 if ($inQuotes) {
423 # remove the last quote and reset the inQuotes flag if
424 # the value ended in an odd number of quotes
425 $inQuotes = 0 if s/((^|[^"])("")*)"$/$1/;
426 s/""/"/g; # un-double the contained quotes
427 }
428 if ($wasQuotes) {
429 # previous separator was quoted, so concatinate with previous value
430 $vals[-1] .= '; ' . $_;
431 } else {
432 push @vals, $_;
433 }
434 }
435 $exifTool->Warn('Incorrectly quoted MWG string-list value') if $inQuotes;
436 return @vals > 1 ? \@vals : $vals[0];
437}
438
439#------------------------------------------------------------------------------
440# Handle logic for overwriting EXIF string-type list tag
441# Inputs: 0) new value hash ref, 1) new value hash ref,
442# 2) old string value (or undef if it didn't exist), 3) new value ref
443# Returns: 1 and sets the new value for the tag
444sub OverwriteStringList($$$$)
445{
446 local $_;
447 my ($exifTool, $nvHash, $val, $newValuePt) = @_;
448 my (@new, $delIndex);
449 if ($$nvHash{DelValue} and defined $val) {
450 # preserve specified old values
451 my $old = StringToList($val, $exifTool);
452 my @old = ref $old eq 'ARRAY' ? @$old : $old;
453 if (@{$$nvHash{DelValue}}) {
454 my %del;
455 $del{$_} = 1 foreach @{$$nvHash{DelValue}};
456 foreach (@old) {
457 $del{$_} or push(@new, $_), next;
458 $delIndex or $delIndex = scalar @new;
459 }
460 } else {
461 push @new, @old;
462 }
463 }
464 # add new values (at location of deleted values, if any)
465 if ($$nvHash{Value}) {
466 if (defined $delIndex) {
467 splice @new, $delIndex, 0, @{$$nvHash{Value}};
468 } else {
469 push @new, @{$$nvHash{Value}};
470 }
471 }
472 if (@new) {
473 # convert back to string format
474 $$newValuePt = ListToString(\@new);
475 } else {
476 $$newValuePt = undef; # delete the tag
477 }
478 return 1;
479}
480
481#------------------------------------------------------------------------------
482# Reconcile IPTC digest after writing an MWG tag
483# Inputs: 0) ExifTool object ref
484# Returns: empty string
485sub ReconcileIPTCDigest($)
486{
487 my $exifTool = shift;
488
489 # set new value for IPTCDigest if not done already
490 unless ($Image::ExifTool::Photoshop::iptcDigestInfo and
491 $exifTool->{NEW_VALUE}{$Image::ExifTool::Photoshop::iptcDigestInfo})
492 {
493 # write new IPTCDigest only if it doesn't exist or
494 # is the same as the digest of the original IPTC
495 my @a; # (capture warning messages)
496 @a = $exifTool->SetNewValue('Photoshop:IPTCDigest', 'old', Protected => 1, DelValue => 1);
497 @a = $exifTool->SetNewValue('Photoshop:IPTCDigest', 'new', Protected => 1);
498 }
499 return '';
500}
501
502#------------------------------------------------------------------------------
503# Recover strings which were truncated by IPTC dataset length limit
504# Inputs: 0) IPTC value, 1) XMP value, 2) length limit
505# Notes: handles the case where IPTC and/or XMP values are lists
506sub RecoverTruncatedIPTC($$$)
507{
508 my ($iptc, $xmp, $limit) = @_;
509
510 return $iptc unless defined $xmp;
511 if (ref $iptc) {
512 $xmp = [ $xmp ] unless ref $xmp;
513 my ($i, @vals);
514 for ($i=0; $i<@$iptc; ++$i) {
515 push @vals, RecoverTruncatedIPTC($$iptc[$i], $$xmp[$i], $limit);
516 }
517 return \@vals;
518 } elsif (defined $iptc and length $iptc == $limit) {
519 $xmp = $$xmp[0] if ref $xmp; # take first element of list
520 return $xmp if length $xmp > $limit and $iptc eq substr($xmp, 0, $limit);
521 }
522 return $iptc;
523}
524
5251; # end
526
527__END__
528
529=head1 NAME
530
531Image::ExifTool::MWG - Metadata Working Group support
532
533=head1 SYNOPSIS
534
535 # enable MWG tags (strict mode enabled by default)
536 use Image::ExifTool::MWG;
537
538 # disable MWG strict mode
539 $Image::ExifTool::MWG::strict = 0;
540
541=head1 DESCRIPTION
542
543The MWG module contains tag definitions which are designed to simplify
544implementation of the Metadata Working Group guidelines. These special MWG
545composite tags are enabled simply by loading this module:
546
547 use Image::ExifTool::MWG;
548
549When the MWG module is loaded, "strict MWG conformance" is enabled by
550default. In this mode, ExifTool will generate a Warning tag instead of
551extracting EXIF, IPTC and XMP from non-standard locations. The strict mode
552may be disabled by setting the MWG "strict" flag to zero (either before or
553after loading the MWG module):
554
555 $Image::ExifTool::MWG::strict = 0;
556
557=head1 AUTHOR
558
559Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
560
561This library is free software; you can redistribute it and/or modify it
562under the same terms as Perl itself.
563
564=head1 REFERENCES
565
566=over 4
567
568=item L<http://www.metadataworkinggroup.org/>
569
570=back
571
572=head1 SEE ALSO
573
574L<Image::ExifTool::TagNames/MWG Tags>,
575L<Image::ExifTool(3pm)|Image::ExifTool>
576
577=cut
Note: See TracBrowser for help on using the repository browser.