1#------------------------------------------------------------------------------
2# File:         XMP2.pl
3#
4# Description:  Additional XMP namespace definitions
5#
6# Revisions:    10/12/2008 - P. Harvey Created
7#
8# References:   1) PLUS - http://ns.useplus.org/
9#               2) PRISM - http://www.prismstandard.org/
10#               3) http://www.portfoliofaq.com/pfaq/v7mappings.htm
11#               4) http://www.iptc.org/IPTC4XMP/
12#               5) http://creativecommons.org/technology/xmp
13#                  --> changed to http://wiki.creativecommons.org/Companion_File_metadata_specification (2007/12/21)
14#               6) http://www.optimasc.com/products/fileid/xmp-extensions.pdf
15#               9) http://www.w3.org/TR/SVG11/
16#               11) http://www.extensis.com/en/support/kb_article.jsp?articleNumber=6102211
17#               12) XMPSpecificationPart3_May2013, page 58
18#               13) https://developer.android.com/training/camera2/Dynamic-depth-v1.0.pdf
19#------------------------------------------------------------------------------
20
21package Image::ExifTool::XMP;
22
23use strict;
24use Image::ExifTool qw(:Utils);
25use Image::ExifTool::XMP;
26
27sub Init_crd($);
28
29#------------------------------------------------------------------------------
30
31# xmpDM structure definitions
32my %sCuePointParam = (
33    STRUCT_NAME => 'CuePointParam',
34    NAMESPACE   => 'xmpDM',
35    key         => { },
36    value       => { },
37);
38my %sMarker = (
39    STRUCT_NAME => 'Marker',
40    NAMESPACE   => 'xmpDM',
41    comment     => { },
42    duration    => { },
43    location    => { },
44    name        => { },
45    startTime   => { },
46    target      => { },
47    type        => { },
48    # added Oct 2008
49    cuePointParams => { Struct => \%sCuePointParam, List => 'Seq' },
50    cuePointType=> { },
51    probability => { Writable => 'real' },
52    speaker     => { },
53);
54my %sTime = (
55    STRUCT_NAME => 'Time',
56    NAMESPACE   => 'xmpDM',
57    scale       => { Writable => 'rational' },
58    value       => { Writable => 'integer' },
59);
60my %sTimecode = (
61    STRUCT_NAME => 'Timecode',
62    NAMESPACE   => 'xmpDM',
63    timeFormat  => {
64        PrintConv => {
65            '24Timecode' => '24 fps',
66            '25Timecode' => '25 fps',
67            '2997DropTimecode' => '29.97 fps (drop)',
68            '2997NonDropTimecode' => '29.97 fps (non-drop)',
69            '30Timecode' => '30 fps',
70            '50Timecode' => '50 fps',
71            '5994DropTimecode' => '59.94 fps (drop)',
72            '5994NonDropTimecode' => '59.94 fps (non-drop)',
73            '60Timecode' => '60 fps',
74            '23976Timecode' => '23.976 fps',
75        },
76    },
77    timeValue   => { },
78    value       => { Writable => 'integer', Notes => 'only in XMP 2008 spec; an error?' },
79);
80my %sPose = (
81    STRUCT_NAME => 'Pose',
82    NAMESPACE => { Pose => 'http://ns.google.com/photos/dd/1.0/pose/' },
83    PositionX => { Writable => 'real', Groups => { 2 => 'Location' } },
84    PositionY => { Writable => 'real', Groups => { 2 => 'Location' } },
85    PositionZ => { Writable => 'real', Groups => { 2 => 'Location' } },
86    RotationX => { Writable => 'real', Groups => { 2 => 'Location' } },
87    RotationY => { Writable => 'real', Groups => { 2 => 'Location' } },
88    RotationZ => { Writable => 'real', Groups => { 2 => 'Location' } },
89    RotationW => { Writable => 'real', Groups => { 2 => 'Location' } },
90    Timestamp => {
91        Writable => 'integer',
92        Shift => 'Time',
93        Groups => { 2 => 'Time' },
94        ValueConv => 'ConvertUnixTime($val / 1000, 1, 3)',
95        ValueConvInv => 'int(GetUnixTime($val, 1) * 1000)',
96        PrintConv => '$self->ConvertDateTime($val)',
97        PrintConvInv => '$self->InverseDateTime($val,undef,1)',
98    },
99);
100my %sEarthPose = (
101    STRUCT_NAME => 'EarthPose',
102    NAMESPACE => { EarthPose => 'http://ns.google.com/photos/dd/1.0/earthpose/' },
103    Latitude  => { Writable => 'real', Groups => { 2 => 'Location' }, %latConv },
104    Longitude => { Writable => 'real', Groups => { 2 => 'Location' }, %longConv },
105    Altitude  => {
106        Writable => 'real',
107        Groups => { 2 => 'Location' },
108        PrintConv => '"$val m"',
109        PrintConvInv => '$val=~s/\s*m$//;$val',
110    },
111    RotationX => { Writable => 'real', Groups => { 2 => 'Location' } },
112    RotationY => { Writable => 'real', Groups => { 2 => 'Location' } },
113    RotationZ => { Writable => 'real', Groups => { 2 => 'Location' } },
114    RotationW => { Writable => 'real', Groups => { 2 => 'Location' } },
115    Timestamp => {
116        Writable => 'integer',
117        Shift => 'Time',
118        Groups => { 2 => 'Time' },
119        ValueConv => 'ConvertUnixTime($val / 1000, 1, 3)',
120        ValueConvInv => 'int(GetUnixTime($val, 1) * 1000)',
121        PrintConv => '$self->ConvertDateTime($val)',
122        PrintConvInv => '$self->InverseDateTime($val,undef,1)',
123    },
124);
125my %sVendorInfo = (
126    STRUCT_NAME => 'VendorInfo',
127    NAMESPACE   => { VendorInfo => 'http://ns.google.com/photos/dd/1.0/vendorinfo/' },
128    Model => { },
129    Manufacturer => { },
130    Notes => { },
131);
132my %sAppInfo = (
133    STRUCT_NAME => 'AppInfo',
134    NAMESPACE   => { AppInfo => 'http://ns.google.com/photos/dd/1.0/appinfo/' },
135    Application => { },
136    Version => { },
137    ItemURI => { },
138);
139
140# camera-raw defaults
141%Image::ExifTool::XMP::crd = (
142    %xmpTableDefaults,
143    INIT_TABLE => \&Init_crd,
144    GROUPS => { 1 => 'XMP-crd', 2 => 'Image' },
145    NAMESPACE   => 'crd',
146    AVOID => 1,
147    TABLE_DESC => 'Photoshop Camera Defaults namespace',
148    NOTES => 'Adobe Camera Raw Defaults tags.',
149    # (tags added dynamically when WRITE_PROC is called)
150);
151
152# XMP Dynamic Media namespace properties (xmpDM)
153%Image::ExifTool::XMP::xmpDM = (
154    %xmpTableDefaults,
155    GROUPS => { 1 => 'XMP-xmpDM', 2 => 'Image' },
156    NAMESPACE => 'xmpDM',
157    NOTES => 'XMP Dynamic Media namespace tags.',
158    absPeakAudioFilePath=> { },
159    album               => { },
160    altTapeName         => { },
161    altTimecode         => { Struct => \%sTimecode },
162    artist              => { Avoid => 1, Groups => { 2 => 'Author' } },
163    audioModDate        => { Groups => { 2 => 'Time' }, %dateTimeInfo },
164    audioSampleRate     => { Writable => 'integer' },
165    audioSampleType => {
166        PrintConv => {
167            '8Int' => '8-bit integer',
168            '16Int' => '16-bit integer',
169            '24Int' => '24-bit integer',
170            '32Int' => '32-bit integer',
171            '32Float' => '32-bit float',
172            'Compressed' => 'Compressed',
173            'Packed' => 'Packed',
174            'Other' => 'Other',
175        },
176    },
177    audioChannelType => {
178        PrintConv => {
179            'Mono' => 'Mono',
180            'Stereo' => 'Stereo',
181            '5.1' => '5.1',
182            '7.1' => '7.1',
183            '16 Channel' => '16 Channel',
184            'Other' => 'Other',
185        },
186    },
187    audioCompressor     => { },
188    beatSpliceParams => {
189        Struct => {
190            STRUCT_NAME => 'BeatSpliceStretch',
191            NAMESPACE   => 'xmpDM',
192            riseInDecibel       => { Writable => 'real' },
193            riseInTimeDuration  => { Struct => \%sTime },
194            useFileBeatsMarker  => { Writable => 'boolean' },
195        },
196    },
197    cameraAngle         => { },
198    cameraLabel         => { },
199    cameraModel         => { },
200    cameraMove          => { },
201    client              => { },
202    comment             => { Name => 'DMComment' },
203    composer            => { Groups => { 2 => 'Author' } },
204    contributedMedia => {
205        Struct => {
206            STRUCT_NAME => 'Media',
207            NAMESPACE   => 'xmpDM',
208            duration    => { Struct => \%sTime },
209            managed     => { Writable => 'boolean' },
210            path        => { },
211            startTime   => { Struct => \%sTime },
212            track       => { },
213            webStatement=> { },
214        },
215        List => 'Bag',
216    },
217    copyright       => { Avoid => 1, Groups => { 2 => 'Author' } }, # (deprecated)
218    director        => { },
219    directorPhotography => { },
220    discNumber      => { }, #12
221    duration        => { Struct => \%sTime },
222    engineer        => { },
223    fileDataRate    => { Writable => 'rational' },
224    genre           => { },
225    good            => { Writable => 'boolean' },
226    instrument      => { },
227    introTime       => { Struct => \%sTime },
228    key => {
229        PrintConvColumns => 3,
230        PrintConv => {
231            'C'  => 'C',  'C#' => 'C#', 'D'  => 'D',  'D#' => 'D#',
232            'E'  => 'E',  'F'  => 'F',  'F#' => 'F#', 'G'  => 'G',
233            'G#' => 'G#', 'A'  => 'A',  'A#' => 'A#', 'B'  => 'B',
234        },
235    },
236    logComment      => { },
237    loop            => { Writable => 'boolean' },
238    lyrics          => { }, #12
239    numberOfBeats   => { Writable => 'real' },
240    markers         => { Struct => \%sMarker, List => 'Seq' },
241    metadataModDate => { Groups => { 2 => 'Time' }, %dateTimeInfo },
242    outCue          => { Struct => \%sTime },
243    partOfCompilation=>{ Writable => 'boolean' }, #12
244    projectName     => { },
245    projectRef => {
246        Struct => {
247            STRUCT_NAME => 'ProjectLink',
248            NAMESPACE   => 'xmpDM',
249            path        => { },
250            type        => {
251                PrintConv => {
252                    movie => 'Movie',
253                    still => 'Still Image',
254                    audio => 'Audio',
255                    custom => 'Custom',
256                },
257            },
258        },
259    },
260    pullDown => {
261        PrintConvColumns => 2,
262        PrintConv => {
263            'WSSWW' => 'WSSWW',  'SSWWW' => 'SSWWW',
264            'SWWWS' => 'SWWWS',  'WWWSS' => 'WWWSS',
265            'WWSSW' => 'WWSSW',  'WWWSW' => 'WWWSW',
266            'WWSWW' => 'WWSWW',  'WSWWW' => 'WSWWW',
267            'SWWWW' => 'SWWWW',  'WWWWS' => 'WWWWS',
268        },
269    },
270    relativePeakAudioFilePath => { },
271    relativeTimestamp   => { Struct => \%sTime },
272    releaseDate         => { Groups => { 2 => 'Time' }, %dateTimeInfo },
273    resampleParams => {
274        Struct => {
275            STRUCT_NAME => 'ResampleStretch',
276            NAMESPACE   => 'xmpDM',
277            quality     => { PrintConv => { Low => 'Low', Medium => 'Medium', High => 'High' } },
278        },
279    },
280    scaleType => {
281        PrintConv => {
282            Major => 'Major',
283            Minor => 'Minor',
284            Both => 'Both',
285            Neither => 'Neither',
286        },
287    },
288    scene           => { Avoid => 1 },
289    shotDate        => { Groups => { 2 => 'Time' }, %dateTimeInfo },
290    shotDay         => { },
291    shotLocation    => { },
292    shotName        => { },
293    shotNumber      => { },
294    shotSize        => { },
295    speakerPlacement=> { },
296    startTimecode   => { Struct => \%sTimecode },
297    startTimeSampleSize => { Writable => 'integer' }, #PH
298    startTimeScale  => { }, #PH (real?)
299    stretchMode     => {
300        PrintConv => {
301            'Fixed length' => 'Fixed length',
302            'Time-Scale' => 'Time-Scale',
303            'Resample' => 'Resample',
304            'Beat Splice' => 'Beat Splice',
305            'Hybrid' => 'Hybrid',
306        },
307    },
308    takeNumber      => { Writable => 'integer' },
309    tapeName        => { },
310    tempo           => { Writable => 'real' },
311    timeScaleParams => {
312        Struct => {
313            STRUCT_NAME => 'TimeScaleStretch',
314            NAMESPACE   => 'xmpDM',
315            frameOverlappingPercentage => { Writable => 'real' },
316            frameSize   => { Writable => 'real' },
317            quality     => { PrintConv => { Low => 'Low', Medium => 'Medium', High => 'High' } },
318        },
319    },
320    timeSignature   => {
321        PrintConvColumns => 3,
322        PrintConv => {
323            '2/4' => '2/4',  '3/4' => '3/4',  '4/4' => '4/4',
324            '5/4' => '5/4',  '7/4' => '7/4',  '6/8' => '6/8',
325            '9/8' => '9/8',  '12/8'=> '12/8', 'other' => 'other',
326        },
327    },
328    trackNumber     => { Writable => 'integer' },
329    Tracks => {
330        Struct => {
331            STRUCT_NAME => 'Track',
332            NAMESPACE   => 'xmpDM',
333            frameRate => { },
334            markers   => { Struct => \%sMarker, List => 'Seq' },
335            trackName => { },
336            trackType => { },
337        },
338        List => 'Bag',
339    },
340    videoAlphaMode => {
341        PrintConv => {
342            'straight' => 'Straight',
343            'pre-multiplied', => 'Pre-multiplied',
344            'none' => 'None',
345        },
346    },
347    videoAlphaPremultipleColor   => { Struct => \%sColorant },
348    videoAlphaUnityIsTransparent => { Writable => 'boolean' },
349    videoColorSpace     => {
350        PrintConv => {
351            'sRGB' => 'sRGB',
352            'CCIR-601' => 'CCIR-601',
353            'CCIR-709' => 'CCIR-709',
354        },
355    },
356    videoCompressor => { },
357    videoFieldOrder => {
358        PrintConv => {
359            Upper => 'Upper',
360            Lower => 'Lower',
361            Progressive => 'Progressive',
362        },
363    },
364    videoFrameRate  => { Writable => 'real' },
365    videoFrameSize  => { Struct => \%sDimensions },
366    videoModDate    => { Groups => { 2 => 'Time' }, %dateTimeInfo },
367    videoPixelAspectRatio => { Writable => 'rational' },
368    videoPixelDepth => {
369        PrintConv => {
370            '8Int' => '8-bit integer',
371            '16Int' => '16-bit integer',
372            '24Int' => '24-bit integer',
373            '32Int' => '32-bit integer',
374            '32Float' => '32-bit float',
375            'Other' => 'Other',
376        },
377    },
378);
379
380#------------------------------------------------------------------------------
381# IPTC Extensions version 1.3 (+ proposed video extensions)
382
383# IPTC Extension 1.0 structures
384my %sLocationDetails = (
385    STRUCT_NAME => 'LocationDetails',
386    NAMESPACE   => 'Iptc4xmpExt',
387    GROUPS      => { 2 => 'Location' },
388    Identifier  => { List => 'Bag', Namespace => 'xmp' },
389    City        => { },
390    CountryCode => { },
391    CountryName => { },
392    ProvinceState => { },
393    Sublocation => { },
394    WorldRegion => { },
395    LocationId  => { List => 'Bag' },
396    LocationName => { Writable => 'lang-alt' },
397    GPSLatitude  => { Namespace => 'exif', %latConv },
398    GPSLongitude => { Namespace => 'exif', %longConv },
399    GPSAltitude => {
400        Namespace => 'exif',
401        Writable => 'rational',
402        PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "$val m"',
403        PrintConvInv => '$val=~s/\s*m$//;$val',
404    },
405);
406my %sCVTermDetails = (
407    STRUCT_NAME => 'CVTermDetails',
408    NAMESPACE   => 'Iptc4xmpExt',
409    CvTermId    => { },
410    CvTermName  => { Writable => 'lang-alt' },
411    CvId        => { },
412    CvTermRefinedAbout => { },
413);
414
415# IPTC video extensions
416my %sPublicationEvent = (
417    STRUCT_NAME => 'PublicationEvent',
418    NAMESPACE   => 'Iptc4xmpExt',
419    Date        => { Groups => { 2 => 'Time' }, %dateTimeInfo },
420    Name        => { },
421    Identifier  => { },
422);
423my %sEntity = (
424    STRUCT_NAME => 'Entity',
425    NAMESPACE   => 'Iptc4xmpExt',
426    Identifier  => { List => 'Bag', Namespace => 'xmp' },
427    Name        => { Writable => 'lang-alt' },
428);
429my %sEntityWithRole = (
430    STRUCT_NAME => 'EntityWithRole',
431    NAMESPACE   => 'Iptc4xmpExt',
432    Identifier  => { List => 'Bag', Namespace => 'xmp' },
433    Name        => { Writable => 'lang-alt' },
434    Role        => { List => 'Bag' },
435);
436# (no longer used)
437#my %sFrameSize = (
438#    STRUCT_NAME => 'FrameSize',
439#    NAMESPACE   => 'Iptc4xmpExt',
440#    WidthPixels  => { Writable => 'integer' },
441#    HeightPixels => { Writable => 'integer' },
442#);
443my %sRating = (
444    STRUCT_NAME => 'Rating',
445    NAMESPACE   => 'Iptc4xmpExt',
446    RatingValue         => { FlatName => 'Value' },
447    RatingSourceLink    => { FlatName => 'SourceLink' },
448    RatingScaleMinValue => { FlatName => 'ScaleMinValue' },
449    RatingScaleMaxValue => { FlatName => 'ScaleMaxValue' },
450    RatingValueLogoLink => { FlatName => 'ValueLogoLink' },
451    RatingRegion => {
452        FlatName => 'Region',
453        Struct => \%sLocationDetails,
454        List => 'Bag',
455    },
456);
457my %sEpisode = (
458    STRUCT_NAME => 'EpisodeOrSeason',
459    NAMESPACE   => 'Iptc4xmpExt',
460    Name        => { },
461    Number      => { },
462    Identifier  => { },
463);
464my %sSeries = (
465    STRUCT_NAME => 'Series',
466    NAMESPACE   => 'Iptc4xmpExt',
467    Name        => { },
468    Identifier  => { },
469);
470my %sTemporalCoverage = (
471    STRUCT_NAME => 'TemporalCoverage',
472    NAMESPACE   => 'Iptc4xmpExt',
473    tempCoverageFrom => { FlatName => 'From', %dateTimeInfo, Groups => { 2 => 'Time' } },
474    tempCoverageTo   => { FlatName => 'To',   %dateTimeInfo, Groups => { 2 => 'Time' } },
475);
476my %sQualifiedLink = (
477    STRUCT_NAME => 'QualifiedLink',
478    NAMESPACE   => 'Iptc4xmpExt',
479    Link        => { },
480    LinkQualifier => { },
481);
482my %sTextRegion = (
483    STRUCT_NAME => 'TextRegion',
484    NAMESPACE   => 'Iptc4xmpExt',
485    RegionText  => { },
486    Region      => { Struct => \%Image::ExifTool::XMP::sArea },
487);
488my %sLinkedImage = (
489    STRUCT_NAME => 'LinkedImage',
490    NAMESPACE   => 'Iptc4xmpExt',
491    Link        => { },
492    LinkQualifier => { List => 'Bag' },
493    ImageRole   => { },
494   'format'     => { Namespace => 'dc' },
495    WidthPixels => { Writable => 'integer' },
496    HeightPixels=> { Writable => 'integer' },
497    UsedVideoFrame => { Struct => \%sTimecode },
498);
499my %sBoundaryPoint = ( # new in 1.5
500    STRUCT_NAME => 'BoundaryPoint',
501    NAMESPACE   => 'Iptc4xmpExt',
502    rbX => { FlatName => 'X', Writable => 'real' },
503    rbY => { FlatName => 'Y', Writable => 'real' },
504);
505my %sRegionBoundary = ( # new in 1.5
506    STRUCT_NAME => 'RegionBoundary',
507    NAMESPACE   => 'Iptc4xmpExt',
508    rbShape => { FlatName => 'Shape', PrintConv => { rectangle => 'Rectangle', circle => 'Circle', polygon => 'Polygon' } },
509    rbUnit  => { FlatName => 'Unit',  PrintConv => { pixel => 'Pixel', relative => 'Relative' } },
510    rbX => { FlatName => 'X', Writable => 'real' },
511    rbY => { FlatName => 'Y', Writable => 'real' },
512    rbW => { FlatName => 'W', Writable => 'real' },
513    rbH => { FlatName => 'H', Writable => 'real' },
514    rbRx => { FlatName => 'Rx', Writable => 'real' },
515    rbVertices => { FlatName => 'Vertices', List => 'Seq', Struct => \%sBoundaryPoint },
516);
517my %sImageRegion = ( # new in 1.5
518    STRUCT_NAME => 'ImageRegion',
519    NAMESPACE   => undef,   # undefined to allow variable-namespace extensions
520    NOTES => q{
521        This structure is new in the IPTC Extension version 1.5 specification.  As
522        well as the fields defined below, this structure may contain any top-level
523        XMP tags, but since they aren't pre-defined the only way to add these tags
524        is to write ImageRegion as a structure with these tags as new fields.
525    },
526    RegionBoundary => { Namespace => 'Iptc4xmpExt', FlatName => 'Boundary', Struct => \%sRegionBoundary },
527    rId    => { Namespace => 'Iptc4xmpExt', FlatName => 'ID' },
528    Name   => { Namespace => 'Iptc4xmpExt', Writable => 'lang-alt' },
529    rCtype => { Namespace => 'Iptc4xmpExt', FlatName => 'Ctype', List => 'Bag', Struct => \%sEntity },
530    rRole  => { Namespace => 'Iptc4xmpExt', FlatName => 'Role',  List => 'Bag', Struct => \%sEntity },
531);
532
533# IPTC Extension namespace properties (Iptc4xmpExt) (ref 4)
534%Image::ExifTool::XMP::iptcExt = (
535    %xmpTableDefaults,
536    GROUPS => { 1 => 'XMP-iptcExt', 2 => 'Author' },
537    NAMESPACE   => 'Iptc4xmpExt',
538    TABLE_DESC => 'XMP IPTC Extension',
539    NOTES => q{
540        This table contains tags defined by the IPTC Extension schema version 1.5.
541        The actual namespace prefix is "Iptc4xmpExt", but ExifTool shortens this for
542        the family 1 group name. (see L<http://www.iptc.org/IPTC4XMP/>)
543    },
544    AboutCvTerm => {
545        Struct => \%sCVTermDetails,
546        List => 'Bag',
547    },
548    AboutCvTermCvId                 => { Flat => 1, Name => 'AboutCvTermCvId' },
549    AboutCvTermCvTermId             => { Flat => 1, Name => 'AboutCvTermId' },
550    AboutCvTermCvTermName           => { Flat => 1, Name => 'AboutCvTermName' },
551    AboutCvTermCvTermRefinedAbout   => { Flat => 1, Name => 'AboutCvTermRefinedAbout' },
552    AddlModelInfo   => { Name => 'AdditionalModelInformation' },
553    ArtworkOrObject => {
554        Struct => {
555            STRUCT_NAME => 'ArtworkOrObjectDetails',
556            NAMESPACE   => 'Iptc4xmpExt',
557            AOCopyrightNotice => { },
558            AOCreator    => { List => 'Seq' },
559            AODateCreated=> { Groups => { 2 => 'Time' }, %dateTimeInfo },
560            AOSource     => { },
561            AOSourceInvNo=> { },
562            AOTitle      => { Writable => 'lang-alt' },
563            AOCurrentCopyrightOwnerName => { },
564            AOCurrentCopyrightOwnerId   => { },
565            AOCurrentLicensorName       => { },
566            AOCurrentLicensorId         => { },
567            AOCreatorId                 => { List => 'Seq' },
568            AOCircaDateCreated          => { Groups => { 2 => 'Time' }, Protected => 1 },
569            AOStylePeriod               => { List => 'Bag' },
570            AOSourceInvURL              => { },
571            AOContentDescription        => { Writable => 'lang-alt' },
572            AOContributionDescription   => { Writable => 'lang-alt' },
573            AOPhysicalDescription       => { Writable => 'lang-alt' },
574        },
575        List => 'Bag',
576    },
577    ArtworkOrObjectAOCopyrightNotice           => { Flat => 1, Name => 'ArtworkCopyrightNotice' },
578    ArtworkOrObjectAOCreator                   => { Flat => 1, Name => 'ArtworkCreator' },
579    ArtworkOrObjectAODateCreated               => { Flat => 1, Name => 'ArtworkDateCreated' },
580    ArtworkOrObjectAOSource                    => { Flat => 1, Name => 'ArtworkSource' },
581    ArtworkOrObjectAOSourceInvNo               => { Flat => 1, Name => 'ArtworkSourceInventoryNo' },
582    ArtworkOrObjectAOTitle                     => { Flat => 1, Name => 'ArtworkTitle' },
583    ArtworkOrObjectAOCurrentCopyrightOwnerName => { Flat => 1, Name => 'ArtworkCopyrightOwnerName' },
584    ArtworkOrObjectAOCurrentCopyrightOwnerId   => { Flat => 1, Name => 'ArtworkCopyrightOwnerID' },
585    ArtworkOrObjectAOCurrentLicensorName       => { Flat => 1, Name => 'ArtworkLicensorName' },
586    ArtworkOrObjectAOCurrentLicensorId         => { Flat => 1, Name => 'ArtworkLicensorID' },
587    ArtworkOrObjectAOCreatorId                 => { Flat => 1, Name => 'ArtworkCreatorID' },
588    ArtworkOrObjectAOCircaDateCreated          => { Flat => 1, Name => 'ArtworkCircaDateCreated' },
589    ArtworkOrObjectAOStylePeriod               => { Flat => 1, Name => 'ArtworkStylePeriod' },
590    ArtworkOrObjectAOSourceInvURL              => { Flat => 1, Name => 'ArtworkSourceInvURL' },
591    ArtworkOrObjectAOContentDescription        => { Flat => 1, Name => 'ArtworkContentDescription' },
592    ArtworkOrObjectAOContributionDescription   => { Flat => 1, Name => 'ArtworkContributionDescription' },
593    ArtworkOrObjectAOPhysicalDescription       => { Flat => 1, Name => 'ArtworkPhysicalDescription' },
594    CVterm => {
595        Name => 'ControlledVocabularyTerm',
596        List => 'Bag',
597        Notes => 'deprecated by version 1.2',
598    },
599    DigImageGUID            => { Groups => { 2 => 'Image' }, Name => 'DigitalImageGUID' },
600    DigitalSourcefileType   => {
601        Name => 'DigitalSourceFileType',
602        Notes => 'now deprecated -- replaced by DigitalSourceType',
603        Groups => { 2 => 'Image' },
604    },
605    DigitalSourceType       => { Name => 'DigitalSourceType', Groups => { 2 => 'Image' } },
606    EmbdEncRightsExpr => {
607        Struct => {
608            STRUCT_NAME => 'EEREDetails',
609            NAMESPACE   => 'Iptc4xmpExt',
610            EncRightsExpr       => { },
611            RightsExprEncType   => { },
612            RightsExprLangId    => { },
613        },
614        List => 'Bag',
615    },
616    EmbdEncRightsExprEncRightsExpr      => { Flat => 1, Name => 'EmbeddedEncodedRightsExpr' },
617    EmbdEncRightsExprRightsExprEncType  => { Flat => 1, Name => 'EmbeddedEncodedRightsExprType' },
618    EmbdEncRightsExprRightsExprLangId   => { Flat => 1, Name => 'EmbeddedEncodedRightsExprLangID' },
619    Event       => { Writable => 'lang-alt' },
620    IptcLastEdited => {
621        Name => 'IPTCLastEdited',
622        Groups => { 2 => 'Time' },
623        %dateTimeInfo,
624    },
625    LinkedEncRightsExpr => {
626        Struct => {
627            STRUCT_NAME => 'LEREDetails',
628            NAMESPACE   => 'Iptc4xmpExt',
629            LinkedRightsExpr    => { },
630            RightsExprEncType   => { },
631            RightsExprLangId    => { },
632        },
633        List => 'Bag',
634    },
635    LinkedEncRightsExprLinkedRightsExpr  => { Flat => 1, Name => 'LinkedEncodedRightsExpr' },
636    LinkedEncRightsExprRightsExprEncType => { Flat => 1, Name => 'LinkedEncodedRightsExprType' },
637    LinkedEncRightsExprRightsExprLangId  => { Flat => 1, Name => 'LinkedEncodedRightsExprLangID' },
638    LocationCreated => {
639        Struct => \%sLocationDetails,
640        Groups => { 2 => 'Location' },
641        List => 'Bag',
642    },
643    LocationShown => {
644        Struct => \%sLocationDetails,
645        Groups => { 2 => 'Location' },
646        List => 'Bag',
647    },
648    MaxAvailHeight          => { Groups => { 2 => 'Image' }, Writable => 'integer' },
649    MaxAvailWidth           => { Groups => { 2 => 'Image' }, Writable => 'integer' },
650    ModelAge                => { List => 'Bag', Writable => 'integer' },
651    OrganisationInImageCode => { List => 'Bag' },
652    OrganisationInImageName => { List => 'Bag' },
653    PersonInImage           => { List => 'Bag' },
654    PersonInImageWDetails => {
655        Struct => {
656            STRUCT_NAME => 'PersonDetails',
657            NAMESPACE   => 'Iptc4xmpExt',
658            PersonId    => { List => 'Bag' },
659            PersonName  => { Writable => 'lang-alt' },
660            PersonCharacteristic => {
661                Struct  => \%sCVTermDetails,
662                List    => 'Bag',
663            },
664            PersonDescription => { Writable => 'lang-alt' },
665        },
666        List => 'Bag',
667    },
668    PersonInImageWDetailsPersonId                               => { Flat => 1, Name => 'PersonInImageId' },
669    PersonInImageWDetailsPersonName                             => { Flat => 1, Name => 'PersonInImageName' },
670    PersonInImageWDetailsPersonCharacteristic                   => { Flat => 1, Name => 'PersonInImageCharacteristic' },
671    PersonInImageWDetailsPersonCharacteristicCvId               => { Flat => 1, Name => 'PersonInImageCvTermCvId' },
672    PersonInImageWDetailsPersonCharacteristicCvTermId           => { Flat => 1, Name => 'PersonInImageCvTermId' },
673    PersonInImageWDetailsPersonCharacteristicCvTermName         => { Flat => 1, Name => 'PersonInImageCvTermName' },
674    PersonInImageWDetailsPersonCharacteristicCvTermRefinedAbout => { Flat => 1, Name => 'PersonInImageCvTermRefinedAbout' },
675    PersonInImageWDetailsPersonDescription                      => { Flat => 1, Name => 'PersonInImageDescription' },
676    ProductInImage => {
677        Struct => {
678            STRUCT_NAME => 'ProductDetails',
679            NAMESPACE   => 'Iptc4xmpExt',
680            ProductName => { Writable => 'lang-alt' },
681            ProductGTIN => { },
682            ProductDescription => { Writable => 'lang-alt' },
683        },
684        List => 'Bag',
685    },
686    ProductInImageProductName        => { Flat => 1, Name => 'ProductInImageName' },
687    ProductInImageProductGTIN        => { Flat => 1, Name => 'ProductInImageGTIN' },
688    ProductInImageProductDescription => { Flat => 1, Name => 'ProductInImageDescription' },
689    RegistryId => {
690        Name => 'RegistryID',
691        Struct => {
692            STRUCT_NAME => 'RegistryEntryDetails',
693            NAMESPACE   => 'Iptc4xmpExt',
694            RegItemId   => { },
695            RegOrgId    => { },
696            RegEntryRole=> { }, # (new in 1.3)
697        },
698        List => 'Bag',
699    },
700    RegistryIdRegItemId => { Flat => 1, Name => 'RegistryItemID' },
701    RegistryIdRegOrgId  => { Flat => 1, Name => 'RegistryOrganisationID' },
702    RegistryIdRegEntryRole => { Flat => 1, Name => 'RegistryEntryRole' },
703
704    # new Extension 1.3 properties
705    Genre           => { Groups => { 2 => 'Image' }, List => 'Bag', Struct => \%sCVTermDetails },
706
707    # new video properties (Oct 2016, ref Michael Steidl)
708    # (see http://www.iptc.org/std/videometadatahub/recommendation/IPTC-VideoMetadataHub-props-Rec_1.0.html)
709    CircaDateCreated=> { Groups => { 2 => 'Time' } },
710    Episode         => { Groups => { 2 => 'Video' }, Struct => \%sEpisode },
711    ExternalMetadataLink => { Groups => { 2 => 'Other' }, List => 'Bag' },
712    FeedIdentifier  => { Groups => { 2 => 'Video' } },
713    PublicationEvent=> { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sPublicationEvent },
714    Rating          => {
715        Groups => { 2 => 'Other' },
716        Struct  => \%sRating,
717        List    => 'Bag',
718    },
719    ReleaseReady    => { Groups => { 2 => 'Other' }, Writable => 'boolean' },
720    Season          => { Groups => { 2 => 'Video' }, Struct => \%sEpisode },
721    Series          => { Groups => { 2 => 'Video' }, Struct => \%sSeries },
722    StorylineIdentifier => { Groups => { 2 => 'Video' }, List => 'Bag' },
723    StylePeriod     => { Groups => { 2 => 'Video' } },
724    TemporalCoverage=> { Groups => { 2 => 'Video' }, Struct => \%sTemporalCoverage },
725    WorkflowTag     => { Groups => { 2 => 'Video' }, Struct => \%sCVTermDetails },
726    DataOnScreen    => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sTextRegion },
727    Dopesheet       => { Groups => { 2 => 'Video' }, Writable => 'lang-alt' },
728    DopesheetLink   => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sQualifiedLink },
729    Headline        => { Groups => { 2 => 'Video' }, Writable => 'lang-alt', Avoid => 1 },
730    PersonHeard     => { Groups => { 2 => 'Audio' }, List => 'Bag', Struct => \%sEntity },
731    VideoShotType   => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sEntity },
732    EventExt        => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sEntity, Name => 'ShownEvent' },
733    Transcript      => { Groups => { 2 => 'Video' }, Writable => 'lang-alt' },
734    TranscriptLink  => { Groups => { 2 => 'Video' }, List => 'Bag', Struct => \%sQualifiedLink },
735    VisualColour    => {
736        Name => 'VisualColor',
737        Groups => { 2 => 'Video' },
738        PrintConv => {
739            'bw-monochrome' => 'Monochrome',
740            'colour'        => 'Color',
741        },
742    },
743    Contributor     => { List => 'Bag', Struct => \%sEntityWithRole },
744    CopyrightYear   => { Groups => { 2 => 'Time' },  Writable => 'integer' },
745    Creator         => { List => 'Bag', Struct => \%sEntityWithRole },
746    SupplyChainSource => { Groups => { 2 => 'Other' }, List => 'Bag', Struct => \%sEntity },
747    audioBitRate    => { Groups => { 2 => 'Audio' }, Writable => 'integer', Name => 'AudioBitrate' },
748    audioBitRateMode=> {
749        Name => 'AudioBitrateMode',
750        Groups => { 2 => 'Audio' },
751        PrintConv => {
752            fixed => 'Fixed',
753            variable => 'Variable',
754        },
755    },
756    audioChannelCount       => { Groups => { 2 => 'Audio' }, Writable => 'integer' },
757    videoDisplayAspectRatio => { Groups => { 2 => 'Audio' }, Writable => 'rational' },
758    ContainerFormat         => { Groups => { 2 => 'Video' }, Struct => \%sEntity },
759    StreamReady => {
760        Groups => { 2 => 'Video' },
761        PrintConv => {
762            true => 'True',
763            false => 'False',
764            unknown => 'Unknown',
765        },
766    },
767    videoBitRate     => { Groups => { 2 => 'Video' }, Writable => 'integer', Name => 'VideoBitrate' },
768    videoBitRateMode => {
769        Name => 'VideoBitrateMode',
770        Groups => { 2 => 'Video' },
771        PrintConv => {
772            fixed => 'Fixed',
773            variable => 'Variable',
774        },
775    },
776    videoEncodingProfile => { Groups => { 2 => 'Video' } },
777    videoStreamsCount    => { Groups => { 2 => 'Video' }, Writable => 'integer' },
778    # new IPTC video metadata 1.1 properties
779    # (ref https://www.iptc.org/std/videometadatahub/recommendation/IPTC-VideoMetadataHub-props-Rec_1.1.html)
780    SnapshotLink => { Groups => { 2 => 'Image' }, List => 'Bag', Struct => \%sLinkedImage, Name => 'Snapshot' },
781    # new IPTC video metadata 1.2 properties
782    # (ref http://www.iptc.org/std/videometadatahub/recommendation/IPTC-VideoMetadataHub-props-Rec_1.2.html)
783    RecDevice => {
784        Groups => { 2 => 'Device' },
785        Struct => {
786            STRUCT_NAME => 'Device',
787            NAMESPACE   => 'Iptc4xmpExt',
788            Manufacturer        => { },
789            ModelName           => { },
790            SerialNumber        => { },
791            AttLensDescription  => { },
792            OwnersDeviceId      => { },
793        },
794    },
795    PlanningRef         => { List => 'Bag', Struct => \%sEntityWithRole },
796    audioBitsPerSample  => { Groups => { 2 => 'Audio' }, Writable => 'integer' },
797    # new IPTC Extension schema 1.5 property
798    ImageRegion => { Groups => { 2 => 'Image' }, List => 'Bag', Struct => \%sImageRegion },
799);
800
801#------------------------------------------------------------------------------
802# PRISM
803#
804# NOTE: The "Avoid" flag is set for all PRISM tags (via tag table AVOID flag)
805
806# my %obsolete = (
807#     Notes => 'obsolete in 2.0',
808#     ValueConvInv => sub {
809#         my ($val, $self) = @_;
810#         unless ($self->Options('IgnoreMinorErrors')) {
811#             warn "Warning: [minor] Attempt to write obsolete tag\n";
812#             return undef;
813#         }
814#         return $val;
815#     }
816# );
817
818# PRISM structure definitions
819my %prismPublicationDate = (
820    STRUCT_NAME => 'prismPublicationDate',
821    NAMESPACE   => 'prism',
822    date        => { %dateTimeInfo, Groups => { 2 => 'Time'} },
823    'a-platform'=> { },
824);
825
826# Publishing Requirements for Industry Standard Metadata (prism) (ref 2)
827%Image::ExifTool::XMP::prism = (
828    %xmpTableDefaults,
829    GROUPS => { 0 => 'XMP', 1 => 'XMP-prism', 2 => 'Document' },
830    NAMESPACE => 'prism',
831    AVOID => 1,
832    NOTES => q{
833        Publishing Requirements for Industry Standard Metadata 3.0 namespace
834        tags.  (see L<http://www.prismstandard.org/>)
835    },
836    academicField   => { }, # (3.0)
837    aggregateIssueNumber => { Writable => 'integer' }, # (3.0)
838    aggregationType => { List => 'Bag' },
839    alternateTitle  => {
840        List => 'Bag',
841        Struct => { # (becomes a structure in 3.0)
842            STRUCT_NAME => 'prismAlternateTitle',
843            NAMESPACE   => 'prism',
844            text        => { },
845            'a-platform'=> { },
846            'a-lang'    => { },
847        },
848    },
849    blogTitle       => { }, # (3.0)
850    blogURL         => { }, # (3.0)
851    bookEdition     => { }, # (3.0)
852    byteCount       => { Writable => 'integer' },
853    channel         => {
854        List => 'Bag',
855        Struct => { # (becomes a structure in 3.0)
856            STRUCT_NAME => 'prismChannel',
857            NAMESPACE   => 'prism',
858            channel     => { },
859            subchannel1 => { },
860            subchannel2 => { },
861            subchannel3 => { },
862            subchannel4 => { },
863            'a-lang'    => { },
864        },
865    },
866    complianceProfile=>{ PrintConv => { three => 'Three' } },
867    contentType     => { }, # (3.0)
868    copyrightYear   => { }, # (3.0)
869    # copyright       => { Groups => { 2 => 'Author' } }, # (deprecated in 3.0)
870    corporateEntity => { List => 'Bag' },
871    coverDate       => { %dateTimeInfo, Groups => { 2 => 'Time'} },
872    coverDisplayDate=> { },
873    creationDate    => { %dateTimeInfo, Groups => { 2 => 'Time'} },
874    dateRecieved    => { %dateTimeInfo, Groups => { 2 => 'Time'} },
875    device          => { }, # (3.0)
876    distributor     => { },
877    doi             => { Name => 'DOI', Description => 'Digital Object Identifier' },
878    edition         => { },
879    eIssn           => { },
880    #embargoDate     => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} }, # (deprecated in 3.0)
881    endingPage      => { },
882    event           => { List => 'Bag' },
883    #expirationDate  => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} }, # (deprecated in 3.0)
884    genre           => { List => 'Bag' },
885    hasAlternative  => { List => 'Bag' },
886    hasCorrection   => {
887        Struct => { # (becomes a structure in 3.0)
888            STRUCT_NAME => 'prismHasCorrection',
889            NAMESPACE   => 'prism',
890            text        => { },
891            'a-platform'=> { },
892            'a-lang'    => { },
893        },
894    },
895    # hasPreviousVersion => { }, # (not in 3.0)
896    hasTranslation  => { List => 'Bag' },
897    industry        => { List => 'Bag' },
898    isAlternativeOf => { List => 'Bag' }, # (3.0)
899    isbn            => { Name => 'ISBN', List => 'Bag' }, # 2.1 (becomes a list in 3.0)
900    isCorrectionOf  => { List => 'Bag' },
901    issn            => { Name => 'ISSN' },
902    issueIdentifier => { },
903    issueName       => { },
904    issueTeaser     => { }, # (3.0)
905    issueType       => { }, # (3.0)
906    isTranslationOf => { },
907    keyword         => { List => 'Bag' },
908    killDate        => {
909        Struct => { # (becomes a structure in 3.0)
910            STRUCT_NAME => 'prismKillDate',
911            NAMESPACE   => 'prism',
912            date        => { %dateTimeInfo, Groups => { 2 => 'Time'} },
913            'a-platform'=> { }, #PH (missed in spec?)
914        },
915    },
916   'link'           => { List => 'Bag' }, # (3.0)
917    location        => { List => 'Bag' },
918    # metadataContainer => { }, (not valid for PRISM XMP)
919    modificationDate=> { %dateTimeInfo, Groups => { 2 => 'Time'} },
920    nationalCatalogNumber => { }, # (3.0)
921    number          => { },
922    object          => { List => 'Bag' },
923    onSaleDate => { # (3.0)
924        List => 'Bag',
925        Struct => {
926            STRUCT_NAME => 'prismOnSaleDate',
927            NAMESPACE   => 'prism',
928            date        => { %dateTimeInfo, Groups => { 2 => 'Time'} },
929            'a-platform'=> { },
930        },
931    },
932    onSaleDay => { # (3.0)
933        List => 'Bag',
934        Struct => {
935            STRUCT_NAME => 'prismOnSaleDay',
936            NAMESPACE   => 'prism',
937            day         => { }, #PH (not named in spec)
938            'a-platform'=> { },
939        },
940    },
941    offSaleDate => { # (3.0)
942        List => 'Bag',
943        Struct => {
944            STRUCT_NAME => 'prismOffSaleDate',
945            NAMESPACE   => 'prism',
946            date        => { %dateTimeInfo, Groups => { 2 => 'Time'} },
947            'a-platform'=> { },
948        },
949    },
950    organization    => { List => 'Bag' },
951    originPlatform  => {
952        List => 'Bag',
953        PrintConv => {
954            email       => 'E-Mail',
955            mobile      => 'Mobile',
956            broadcast   => 'Broadcast',
957            web         => 'Web',
958           'print'      => 'Print',
959            recordableMedia => 'Recordable Media',
960            other       => 'Other',
961        },
962    },
963    pageCount       => { Writable => 'integer' }, # (3.0)
964    pageProgressionDirection => { # (3.0)
965        PrintConv => { LTR => 'Left to Right', RTL => 'Right to Left' },
966    },
967    pageRange       => { List => 'Bag' },
968    person          => { },
969    platform        => { }, # (3.0)
970    productCode     => { }, # (3.0)
971    profession      => { }, # (3.0)
972    publicationDate => {
973        List => 'Bag',
974        Struct => \%prismPublicationDate, # (becomes a structure in 3.0)
975    },
976    publicationDisplayDate => { # (3.0)
977        List => 'Bag',
978        Struct => \%prismPublicationDate,
979    },
980    publicationName => { },
981    publishingFrequency => { }, # (3.0)
982    rating          => { },
983    # rightsAgent     => { }, # (deprecated in 3.0)
984    samplePageRange => { }, # (3.0)
985    section         => { },
986    sellingAgency   => { }, # (3.0)
987    seriesNumber    => { Writable => 'integer' }, # (3.0)
988    seriesTitle     => { }, # (3.0)
989    sport           => { }, # (3.0)
990    startingPage    => { },
991    subsection1     => { },
992    subsection2     => { },
993    subsection3     => { },
994    subsection4     => { },
995    subtitle        => { }, # (3.0)
996    supplementDisplayID => { }, # (3.0)
997    supplementStartingPage => { }, # (3.0)
998    supplementTitle => { }, # (3.0)
999    teaser          => { List => 'Bag' },
1000    ticker          => { List => 'Bag' },
1001    timePeriod      => { },
1002    url             => {
1003        Name => 'URL',
1004        List => 'Bag',
1005        Struct => { # (becomes a structure in 3.0)
1006            STRUCT_NAME => 'prismUrl',
1007            NAMESPACE   => 'prism',
1008            url         => { },
1009            'a-platform'=> { },
1010        },
1011    },
1012    uspsNumber      => { }, # (3.0)
1013    versionIdentifier => { },
1014    volume          => { },
1015    wordCount       => { Writable => 'integer' },
1016# tags that existed in version 1.3
1017#    category        => { %obsolete, List => 'Bag' },
1018#    hasFormat       => { %obsolete, List => 'Bag' },
1019#    hasPart         => { %obsolete, List => 'Bag' },
1020#    isFormatOf      => { %obsolete, List => 'Bag' },
1021#    isPartOf        => { %obsolete },
1022#    isReferencedBy  => { %obsolete, List => 'Bag' },
1023#    isRequiredBy    => { %obsolete, List => 'Bag' },
1024#    isVersionOf     => { %obsolete },
1025#    objectTitle     => { %obsolete, List => 'Bag' },
1026#    receptionDate   => { %obsolete },
1027#    references      => { %obsolete, List => 'Bag' },
1028#    requires        => { %obsolete, List => 'Bag' },
1029# tags in older versions
1030#    page
1031#    contentLength
1032#    creationTime
1033#    expirationTime
1034#    hasVersion
1035#    isAlternativeFor
1036#    isBasedOn
1037#    isBasisFor
1038#    modificationTime
1039#    publicationTime
1040#    receptionTime
1041#    releaseTime
1042);
1043
1044# PRISM Rights Language namespace (prl) (ref 2)
1045%Image::ExifTool::XMP::prl = (
1046    %xmpTableDefaults,
1047    GROUPS => { 0 => 'XMP', 1 => 'XMP-prl', 2 => 'Document' },
1048    NAMESPACE => 'prl',
1049    AVOID => 1,
1050    NOTES => q{
1051        PRISM Rights Language 2.1 namespace tags.  These tags have been deprecated
1052        since the release of the PRISM Usage Rights 3.0. (see
1053        L<http://www.prismstandard.org/>)
1054    },
1055    geography       => { List => 'Bag' },
1056    industry        => { List => 'Bag' },
1057    usage           => { List => 'Bag' },
1058);
1059
1060# PRISM Usage Rights namespace (prismusagerights) (ref 2)
1061%Image::ExifTool::XMP::pur = (
1062    %xmpTableDefaults,
1063    GROUPS => { 0 => 'XMP', 1 => 'XMP-pur', 2 => 'Document' },
1064    NAMESPACE => 'pur',
1065    AVOID => 1,
1066    NOTES => q{
1067        PRISM Usage Rights 3.0 namespace tags.  (see
1068        L<http://www.prismstandard.org/>)
1069    },
1070    adultContentWarning => { List => 'Bag' },
1071    agreement           => { List => 'Bag' },
1072    copyright           => {
1073        # (not clear in 3.0 spec, which lists only "bag Text", and called
1074        #  "copyrightDate" instead of "copyright" the PRISM basic 3.0 spec)
1075        Writable => 'lang-alt',
1076        Groups => { 2 => 'Author' },
1077    },
1078    creditLine          => { List => 'Bag' },
1079    embargoDate         => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} },
1080    exclusivityEndDate  => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} },
1081    expirationDate      => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} },
1082    imageSizeRestriction=> { },
1083    optionEndDate       => { List => 'Bag', %dateTimeInfo, Groups => { 2 => 'Time'} },
1084    permissions         => { List => 'Bag' },
1085    restrictions        => { List => 'Bag' },
1086    reuseProhibited     => { Writable => 'boolean' },
1087    rightsAgent         => { },
1088    rightsOwner         => { },
1089    # usageFee            => { List => 'Bag' }, # (not in 3.0)
1090);
1091
1092# PRISM Metadata for Images namespace (pmi) (ref 2)
1093%Image::ExifTool::XMP::pmi = (
1094    %xmpTableDefaults,
1095    GROUPS => { 0 => 'XMP', 1 => 'XMP-pmi', 2 => 'Image' },
1096    NAMESPACE => 'pmi',
1097    AVOID => 1,
1098    NOTES => q{
1099        PRISM Metadata for Images 3.0 namespace tags.  (see
1100        L<http://www.prismstandard.org/>)
1101    },
1102    color => {
1103        PrintConv => {
1104            bw => 'BW',
1105            color => 'Color',
1106            sepia => 'Sepia',
1107            duotone => 'Duotone',
1108            tritone => 'Tritone',
1109            quadtone => 'Quadtone',
1110        },
1111    },
1112    contactInfo     => { },
1113    displayName     => { },
1114    distributorProductID => { },
1115    eventAlias      => { },
1116    eventEnd        => { },
1117    eventStart      => { },
1118    eventSubtype    => { },
1119    eventType       => { },
1120    field           => { },
1121    framing         => { },
1122    location        => { },
1123    make            => { },
1124    manufacturer    => { },
1125    model           => { },
1126    modelYear       => { },
1127    objectDescription=>{ },
1128    objectSubtype   => { },
1129    objectType      => { },
1130    orientation => {
1131        PrintConv => {
1132            horizontal => 'Horizontal',
1133            vertical => 'Vertical',
1134        }
1135    },
1136    positionDescriptor => { },
1137    productID       => { },
1138    productIDType   => { },
1139    season => {
1140        PrintConv => {
1141            spring => 'Spring',
1142            summer => 'Summer',
1143            fall => 'Fall',
1144            winter => 'Winter',
1145        },
1146    },
1147    sequenceName    => { },
1148    sequenceNumber  => { },
1149    sequenceTotalNumber => { },
1150    setting         => { },
1151    shootID         => { },
1152    slideshowName   => { },
1153    slideshowNumber => { Writable => 'integer' },
1154    slideshowTotalNumber => { Writable => 'integer' },
1155    viewpoint       => { },
1156    visualTechnique => { },
1157);
1158
1159# PRISM Recipe Metadata (prm) (ref 2)
1160%Image::ExifTool::XMP::prm = (
1161    %xmpTableDefaults,
1162    GROUPS => { 0 => 'XMP', 1 => 'XMP-prm', 2 => 'Document' },
1163    NAMESPACE => 'prm',
1164    AVOID => 1,
1165    NOTES => q{
1166        PRISM Recipe Metadata 3.0 namespace tags.  (see
1167        L<http://www.prismstandard.org/>)
1168    },
1169    cookingEquipment    => { },
1170    cookingMethod       => { },
1171    course              => { },
1172    cuisine             => { },
1173    dietaryNeeds        => { },
1174    dishType            => { },
1175    duration            => { },
1176    ingredientExclusion => { },
1177    mainIngredient      => { },
1178    meal                => { },
1179    recipeEndingPage    => { },
1180    recipePageRange     => { },
1181    recipeSource        => { },
1182    recipeStartingPage  => { },
1183    recipeTitle         => { },
1184    servingSize         => { },
1185    skillLevel          => { },
1186    specialOccasion     => { },
1187    yield               => { },
1188);
1189
1190#------------------------------------------------------------------------------
1191
1192# DICOM namespace properties (DICOM) (ref PH, written by CS3)
1193%Image::ExifTool::XMP::DICOM = (
1194    %xmpTableDefaults,
1195    GROUPS => { 1 => 'XMP-DICOM', 2 => 'Image' },
1196    NAMESPACE => 'DICOM',
1197    NOTES => q{
1198        DICOM namespace tags.  These XMP tags allow some DICOM information to be
1199        stored in files of other than DICOM format.  See the
1200        L<DICOM Tags documentation|Image::ExifTool::TagNames/DICOM Tags> for a list
1201        of tags available in DICOM-format files.
1202    },
1203    # change some tag names to correspond with DICOM tags
1204    PatientName             => { },
1205    PatientID               => { },
1206    PatientSex              => { },
1207    PatientDOB => {
1208        Name => 'PatientBirthDate',
1209        Groups => { 2 => 'Time' },
1210        %dateTimeInfo,
1211    },
1212    StudyID                 => { },
1213    StudyPhysician          => { },
1214    StudyDateTime           => { Groups => { 2 => 'Time' }, %dateTimeInfo },
1215    StudyDescription        => { },
1216    SeriesNumber            => { },
1217    SeriesModality          => { },
1218    SeriesDateTime          => { Groups => { 2 => 'Time' }, %dateTimeInfo },
1219    SeriesDescription       => { },
1220    EquipmentInstitution    => { },
1221    EquipmentManufacturer   => { },
1222);
1223
1224# PixelLive namespace properties (PixelLive) (ref 3)
1225%Image::ExifTool::XMP::PixelLive = (
1226    GROUPS => { 1 => 'XMP-PixelLive', 2 => 'Image' },
1227    NAMESPACE => 'PixelLive',
1228    AVOID => 1,
1229    NOTES => q{
1230        PixelLive namespace tags.  These tags are not writable because they are very
1231        uncommon and I haven't been able to locate a reference which gives the
1232        namespace URI.
1233    },
1234    AUTHOR    => { Name => 'Author',    Groups => { 2 => 'Author' } },
1235    COMMENTS  => { Name => 'Comments' },
1236    COPYRIGHT => { Name => 'Copyright', Groups => { 2 => 'Author' } },
1237    DATE      => { Name => 'Date',      Groups => { 2 => 'Time' } },
1238    GENRE     => { Name => 'Genre' },
1239    TITLE     => { Name => 'Title' },
1240);
1241
1242# Extensis Portfolio tags (extensis) (ref 11)
1243%Image::ExifTool::XMP::extensis = (
1244    %xmpTableDefaults,
1245    GROUPS => { 1 => 'XMP-extensis', 2 => 'Image' },
1246    NAMESPACE => 'extensis',
1247    NOTES => 'Tags used by Extensis Portfolio.',
1248    Approved     => { Writable => 'boolean' },
1249    ApprovedBy   => { },
1250    ClientName   => { },
1251    JobName      => { },
1252    JobStatus    => { },
1253    RoutedTo     => { },
1254    RoutingNotes => { },
1255    WorkToDo     => { },
1256);
1257
1258# IDimager structures (ref PH)
1259my %sTagStruct;
1260%sTagStruct = (
1261    STRUCT_NAME => 'TagStructure',
1262    NAMESPACE => 'ics',
1263    LabelName => { },
1264    Reference => { },
1265    ParentReference => { },
1266    SubLabels => { Struct => \%sTagStruct, List => 'Bag' },
1267);
1268my %sSubVersion = (
1269    STRUCT_NAME => 'SubVersion',
1270    NAMESPACE => 'ics',
1271    VersRef => { },
1272    FileName => { },
1273);
1274
1275# IDimager namespace (ics) (ref PH)
1276%Image::ExifTool::XMP::ics = (
1277    %xmpTableDefaults,
1278    GROUPS => { 0 => 'XMP', 1 => 'XMP-ics', 2 => 'Image' },
1279    NAMESPACE => 'ics',
1280    NOTES => q{
1281        Tags used by IDimager.  Nested TagStructure structures are unrolled to an
1282        arbitrary depth of 6 to avoid infinite recursion.
1283    },
1284    ImageRef => { },
1285    TagStructure => { Struct => \%sTagStruct, List => 'Bag' },
1286    TagStructureLabelName => { Name => 'LabelName1', Flat => 1 },
1287    TagStructureReference => { Name => 'Reference1', Flat => 1 },
1288    TagStructureSubLabels => { Name => 'SubLabels1', Flat => 1 },
1289    TagStructureParentReference => { Name => 'ParentReference1', Flat => 1 },
1290    TagStructureSubLabelsLabelName => { Name => 'LabelName2', Flat => 1 },
1291    TagStructureSubLabelsReference => { Name => 'Reference2', Flat => 1 },
1292    TagStructureSubLabelsSubLabels => { Name => 'SubLabels2', Flat => 1 },
1293    TagStructureSubLabelsParentReference => { Name => 'ParentReference2', Flat => 1 },
1294    TagStructureSubLabelsSubLabelsLabelName => { Name => 'LabelName3', Flat => 1 },
1295    TagStructureSubLabelsSubLabelsReference => { Name => 'Reference3', Flat => 1 },
1296    TagStructureSubLabelsSubLabelsSubLabels => { Name => 'SubLabels3', Flat => 1 },
1297    TagStructureSubLabelsSubLabelsParentReference => { Name => 'ParentReference3', Flat => 1 },
1298    TagStructureSubLabelsSubLabelsSubLabelsLabelName => { Name => 'LabelName4', Flat => 1 },
1299    TagStructureSubLabelsSubLabelsSubLabelsReference => { Name => 'Reference4', Flat => 1 },
1300    TagStructureSubLabelsSubLabelsSubLabelsSubLabels => { Name => 'SubLabels4', Flat => 1 },
1301    TagStructureSubLabelsSubLabelsSubLabelsParentReference => { Name => 'ParentReference4', Flat => 1 },
1302    TagStructureSubLabelsSubLabelsSubLabelsSubLabelsLabelName => { Name => 'LabelName5', Flat => 1 },
1303    TagStructureSubLabelsSubLabelsSubLabelsSubLabelsReference => { Name => 'Reference5', Flat => 1 },
1304    TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabels => { Name => 'SubLabels5', Flat => 1, NoSubStruct => 1 }, # break infinite recursion
1305    TagStructureSubLabelsSubLabelsSubLabelsSubLabelsParentReference => { Name => 'ParentReference5', Flat => 1 },
1306    TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabelsLabelName => { Name => 'LabelName6', Flat => 1 },
1307    TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabelsReference => { Name => 'Reference6', Flat => 1 },
1308    TagStructureSubLabelsSubLabelsSubLabelsSubLabelsSubLabelsParentReference => { Name => 'ParentReference6', Flat => 1 },
1309    SubVersions => { Struct => \%sSubVersion, List => 'Bag' },
1310    SubVersionsVersRef => { Name => 'SubVersionReference', Flat => 1 },
1311    SubVersionsFileName => { Name => 'SubVersionFileName', Flat => 1 },
1312    TimeStamp  => { Avoid => 1, Groups => { 2 => 'Time' }, %dateTimeInfo },
1313    AppVersion => { Avoid => 1 },
1314);
1315
1316# ACDSee namespace (acdsee) (ref PH)
1317%Image::ExifTool::XMP::acdsee = (
1318    %xmpTableDefaults,
1319    GROUPS => { 0 => 'XMP', 1 => 'XMP-acdsee', 2 => 'Image' },
1320    NAMESPACE => 'acdsee',
1321    AVOID => 1,
1322    NOTES => q{
1323        ACD Systems ACDSee namespace tags.
1324
1325        (A note to software developers: Re-inventing your own private tags instead
1326        of using the equivalent tags in standard XMP namespaces defeats one of the
1327        most valuable features of metadata: interoperability.  Your applications
1328        mumble to themselves instead of speaking out for the rest of the world to
1329        hear.)
1330    },
1331    author     => { Groups => { 2 => 'Author' } },
1332    caption    => { },
1333    categories => { },
1334    collections=> { },
1335    datetime   => { Name => 'DateTime', Groups => { 2 => 'Time' }, %dateTimeInfo },
1336    keywords   => { List => 'Bag' },
1337    notes      => { },
1338    rating     => { Writable => 'real' }, # integer?
1339    tagged     => { Writable => 'boolean' },
1340    rawrppused => { Writable => 'boolean' },
1341    rpp => {
1342        Name => 'RPP',
1343        Writable => 'lang-alt',
1344        Notes => 'raw processing settings in XML format',
1345        Binary => 1,
1346    },
1347    dpp => {
1348        Name => 'DPP',
1349        Writable => 'lang-alt',
1350        Notes => 'newer version of XML raw processing settings',
1351        Binary => 1,
1352    },
1353    # more tags (ref forum6840)
1354    FixtureIdentifier   => { },
1355    EditStatus          => { },
1356    ReleaseDate         => { },
1357    ReleaseTime         => { },
1358    OriginatingProgram  => { },
1359    ObjectCycle         => { },
1360    Snapshots           => { List => 'Bag', Binary => 1 },
1361);
1362
1363# Picture Licensing Universal System namespace properties (xmpPLUS)
1364%Image::ExifTool::XMP::xmpPLUS = (
1365    %xmpTableDefaults,
1366    GROUPS => { 1 => 'XMP-xmpPLUS', 2 => 'Author' },
1367    NAMESPACE => 'xmpPLUS',
1368    AVOID => 1,
1369    NOTES => q{
1370        XMP Picture Licensing Universal System (PLUS) tags as written by some older
1371        Adobe applications.  See L<PLUS XMP Tags|Image::ExifTool::TagNames/PLUS XMP Tags>
1372        for the current PLUS tags.
1373    },
1374    CreditLineReq   => { Writable => 'boolean' },
1375    ReuseAllowed    => { Writable => 'boolean' },
1376);
1377
1378# Creative Commons namespace properties (cc) (ref 5)
1379%Image::ExifTool::XMP::cc = (
1380    %xmpTableDefaults,
1381    GROUPS => { 1 => 'XMP-cc', 2 => 'Author' },
1382    NAMESPACE => 'cc',
1383    NOTES => q{
1384        Creative Commons namespace tags.  Note that the CC specification for XMP is
1385        non-existent, so ExifTool must make some assumptions about the format of the
1386        specific properties in XMP (see L<http://creativecommons.org/ns>).
1387    },
1388    # Work properties
1389    license         => { Resource => 1 },
1390    attributionName => { },
1391    attributionURL  => { Resource => 1 },
1392    morePermissions => { Resource => 1 },
1393    useGuidelines   => { Resource => 1 },
1394    # License properties
1395    permits => {
1396        List => 'Bag',
1397        Resource => 1,
1398        PrintConv => {
1399            'cc:Sharing' => 'Sharing',
1400            'cc:DerivativeWorks' => 'Derivative Works',
1401            'cc:Reproduction' => 'Reproduction',
1402            'cc:Distribution' => 'Distribution',
1403        },
1404    },
1405    requires => {
1406        List => 'Bag',
1407        Resource => 1,
1408        PrintConv => {
1409            'cc:Copyleft' => 'Copyleft',
1410            'cc:LesserCopyleft' => 'Lesser Copyleft',
1411            'cc:SourceCode' => 'Source Code',
1412            'cc:ShareAlike' => 'Share Alike',
1413            'cc:Notice' => 'Notice',
1414            'cc:Attribution' => 'Attribution',
1415        },
1416    },
1417    prohibits => {
1418        List => 'Bag',
1419        Resource => 1,
1420        PrintConv => {
1421            'cc:HighIncomeNationUse' => 'High Income Nation Use',
1422            'cc:CommercialUse' => 'Commercial Use',
1423        },
1424    },
1425    jurisdiction    => { Resource => 1 },
1426    legalcode       => { Name => 'LegalCode', Resource => 1 },
1427    deprecatedOn    => { %dateTimeInfo, Groups => { 2 => 'Time' } },
1428);
1429
1430# Description Explorer namespace properties (dex) (ref 6)
1431%Image::ExifTool::XMP::dex = (
1432    %xmpTableDefaults,
1433    GROUPS => { 1 => 'XMP-dex', 2 => 'Image' },
1434    NAMESPACE => 'dex',
1435    NOTES => q{
1436        Description Explorer namespace tags.  These tags are not very common.  The
1437        Source and Rating tags are avoided when writing due to name conflicts with
1438        other XMP tags.  (see L<http://www.optimasc.com/products/fileid/>)
1439    },
1440    crc32       => { Name => 'CRC32', Writable => 'integer' },
1441    source      => { Avoid => 1 },
1442    shortdescription => {
1443        Name => 'ShortDescription',
1444        Writable => 'lang-alt',
1445    },
1446    licensetype => {
1447        Name => 'LicenseType',
1448        PrintConv => {
1449            unknown        => 'Unknown',
1450            shareware      => 'Shareware',
1451            freeware       => 'Freeware',
1452            adware         => 'Adware',
1453            demo           => 'Demo',
1454            commercial     => 'Commercial',
1455           'public domain' => 'Public Domain',
1456           'open source'   => 'Open Source',
1457        },
1458    },
1459    revision    => { },
1460    rating      => { Avoid => 1 },
1461    os          => { Name => 'OS', Writable => 'integer' },
1462    ffid        => { Name => 'FFID' },
1463);
1464
1465# iView MediaPro namespace properties (mediapro) (ref PH)
1466%Image::ExifTool::XMP::MediaPro = (
1467    %xmpTableDefaults,
1468    GROUPS => { 1 => 'XMP-mediapro', 2 => 'Image' },
1469    NAMESPACE => 'mediapro',
1470    NOTES => 'iView MediaPro namespace tags.',
1471    Event       => {
1472        Avoid => 1,
1473        Notes => 'avoided due to conflict with XMP-iptcExt:Event',
1474    },
1475    Location    => {
1476        Avoid => 1,
1477        Groups => { 2 => 'Location' },
1478        Notes => 'avoided due to conflict with XMP-iptcCore:Location',
1479    },
1480    Status      => { },
1481    People      => { List => 'Bag' },
1482    UserFields  => { List => 'Bag' },
1483    CatalogSets => { List => 'Bag' },
1484);
1485
1486# Microsoft ExpressionMedia namespace properties (expressionmedia)
1487# (ref https://exiftool.org/forum/index.php/topic,4235.0.html)
1488%Image::ExifTool::XMP::ExpressionMedia = (
1489    %xmpTableDefaults,
1490    GROUPS => { 1 => 'XMP-expressionmedia', 2 => 'Image' },
1491    NAMESPACE => 'expressionmedia',
1492    AVOID => 1,
1493    NOTES => q{
1494        Microsoft Expression Media namespace tags.  These tags are avoided when
1495        writing due to name conflicts with tags in other schemas.
1496    },
1497    Event       => { },
1498    Status      => { },
1499    People      => { List => 'Bag' },
1500    CatalogSets => { List => 'Bag' },
1501);
1502
1503# DigiKam namespace tags (ref PH)
1504%Image::ExifTool::XMP::digiKam = (
1505    %xmpTableDefaults,
1506    GROUPS => { 1 => 'XMP-digiKam', 2 => 'Image' },
1507    NAMESPACE => 'digiKam',
1508    NOTES => 'DigiKam namespace tags.',
1509    CaptionsAuthorNames    => { Writable => 'lang-alt' },
1510    CaptionsDateTimeStamps => { Writable => 'lang-alt', Groups => { 2 => 'Time' } },
1511    TagsList               => { List => 'Seq' },
1512    ColorLabel             => { },
1513    PickLabel              => { },
1514    ImageHistory           => { Avoid => 1, Notes => 'different format from EXIF:ImageHistory' },
1515    LensCorrectionSettings => { },
1516    ImageUniqueID          => { Avoid => 1 },
1517);
1518
1519# SWF namespace tags (ref PH)
1520%Image::ExifTool::XMP::swf = (
1521    %xmpTableDefaults,
1522    GROUPS => { 1 => 'XMP-swf', 2 => 'Image' },
1523    NAMESPACE => 'swf',
1524    NOTES => 'Adobe SWF namespace tags.',
1525    type         => { Avoid => 1 },
1526    bgalpha      => { Name => 'BackgroundAlpha', Writable => 'integer' },
1527    forwardlock  => { Name => 'ForwardLock',     Writable => 'boolean' },
1528    maxstorage   => { Name => 'MaxStorage',      Writable => 'integer' }, # (CS5)
1529);
1530
1531# Sony Ericsson cell phone location tags
1532# refs: http://www.opencellid.org/api
1533# http://zonetag.research.yahoo.com/faq_location.php
1534# http://www.cs.columbia.edu/sip/drafts/LIF%20TS%20101%20v2.0.0.pdf
1535%Image::ExifTool::XMP::cell = (
1536    %xmpTableDefaults,
1537    GROUPS => { 1 => 'XMP-cell', 2 => 'Location' },
1538    NAMESPACE => 'cell',
1539    NOTES => 'Location tags written by some Sony Ericsson phones.',
1540    mcc     => { Name => 'MobileCountryCode' },
1541    mnc     => { Name => 'MobileNetworkCode' },
1542    lac     => { Name => 'LocationAreaCode' },
1543    cellid  => { Name => 'CellTowerID' },
1544    cgi     => { Name => 'CellGlobalID' },
1545    r       => { Name => 'CellR' }, # (what is this? Radius?)
1546);
1547
1548# Apple adjustment settings (ref PH)
1549%Image::ExifTool::XMP::aas = (
1550    %xmpTableDefaults,
1551    GROUPS => { 1 => 'XMP-aas', 2 => 'Image' },
1552    NAMESPACE => 'aas',
1553    NOTES => 'Apple Adjustment Settings used by iPhone/iPad.',
1554    CropX      => { Writable => 'integer', Avoid => 1 },
1555    CropY      => { Writable => 'integer', Avoid => 1 },
1556    CropW      => { Writable => 'integer', Avoid => 1 },
1557    CropH      => { Writable => 'integer', Avoid => 1 },
1558    AffineA    => { Writable => 'real' },
1559    AffineB    => { Writable => 'real' },
1560    AffineC    => { Writable => 'real' },
1561    AffineD    => { Writable => 'real' },
1562    AffineX    => { Writable => 'real' },
1563    AffineY    => { Writable => 'real' },
1564    Vibrance   => { Writable => 'real', Avoid => 1 },
1565    Curve0x    => { Writable => 'real' },
1566    Curve0y    => { Writable => 'real' },
1567    Curve1x    => { Writable => 'real' },
1568    Curve1y    => { Writable => 'real' },
1569    Curve2x    => { Writable => 'real' },
1570    Curve2y    => { Writable => 'real' },
1571    Curve3x    => { Writable => 'real' },
1572    Curve3y    => { Writable => 'real' },
1573    Curve4x    => { Writable => 'real' },
1574    Curve4y    => { Writable => 'real' },
1575    Shadows    => { Writable => 'real', Avoid => 1 },
1576    Highlights => { Writable => 'real', Avoid => 1 },
1577    # the following from StarGeek
1578    FaceBalanceOrigI    => { Writable => 'real' },
1579    FaceBalanceOrigQ    => { Writable => 'real' },
1580    FaceBalanceStrength => { Writable => 'real' },
1581    FaceBalanceWarmth   => { Writable => 'real' },
1582);
1583
1584# Adobe creatorAtom properties (ref PH)
1585%Image::ExifTool::XMP::creatorAtom = (
1586    %xmpTableDefaults,
1587    GROUPS => { 1 => 'XMP-creatorAtom', 2 => 'Image' },
1588    NAMESPACE => 'creatorAtom',
1589    NOTES => 'Adobe creatorAtom tags, written by After Effects.',
1590    macAtom => {
1591        Struct => {
1592            STRUCT_NAME => 'MacAtom',
1593            NAMESPACE   => 'creatorAtom',
1594            applicationCode      => { },
1595            invocationAppleEvent => { },
1596            posixProjectPath     => { },
1597        },
1598    },
1599    windowsAtom => {
1600        Struct => {
1601            STRUCT_NAME => 'WindowsAtom',
1602            NAMESPACE   => 'creatorAtom',
1603            extension       => { },
1604            invocationFlags => { },
1605            uncProjectPath  => { },
1606        },
1607    },
1608    aeProjectLink => { # (After Effects Project Link)
1609        Struct => {
1610            STRUCT_NAME => 'AEProjectLink',
1611            NAMESPACE   => 'creatorAtom',
1612            renderTimeStamp         => { Writable => 'integer' },
1613            compositionID           => { },
1614            renderQueueItemID       => { },
1615            renderOutputModuleIndex => { },
1616            fullPath                => { },
1617        },
1618    },
1619);
1620
1621# FastPictureViewer namespace properties (http://www.fastpictureviewer.com/help/#rtfcomments)
1622%Image::ExifTool::XMP::fpv = (
1623    %xmpTableDefaults,
1624    GROUPS => { 1 => 'XMP-fpv', 2 => 'Image' },
1625    NAMESPACE => 'fpv',
1626    NOTES => q{
1627        Fast Picture Viewer tags (see
1628        L<http://www.fastpictureviewer.com/help/#rtfcomments>).
1629    },
1630    RichTextComment => { },
1631);
1632
1633# Apple FaceInfo namespace properties (ref PH)
1634%Image::ExifTool::XMP::apple_fi = (
1635    %xmpTableDefaults,
1636    GROUPS => { 1 => 'XMP-apple-fi', 2 => 'Image' },
1637    NAMESPACE => 'apple-fi',
1638    NOTES => q{
1639        Face information tags written by the Apple iPhone 5 inside the mwg-rs
1640        RegionExtensions.
1641    },
1642    Timestamp => {
1643        Name => 'TimeStamp',
1644        Writable => 'integer',
1645        # (don't know how to convert this)
1646    },
1647    FaceID          => { Writable => 'integer' },
1648    AngleInfoRoll   => { Writable => 'integer' },
1649    AngleInfoYaw    => { Writable => 'integer' },
1650    ConfidenceLevel => { Writable => 'integer' },
1651);
1652
1653# Google audio namespace
1654%Image::ExifTool::XMP::GAudio = (
1655    %xmpTableDefaults,
1656    GROUPS => { 1 => 'XMP-GAudio', 2 => 'Audio' },
1657    NAMESPACE => 'GAudio',
1658    Data => {
1659        Name => 'AudioData',
1660        ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
1661        ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
1662    },
1663    Mime => { Name => 'AudioMimeType' },
1664);
1665
1666# Google image namespace
1667%Image::ExifTool::XMP::GImage = (
1668    %xmpTableDefaults,
1669    GROUPS => { 1 => 'XMP-GImage', 2 => 'Image' },
1670    NAMESPACE => 'GImage',
1671    Data => {
1672        Name => 'ImageData',
1673        ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
1674        ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
1675    },
1676    Mime => { Name => 'ImageMimeType' },
1677);
1678
1679# Google panorama namespace properties
1680# (ref https://exiftool.org/forum/index.php/topic,4569.0.html)
1681%Image::ExifTool::XMP::GPano = (
1682    %xmpTableDefaults,
1683    GROUPS => { 1 => 'XMP-GPano', 2 => 'Image' },
1684    NAMESPACE => 'GPano',
1685    NOTES => q{
1686        Panorama tags written by Google Photosphere. See
1687        L<https://developers.google.com/panorama/metadata/> for the specification.
1688    },
1689    UsePanoramaViewer               => { Writable => 'boolean' },
1690    CaptureSoftware                 => { },
1691    StitchingSoftware               => { },
1692    ProjectionType                  => { },
1693    PoseHeadingDegrees              => { Writable => 'real' },
1694    PosePitchDegrees                => { Writable => 'real' },
1695    PoseRollDegrees                 => { Writable => 'real' },
1696    InitialViewHeadingDegrees       => { Writable => 'real' },
1697    InitialViewPitchDegrees         => { Writable => 'real' },
1698    InitialViewRollDegrees          => { Writable => 'real' },
1699    InitialHorizontalFOVDegrees     => { Writable => 'real' },
1700    InitialVerticalFOVDegrees       => { Writable => 'real' },
1701    FirstPhotoDate                  => { %dateTimeInfo, Groups => { 2 => 'Time' } },
1702    LastPhotoDate                   => { %dateTimeInfo, Groups => { 2 => 'Time' } },
1703    SourcePhotosCount               => { Writable => 'integer' },
1704    ExposureLockUsed                => { Writable => 'boolean' },
1705    CroppedAreaImageWidthPixels     => { Writable => 'real' },
1706    CroppedAreaImageHeightPixels    => { Writable => 'real' },
1707    FullPanoWidthPixels             => { Writable => 'real' },
1708    FullPanoHeightPixels            => { Writable => 'real' },
1709    CroppedAreaLeftPixels           => { Writable => 'real' },
1710    CroppedAreaTopPixels            => { Writable => 'real' },
1711    InitialCameraDolly              => { Writable => 'real' },
1712    # (the following have been observed, but are not in the specification)
1713    LargestValidInteriorRectLeft    => { Writable => 'real' },
1714    LargestValidInteriorRectTop     => { Writable => 'real' },
1715    LargestValidInteriorRectWidth   => { Writable => 'real' },
1716    LargestValidInteriorRectHeight  => { Writable => 'real' },
1717);
1718
1719# Google Spherical Images namespace (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-rfc.md)
1720%Image::ExifTool::XMP::GSpherical = (
1721    %xmpTableDefaults,
1722    GROUPS => { 1 => 'XMP-GSpherical', 2 => 'Image' },
1723    WRITE_GROUP => 'GSpherical', # write in special location for video files
1724    NAMESPACE => 'GSpherical',
1725    AVOID => 1,
1726    NOTES => q{
1727        Not actually XMP.  These RDF/XML tags are used in Google spherical MP4
1728        videos.  These tags are written into the video track of MOV/MP4 files, and
1729        not at the top level like other XMP tags.  See
1730        L<https://github.com/google/spatial-media/blob/master/docs/spherical-video-rfc.md>
1731        for the specification.
1732    },
1733    # (avoid due to conflicts with XMP-GPano tags)
1734    Spherical                   => { Writable => 'boolean' },
1735    Stitched                    => { Writable => 'boolean' },
1736    StitchingSoftware           => { },
1737    ProjectionType              => { },
1738    StereoMode                  => { },
1739    SourceCount                 => { Writable => 'integer' },
1740    InitialViewHeadingDegrees   => { Writable => 'real' },
1741    InitialViewPitchDegrees     => { Writable => 'real' },
1742    InitialViewRollDegrees      => { Writable => 'real' },
1743    Timestamp                   => {
1744        Name => 'TimeStamp',
1745        Groups => { 2 => 'Time' },
1746        Writable => 'integer',
1747        Shift => 'Time',
1748        ValueConv => 'ConvertUnixTime($val)', #(NC)
1749        ValueConvInv => 'GetUnixTime($val)',
1750        PrintConv => '$self->ConvertDateTime($val)',
1751        PrintConvInv => '$self->InverseDateTime($val)',
1752    },
1753    FullPanoWidthPixels         => { Writable => 'integer' },
1754    FullPanoHeightPixels        => { Writable => 'integer' },
1755    CroppedAreaImageWidthPixels => { Writable => 'integer' },
1756    CroppedAreaImageHeightPixels=> { Writable => 'integer' },
1757    CroppedAreaLeftPixels       => { Writable => 'integer' },
1758    CroppedAreaTopPixels        => { Writable => 'integer' },
1759);
1760
1761# Google depthmap information (ref https://developers.google.com/depthmap-metadata/reference)
1762%Image::ExifTool::XMP::GDepth = (
1763    GROUPS      => { 0 => 'XMP', 1 => 'XMP-GDepth', 2 => 'Image' },
1764    NAMESPACE   => 'GDepth',
1765    AVOID       => 1, # (too many potential tag name conflicts)
1766    NOTES       => q{
1767        Google depthmap information. See
1768        L<https://developers.google.com/depthmap-metadata/> for the specification.
1769    },
1770    WRITABLE    => 'string', # (default to string-type tags)
1771    PRIORITY    => 0,
1772    Format => {
1773        PrintConv => {
1774            RangeInverse => 'RangeInverse',
1775            RangeLinear  => 'RangeLinear',
1776        },
1777    },
1778    Near        => { Writable => 'real' },
1779    Far         => { Writable => 'real' },
1780    Mime        => { },
1781    Data => {
1782        Name => 'DepthImage',
1783        ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
1784        ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
1785    },
1786    Units       => { },
1787    MeasureType => {
1788        PrintConv => {
1789            OpticalAxis => 'OpticalAxis',
1790            OpticalRay  => 'OpticalRay',
1791        },
1792    },
1793    ConfidenceMime  => { },
1794    Confidence => {
1795        ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
1796        ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
1797    },
1798    Manufacturer=> { },
1799    Model       => { },
1800    Software    => { },
1801    ImageWidth  => { Writable => 'real' },
1802    ImageHeight => { Writable => 'real' },
1803);
1804
1805# Google focus namespace
1806%Image::ExifTool::XMP::GFocus = (
1807    %xmpTableDefaults,
1808    GROUPS => { 1 => 'XMP-GFocus', 2 => 'Image' },
1809    NAMESPACE => 'GFocus',
1810    NOTES => 'Focus information found in Google depthmap images.',
1811    BlurAtInfinity  => { Writable => 'real' },
1812    FocalDistance   => { Writable => 'real' },
1813    FocalPointX     => { Writable => 'real' },
1814    FocalPointY     => { Writable => 'real' },
1815);
1816
1817# Google camera namespace (ref PH)
1818%Image::ExifTool::XMP::GCamera = (
1819    %xmpTableDefaults,
1820    GROUPS => { 1 => 'XMP-GCamera', 2 => 'Camera' },
1821    NAMESPACE => 'GCamera',
1822    NOTES => 'Camera information found in Google panorama images.',
1823    BurstID         => { },
1824    BurstPrimary    => { },
1825    PortraitNote    => { },
1826    PortraitRequest => {
1827        Notes => 'High Definition Render Pipeline (HDRP) data', #PH (guess)
1828        ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
1829        ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
1830    },
1831    PortraitVersion => { },
1832    SpecialTypeID   => { List => 'Bag' },
1833    PortraitNote    => { },
1834    DisableAutoCreation => { List => 'Bag' },
1835    hdrp_makernote => {
1836        Name => 'HDRPMakerNote',
1837        # decoded data starts with the following bytes, but nothing yet is known about its contents:
1838        # 48 44 52 50 02 ef 64 35 6d 5e 70 1e 2c ea e3 4c [HDRP..d5m^p.,..L]
1839        ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
1840        ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
1841    },
1842    MicroVideo          => { Writable => 'integer' },
1843    MicroVideoVersion   => { Writable => 'integer' },
1844    MicroVideoOffset    => { Writable => 'integer' },
1845    MicroVideoPresentationTimestampUs => { Writable => 'integer' },
1846);
1847
1848# Google creations namespace (ref PH)
1849%Image::ExifTool::XMP::GCreations = (
1850    %xmpTableDefaults,
1851    GROUPS => { 1 => 'XMP-GCreations', 2 => 'Camera' },
1852    NAMESPACE => 'GCreations',
1853    NOTES => 'Google creations tags.',
1854    CameraBurstID  => { },
1855);
1856
1857# Google depth-map Device namespace (ref 13)
1858%Image::ExifTool::XMP::Device = (
1859    %xmpTableDefaults,
1860    GROUPS => { 1 => 'XMP-Device', 2 => 'Camera' },
1861    NAMESPACE => { Device => 'http://ns.google.com/photos/dd/1.0/device/' },
1862    NOTES => q{
1863        Google depth-map Device tags.  See
1864        L<https://developer.android.com/training/camera2/Dynamic-depth-v1.0.pdf> for
1865        the specification.
1866    },
1867    Container => {
1868        Struct => {
1869            STRUCT_NAME => 'DeviceContainer',
1870            NAMESPACE   => { Container => 'http://ns.google.com/photos/dd/1.0/container/' },
1871            Directory => {
1872                List => 'Seq',
1873                Struct => {
1874                    STRUCT_NAME => 'DeviceDirectory',
1875                    NAMESPACE   => { Container => 'http://ns.google.com/photos/dd/1.0/container/' },
1876                    Item => {
1877                        Struct => {
1878                            STRUCT_NAME => 'DeviceItem',
1879                            NAMESPACE => { Item => 'http://ns.google.com/photos/dd/1.0/item/' },
1880                            Mime    => { },
1881                            Length  => { Writable => 'integer' },
1882                            Padding => { Writable => 'integer' },
1883                            DataURI => { },
1884                        },
1885                    },
1886                },
1887            }
1888        },
1889    },
1890    Profiles => {
1891        List => 'Seq',
1892        FlatName => '',
1893        Struct => {
1894            STRUCT_NAME => 'DeviceProfiles',
1895            NAMESPACE => { Device => 'http://ns.google.com/photos/dd/1.0/device/' },
1896            Profile => {
1897                Struct => {
1898                    STRUCT_NAME => 'DeviceProfile',
1899                    NAMESPACE => { Profile => 'http://ns.google.com/photos/dd/1.0/profile/' },
1900                    CameraIndices => { List => 'Seq', Writable => 'integer' },
1901                    Type => { },
1902                },
1903            },
1904        },
1905    },
1906    Cameras => {
1907        List => 'Seq',
1908        FlatName => '',
1909        Struct => {
1910            STRUCT_NAME => 'DeviceCameras',
1911            NAMESPACE => { Device => 'http://ns.google.com/photos/dd/1.0/device/' },
1912            Camera => {
1913                Struct => {
1914                    STRUCT_NAME => 'DeviceCamera',
1915                    NAMESPACE => { Camera => 'http://ns.google.com/photos/dd/1.0/camera/' },
1916                    DepthMap => {
1917                        Struct => {
1918                            STRUCT_NAME => 'DeviceDepthMap',
1919                            NAMESPACE => { DepthMap => 'http://ns.google.com/photos/dd/1.0/depthmap/' },
1920                            ConfidenceURI => { },
1921                            DepthURI    => { },
1922                            Far         => { Writable => 'real' },
1923                            Format      => { },
1924                            ItemSemantic=> { },
1925                            MeasureType => { },
1926                            Near        => { Writable => 'real' },
1927                            Units       => { },
1928                            Software    => { },
1929                            FocalTableEntryCount => { Writable => 'integer' },
1930                            FocalTable  => { }, # (base64)
1931                        },
1932                    },
1933                    Image => {
1934                        Struct => {
1935                            STRUCT_NAME => 'DeviceImage',
1936                            NAMESPACE => { Image => 'http://ns.google.com/photos/dd/1.0/image/' },
1937                            ItemSemantic=> { },
1938                            ItemURI     => { },
1939                        },
1940                    },
1941                    ImagingModel => {
1942                        Struct => {
1943                            STRUCT_NAME => 'DeviceImagingModel',
1944                            NAMESPACE => { ImagingModel => 'http://ns.google.com/photos/dd/1.0/imagingmodel/' },
1945                            Distortion      => { }, # (base64)
1946                            DistortionCount => { Writable => 'integer' },
1947                            FocalLengthX    => { Writable => 'real' },
1948                            FocalLengthY    => { Writable => 'real' },
1949                            ImageHeight     => { Writable => 'integer' },
1950                            ImageWidth      => { Writable => 'integer' },
1951                            PixelAspectRatio=> { Writable => 'real' },
1952                            PrincipalPointX => { Writable => 'real' },
1953                            PrincipalPointY => { Writable => 'real' },
1954                            Skew            => { Writable => 'real' },
1955                        },
1956                    },
1957                    PointCloud => {
1958                        Struct => {
1959                            STRUCT_NAME => 'DevicePointCloud',
1960                            NAMESPACE => { PointCloud => 'http://ns.google.com/photos/dd/1.0/pointcloud/' },
1961                            PointCloud  => { Writable => 'integer' },
1962                            Points      => { },
1963                            Metric      => { Writable => 'boolean' },
1964                        },
1965                    },
1966                    Pose => { Struct => \%sPose },
1967                    LightEstimate => {
1968                        Struct => {
1969                            STRUCT_NAME => 'DeviceLightEstimate',
1970                            NAMESPACE => { LightEstimate => 'http://ns.google.com/photos/dd/1.0/lightestimate/' },
1971                            ColorCorrectionR => { Writable => 'real' },
1972                            ColorCorrectionG => { Writable => 'real' },
1973                            ColorCorrectionB => { Writable => 'real' },
1974                            PixelIntensity   => { Writable => 'real' },
1975                        },
1976                    },
1977                    VendorInfo => { Struct => \%sVendorInfo },
1978                    AppInfo    => { Struct => \%sAppInfo },
1979                    Trait => { },
1980                },
1981            },
1982        },
1983    },
1984    VendorInfo  => { Struct => \%sVendorInfo },
1985    AppInfo     => { Struct => \%sAppInfo },
1986    EarthPos    => { Struct => \%sEarthPose },
1987    Pose        => { Struct => \%sPose },
1988    Planes => {
1989        List => 'Seq',
1990        FlatName => '',
1991        Struct => {
1992            STRUCT_NAME => 'DevicePlanes',
1993            NAMESPACE => { Device => 'http://ns.google.com/photos/dd/1.0/device/' },
1994            Plane => {
1995                Struct => {
1996                    STRUCT_NAME => 'DevicePlane',
1997                    NAMESPACE => { Plane => 'http://ns.google.com/photos/dd/1.0/plane/' },
1998                    Pose    => { Struct => \%sPose },
1999                    ExtentX => { Writable => 'real' },
2000                    ExtentZ => { Writable => 'real' },
2001                    BoundaryVertexCount => { Writable => 'integer' },
2002                    Boundary => { },
2003                },
2004            },
2005        },
2006    },
2007);
2008
2009# Getty Images namespace (ref PH)
2010%Image::ExifTool::XMP::GettyImages = (
2011    %xmpTableDefaults,
2012    GROUPS => { 1 => 'XMP-getty', 2 => 'Image' },
2013    NAMESPACE => 'GettyImagesGIFT',
2014    NOTES => q{
2015        The actual Getty Images namespace prefix is "GettyImagesGIFT", which is the
2016        prefix recorded in the file, but ExifTool shortens this for the family 1
2017        group name.
2018    },
2019    Personality         => { List => 'Bag' },
2020    OriginalFilename    => { Name => 'OriginalFileName' },
2021    ParentMEID          => { },
2022    # the following from StarGeek
2023    AssetID             => { },
2024    CallForImage        => { },
2025    CameraFilename      => { },
2026    CameraMakeModel     => { Avoid => 1 },
2027    Composition         => { },
2028    CameraSerialNumber  => { Avoid => 1 },
2029    ExclusiveCoverage   => { },
2030    GIFTFtpPriority     => { },
2031    ImageRank           => { },
2032    MediaEventIdDate    => { },
2033    OriginalCreateDateTime => { %dateTimeInfo, Groups => { 2 => 'Time' }, Avoid => 1 },
2034    ParentMediaEventID  => { },
2035    PrimaryFTP          => { List => 'Bag' },
2036    RoutingDestinations => { List => 'Bag' },
2037    RoutingExclusions   => { List => 'Bag' },
2038    SecondaryFTP        => { List => 'Bag' },
2039    TimeShot            => { },
2040);
2041
2042# RED smartphone images (ref PH)
2043%Image::ExifTool::XMP::LImage = (
2044    %xmpTableDefaults,
2045    GROUPS => { 1 => 'XMP-LImage', 2 => 'Image' },
2046    NAMESPACE => 'LImage',
2047    NOTES => 'Tags written by RED smartphones.',
2048    MajorVersion => { },
2049    MinorVersion => { },
2050    RightAlbedo => {
2051        Notes => 'Right stereoscopic image',
2052        Groups => { 2 => 'Preview' },
2053        ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
2054        ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
2055    },
2056);
2057
2058# SVG namespace properties (ref 9)
2059%Image::ExifTool::XMP::SVG = (
2060    GROUPS => { 0 => 'SVG', 1 => 'SVG', 2 => 'Image' },
2061    NAMESPACE => 'svg',
2062    LANG_INFO => \&GetLangInfo,
2063    NOTES => q{
2064        SVG (Scalable Vector Graphics) image tags.  By default, only the top-level
2065        SVG and Metadata tags are extracted from these images, but all graphics tags
2066        may be extracted by setting the Unknown option to 2 (-U on the command
2067        line).  The SVG tags are not part of XMP as such, but are included with the
2068        XMP module for convenience.  (see L<http://www.w3.org/TR/SVG11/>)
2069    },
2070    version    => 'SVGVersion',
2071    id         => 'ID',
2072    metadataId => 'MetadataID',
2073    width      => {
2074        Name => 'ImageWidth',
2075        ValueConv => '$val =~ s/px$//; $val',
2076    },
2077    height     => {
2078        Name => 'ImageHeight',
2079        ValueConv => '$val =~ s/px$//; $val',
2080    },
2081);
2082
2083# table to add tags in other namespaces
2084%Image::ExifTool::XMP::otherSVG = (
2085    GROUPS => { 0 => 'SVG', 2 => 'Unknown' },
2086    LANG_INFO => \&GetLangInfo,
2087    NAMESPACE => undef, # variable namespace
2088);
2089
2090#------------------------------------------------------------------------------
2091# Generate crd tags
2092# Inputs: 0) tag table ref
2093sub Init_crd($)
2094{
2095    my $tagTablePtr = shift;
2096    # import tags from CRS namespace
2097    my $crsTable = GetTagTable('Image::ExifTool::XMP::crs');
2098    my $tag;
2099    foreach $tag (Image::ExifTool::TagTableKeys($crsTable)) {
2100        my $crsInfo = $$crsTable{$tag};
2101        my $tagInfo = $$tagTablePtr{$tag} = { %$crsInfo };
2102        $$tagInfo{Groups} = { 0 => 'XMP', 1 => 'XMP-crd' , 2 => $$crsInfo{Groups}{2} } if $$crsInfo{Groups};
2103    }
2104}
2105
2106
21071;  #end
2108
2109__END__
2110
2111=head1 NAME
2112
2113Image::ExifTool::XMP2.pl - Additional XMP namespace definitions
2114
2115=head1 SYNOPSIS
2116
2117This module is loaded automatically by Image::ExifTool when required.
2118
2119=head1 DESCRIPTION
2120
2121This file contains definitions for less common XMP namespaces.
2122
2123=head1 AUTHOR
2124
2125Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
2126
2127This library is free software; you can redistribute it and/or modify it
2128under the same terms as Perl itself.
2129
2130=head1 REFERENCES
2131
2132=over 4
2133
2134=item L<http://ns.useplus.org/>
2135
2136=item L<http://www.prismstandard.org/>
2137
2138=item L<http://www.portfoliofaq.com/pfaq/v7mappings.htm>
2139
2140=item L<http://www.iptc.org/IPTC4XMP/>
2141
2142=item L<http://creativecommons.org/technology/xmp>
2143
2144=item L<http://www.optimasc.com/products/fileid/xmp-extensions.pdf>
2145
2146=item L<http://www.w3.org/TR/SVG11/>
2147
2148=back
2149
2150=head1 SEE ALSO
2151
2152L<Image::ExifTool::TagNames/XMP Tags>,
2153L<Image::ExifTool(3pm)|Image::ExifTool>
2154
2155=cut
2156