exiftool_vendored 11.86.0 → 11.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +38 -16
  3. data/bin/MANIFEST +3 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +34 -33
  7. data/bin/config_files/acdsee.config +1 -3
  8. data/bin/config_files/depthmap.config +56 -0
  9. data/bin/config_files/example.config +2 -0
  10. data/bin/config_files/gps2utm.config +1 -1
  11. data/bin/config_files/tiff_version.config +1 -1
  12. data/bin/exiftool +56 -39
  13. data/bin/fmt_files/gpx_wpt.fmt +1 -1
  14. data/bin/lib/Image/ExifTool.pm +32 -7
  15. data/bin/lib/Image/ExifTool.pod +53 -52
  16. data/bin/lib/Image/ExifTool/AIFF.pm +1 -1
  17. data/bin/lib/Image/ExifTool/Apple.pm +1 -1
  18. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +3 -3
  19. data/bin/lib/Image/ExifTool/CanonVRD.pm +1 -1
  20. data/bin/lib/Image/ExifTool/DNG.pm +1 -1
  21. data/bin/lib/Image/ExifTool/Exif.pm +3 -3
  22. data/bin/lib/Image/ExifTool/FITS.pm +1 -1
  23. data/bin/lib/Image/ExifTool/FLIR.pm +5 -5
  24. data/bin/lib/Image/ExifTool/Flash.pm +1 -1
  25. data/bin/lib/Image/ExifTool/FlashPix.pm +1 -1
  26. data/bin/lib/Image/ExifTool/Font.pm +2 -2
  27. data/bin/lib/Image/ExifTool/FujiFilm.pm +23 -7
  28. data/bin/lib/Image/ExifTool/GIF.pm +1 -1
  29. data/bin/lib/Image/ExifTool/GeoTiff.pm +1 -1
  30. data/bin/lib/Image/ExifTool/ICC_Profile.pm +1 -1
  31. data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
  32. data/bin/lib/Image/ExifTool/MIE.pm +1 -1
  33. data/bin/lib/Image/ExifTool/Minolta.pm +1 -1
  34. data/bin/lib/Image/ExifTool/Nikon.pm +1 -1
  35. data/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
  36. data/bin/lib/Image/ExifTool/Olympus.pm +4 -2
  37. data/bin/lib/Image/ExifTool/PDF.pm +2 -2
  38. data/bin/lib/Image/ExifTool/PNG.pm +10 -5
  39. data/bin/lib/Image/ExifTool/Panasonic.pm +1 -1
  40. data/bin/lib/Image/ExifTool/Pentax.pm +3 -3
  41. data/bin/lib/Image/ExifTool/Photoshop.pm +1 -1
  42. data/bin/lib/Image/ExifTool/QuickTime.pm +9 -4
  43. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +1 -1
  44. data/bin/lib/Image/ExifTool/README +51 -51
  45. data/bin/lib/Image/ExifTool/RIFF.pm +2 -2
  46. data/bin/lib/Image/ExifTool/RTF.pm +1 -1
  47. data/bin/lib/Image/ExifTool/Samsung.pm +1 -1
  48. data/bin/lib/Image/ExifTool/Sony.pm +1 -1
  49. data/bin/lib/Image/ExifTool/TagLookup.pm +1725 -1617
  50. data/bin/lib/Image/ExifTool/TagNames.pod +307 -9
  51. data/bin/lib/Image/ExifTool/Text.pm +59 -10
  52. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
  53. data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
  54. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +27 -12
  55. data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  56. data/bin/lib/Image/ExifTool/Writer.pl +25 -7
  57. data/bin/lib/Image/ExifTool/XMP.pm +6 -1
  58. data/bin/lib/Image/ExifTool/XMP2.pl +213 -1
  59. data/bin/lib/Image/ExifTool/ZIP.pm +1 -1
  60. data/bin/perl-Image-ExifTool.spec +30 -30
  61. data/lib/exiftool_vendored/version.rb +1 -1
  62. metadata +3 -2
@@ -454,7 +454,7 @@ sub WriteCanonRaw($$$)
454
454
  # pad with original garbage in case it contained something useful
455
455
  $value .= substr($buff, $pt+2+8-$len, 8-$len);
456
456
  } elsif ($len > 8) { # this shouldn't happen
457
- warn "Value too long! -- trucated\n";
457
+ warn "Value too long! -- truncated\n";
458
458
  $value = substr($value, 0, 8);
459
459
  }
460
460
  # create new directory entry
@@ -13,7 +13,7 @@ use strict;
13
13
 
14
14
  #------------------------------------------------------------------------------
15
15
  # Calculate CRC or update running CRC (ref 1)
16
- # Inputs: 0) data reference, 1) running crc to update (undef intially)
16
+ # Inputs: 0) data reference, 1) running crc to update (undef initially)
17
17
  # 2) data position (undef for 0), 3) data length (undef for all data),
18
18
  # Returns: updated CRC
19
19
  my @crcTable;
@@ -532,7 +532,7 @@ sub WriteItemInfo($$$)
532
532
  } elsif ($n <= 0xffffffff) {
533
533
  Set32u($n, $outfile, $$boxPos{iloc}[0] + 8 + $lenPt);
534
534
  } else {
535
- $et->Error("Can't yet promote iloc offset to 64 bits");
535
+ $et->Error("Can't yet promote iloc length to 64 bits");
536
536
  return ();
537
537
  }
538
538
  $n = 0;
@@ -621,18 +621,21 @@ sub WriteItemInfo($$$)
621
621
  my $nlen = ($siz >> 8) & 0x0f;
622
622
  my $nbas = ($siz >> 4) & 0x0f;
623
623
  my $nind = $siz & 0x0f;
624
- my $p;
624
+ my ($pbas, $poff);
625
625
  if ($ilocVer == 0) {
626
626
  # set offset to 0 as flag that this is a new idat chunk being added
627
- $p = length($add{iloc}) + 4 + $nbas + 2;
627
+ $pbas = length($add{iloc}) + 4;
628
+ $poff = $pbas + $nbas + 2;
628
629
  $add{iloc} .= pack('nn',$id,0) . SetVarInt(0,$nbas) . Set16u(1) .
629
630
  SetVarInt(0,$noff) . SetVarInt(length($newVal),$nlen);
630
631
  } elsif ($ilocVer == 1) {
631
- $p = length($add{iloc}) + 6 + $nbas + 2 + $nind;
632
+ $pbas = length($add{iloc}) + 6;
633
+ $poff = $pbas + $nbas + 2 + $nind;
632
634
  $add{iloc} .= pack('nnn',$id,0,0) . SetVarInt(0,$nbas) . Set16u(1) . SetVarInt(0,$nind) .
633
635
  SetVarInt(0,$noff) . SetVarInt(length($newVal),$nlen);
634
636
  } elsif ($ilocVer == 2) {
635
- $p = length($add{iloc}) + 8 + $nbas + 2 + $nind;
637
+ $pbas = length($add{iloc}) + 8;
638
+ $poff = $pbas + $nbas + 2 + $nind;
636
639
  $add{iloc} .= pack('Nnn',$id,0,0) . SetVarInt(0,$nbas) . Set16u(1) . SetVarInt(0,$nind) .
637
640
  SetVarInt(0,$noff) . SetVarInt(length($newVal),$nlen);
638
641
  } else {
@@ -643,9 +646,19 @@ sub WriteItemInfo($$$)
643
646
  my $off = $$dirInfo{ChunkOffset} or $et->Warn('Internal error. Missing ChunkOffset'), last;
644
647
  my $newOff;
645
648
  if ($noff == 4) {
646
- $newOff = [ 'stco_iloc', $$boxPos{iloc}[0] + $$boxPos{iloc}[1] + $p, $noff, 0, $id ];
649
+ $newOff = [ 'stco_iloc', $$boxPos{iloc}[0] + $$boxPos{iloc}[1] + $poff, $noff, 0, $id ];
647
650
  } elsif ($noff == 8) {
648
- $newOff = [ 'co64_iloc', $$boxPos{iloc}[0] + $$boxPos{iloc}[1] + $p, $noff, 0, $id ];
651
+ $newOff = [ 'co64_iloc', $$boxPos{iloc}[0] + $$boxPos{iloc}[1] + $poff, $noff, 0, $id ];
652
+ } elsif ($noff == 0) {
653
+ # offset_size is zero, so store the offset in base_offset instead
654
+ if ($nbas == 4) {
655
+ $newOff = [ 'stco_iloc', $$boxPos{iloc}[0] + $$boxPos{iloc}[1] + $pbas, $nbas, 0, $id ];
656
+ } elsif ($nbas == 8) {
657
+ $newOff = [ 'co64_iloc', $$boxPos{iloc}[0] + $$boxPos{iloc}[1] + $pbas, $nbas, 0, $id ];
658
+ } else {
659
+ $et->Warn("Can't create $name. Invalid iloc offset+base size");
660
+ last;
661
+ }
649
662
  } else {
650
663
  $et->Warn("Can't create $name. Invalid iloc offset size");
651
664
  last;
@@ -1093,7 +1106,7 @@ sub WriteQuickTime($$$)
1093
1106
  my $newVal = $et->GetNewValue($nvHash);
1094
1107
  next unless defined $newVal;
1095
1108
  my $prVal = $newVal;
1096
- my $flags = FormatQTValue($et, \$newVal, $$tagInfo{Format});
1109
+ my $flags = FormatQTValue($et, \$newVal, $format);
1097
1110
  next unless defined $newVal;
1098
1111
  my ($ctry, $lang) = (0, $undLang);
1099
1112
  if ($$ti{LangCode}) {
@@ -1149,7 +1162,6 @@ sub WriteQuickTime($$$)
1149
1162
  $val =~ s/\0$// unless $$tagInfo{Binary};
1150
1163
  $flags = 0x01; # write all strings as UTF-8
1151
1164
  } else {
1152
- $format = $$tagInfo{Format};
1153
1165
  if ($format) {
1154
1166
  # update flags for the format we are writing
1155
1167
  $flags = $qtFormat{$format} if $qtFormat{$format};
@@ -1171,7 +1183,7 @@ sub WriteQuickTime($$$)
1171
1183
  }
1172
1184
  my $prVal = $newVal;
1173
1185
  # format new value for writing (and get new flags)
1174
- $flags = FormatQTValue($et, \$newVal, $$tagInfo{Format});
1186
+ $flags = FormatQTValue($et, \$newVal, $format);
1175
1187
  my $grp = $et->GetGroup($langInfo, 1);
1176
1188
  $et->VerboseValue("- $grp:$$langInfo{Name}", $val);
1177
1189
  $et->VerboseValue("+ $grp:$$langInfo{Name}", $prVal);
@@ -1245,11 +1257,14 @@ sub WriteQuickTime($$$)
1245
1257
  } else {
1246
1258
  $newData = pack('nn', length($newData), $lang) . $newData;
1247
1259
  }
1248
- } elsif (not $$tagInfo{Format} or $$tagInfo{Format} =~ /^string/ and
1249
- not $$tagInfo{Binary} and not $$tagInfo{ValueConv})
1260
+ } elsif (not $format or $format =~ /^string/ and
1261
+ not $$tagInfo{Binary} and not $$tagInfo{ValueConv})
1250
1262
  {
1251
1263
  # write all strings as UTF-8
1252
1264
  $newData = $et->Encode($newData, 'UTF8');
1265
+ } elsif ($format and not $$tagInfo{Binary}) {
1266
+ # format new value for writing
1267
+ $newData = WriteValue($newData, $format);
1253
1268
  }
1254
1269
  }
1255
1270
  $$didTag{$nvHash} = 1; # set flag so we don't add this tag again
@@ -506,7 +506,7 @@ sub ConformPathToNamespace($$)
506
506
  next if $$nsUsed{$ns};
507
507
  my $uri = $nsURI{$ns};
508
508
  unless ($uri) {
509
- warn "No URI for namepace prefix $ns!\n";
509
+ warn "No URI for namespace prefix $ns!\n";
510
510
  next;
511
511
  }
512
512
  my $ns2;
@@ -745,7 +745,7 @@ TAG: foreach $tagInfo (@matchingTags) {
745
745
  }
746
746
  $writeGroup{$tagInfo} = $writeGroup;
747
747
  }
748
- # sort tag info list in reverse order of priority (higest number last)
748
+ # sort tag info list in reverse order of priority (highest number last)
749
749
  # so we get the highest priority error message in the end
750
750
  @tagInfoList = sort { $tagPriority{$a} <=> $tagPriority{$b} } @tagInfoList;
751
751
  # must write any tags which also write other tags first
@@ -857,7 +857,7 @@ TAG: foreach $tagInfo (@matchingTags) {
857
857
  # check to make sure this is a List or Shift tag if adding
858
858
  if ($addValue and not ($shift or $$tagInfo{List})) {
859
859
  if ($addValue eq '2') {
860
- undef $addValue; # quitely reset this option
860
+ undef $addValue; # quietly reset this option
861
861
  } else {
862
862
  $err = "Can't add $wgrp1:$tag (not a List type)";
863
863
  $verbose > 2 and print $out "$err\n";
@@ -1338,13 +1338,13 @@ sub SetNewValuesFromFile($$;@)
1338
1338
  foreach $tag (@tags) {
1339
1339
  # don't try to set errors or warnings
1340
1340
  next if $tag =~ /^(Error|Warning)\b/;
1341
- # get approprite value type if necessary
1341
+ # get appropriate value type if necessary
1342
1342
  if ($opts{SrcType} and $opts{SrcType} ne $srcType) {
1343
1343
  $$info{$tag} = $srcExifTool->GetValue($tag, $opts{SrcType});
1344
1344
  }
1345
1345
  # set value for this tag
1346
1346
  my ($n, $e) = $self->SetNewValue($tag, $$info{$tag}, %opts);
1347
- # delete this tag if we could't set it
1347
+ # delete this tag if we couldn't set it
1348
1348
  $n or delete $$info{$tag};
1349
1349
  }
1350
1350
  return $info;
@@ -2305,6 +2305,10 @@ sub WriteInfo($$;$$)
2305
2305
  $fileType = $tiffType;
2306
2306
  undef $rtnVal;
2307
2307
  } else {
2308
+ if ($tiffType eq 'FFF') {
2309
+ # (see https://exiftool.org/forum/index.php?topic=10848.0)
2310
+ $self->Error('Phocus may not properly update previews of edited FFF images', 1);
2311
+ }
2308
2312
  $dirInfo{Parent} = $tiffType;
2309
2313
  $rtnVal = $self->ProcessTIFF(\%dirInfo);
2310
2314
  }
@@ -5668,7 +5672,8 @@ sub WriteJPEG($$)
5668
5672
  my ($buff, $endPos, $trailInfo);
5669
5673
  my $delPreview = $$self{DEL_PREVIEW};
5670
5674
  $trailInfo = IdentifyTrailer($raf) unless $$delGroup{Trailer};
5671
- unless ($oldOutfile or $delPreview or $trailInfo or $$delGroup{Trailer}) {
5675
+ my $nvTrail = $self->GetNewValueHash($Image::ExifTool::Extra{Trailer});
5676
+ unless ($oldOutfile or $delPreview or $trailInfo or $$delGroup{Trailer} or $nvTrail) {
5672
5677
  # blindly copy the rest of the file
5673
5678
  while ($raf->Read($buff, 65536)) {
5674
5679
  Write($outfile, $buff) or $err = 1, last;
@@ -5699,7 +5704,20 @@ sub WriteJPEG($$)
5699
5704
  }
5700
5705
  # remember position of last data copied
5701
5706
  $endPos = $raf->Tell() - length($buff);
5702
- # rewrite trailers if they exist
5707
+ # write new trailer if specified
5708
+ if ($nvTrail) {
5709
+ # access new value directly to avoid copying a potentially very large data block
5710
+ if ($$nvTrail{Value} and $$nvTrail{Value}[0]) { # (note: "0" will also delete the trailer)
5711
+ $self->VPrint(0, ' Writing new trailer');
5712
+ Write($outfile, $$nvTrail{Value}[0]) or $err = 1;
5713
+ ++$$self{CHANGED};
5714
+ } elsif ($raf->Seek(0, 2) and $raf->Tell() != $endPos) {
5715
+ $self->VPrint(0, ' Deleting trailer (', $raf->Tell() - $endPos, ' bytes)');
5716
+ ++$$self{CHANGED}; # changed if there was previously a trailer
5717
+ }
5718
+ last; # all done
5719
+ }
5720
+ # rewrite existing trailers
5703
5721
  if ($trailInfo) {
5704
5722
  my $tbuf = '';
5705
5723
  $raf->Seek(-length($buff), 1); # seek back to just after EOI
@@ -5863,7 +5881,7 @@ sub WriteJPEG($$)
5863
5881
  HexDump($segDataPt, undef, %dumpParms);
5864
5882
  }
5865
5883
  }
5866
- # group delete of APP segements
5884
+ # group delete of APP segments
5867
5885
  if ($$delGroup{$dirName}) {
5868
5886
  $verbose and print $out " Deleting $dirName segment\n";
5869
5887
  ++$$self{CHANGED};
@@ -183,6 +183,7 @@ my %xmpNS = (
183
183
  dwc => 'http://rs.tdwg.org/dwc/index.htm',
184
184
  GettyImagesGIFT => 'http://xmp.gettyimages.com/gift/1.0/',
185
185
  LImage => 'http://ns.leiainc.com/photos/1.0/image/',
186
+ Profile => 'http://ns.google.com/photos/dd/1.0/profile/',
186
187
  );
187
188
 
188
189
  # build reverse namespace lookup
@@ -778,6 +779,10 @@ my %sRetouchArea = (
778
779
  Name => 'LImage',
779
780
  SubDirectory => { TagTable => 'Image::ExifTool::XMP::LImage' },
780
781
  },
782
+ Device => {
783
+ Name => 'Device',
784
+ SubDirectory => { TagTable => 'Image::ExifTool::XMP::Device' },
785
+ },
781
786
  );
782
787
 
783
788
  # hack to allow XML containing Dublin Core metadata to be handled like XMP (eg. EPUB - see ZIP.pm)
@@ -2244,7 +2249,7 @@ my %sPantryItem = (
2244
2249
 
2245
2250
  # Composite XMP tags
2246
2251
  %Image::ExifTool::XMP::Composite = (
2247
- # get latitude/logitude reference from XMP lat/long tags
2252
+ # get latitude/longitude reference from XMP lat/long tags
2248
2253
  # (used to set EXIF GPS position from XMP tags)
2249
2254
  GPSLatitudeRef => {
2250
2255
  Require => 'XMP-exif:GPSLatitude',
@@ -15,6 +15,7 @@
15
15
  # 9) http://www.w3.org/TR/SVG11/
16
16
  # 11) http://www.extensis.com/en/support/kb_article.jsp?articleNumber=6102211
17
17
  # 12) XMPSpecificationPart3_May2013, page 58
18
+ # 13) https://developer.android.com/training/camera2/Dynamic-depth-v1.0.pdf
18
19
  #------------------------------------------------------------------------------
19
20
 
20
21
  package Image::ExifTool::XMP;
@@ -76,6 +77,65 @@ my %sTimecode = (
76
77
  timeValue => { },
77
78
  value => { Writable => 'integer', Notes => 'only in XMP 2008 spec; an error?' },
78
79
  );
80
+ my %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
+ );
100
+ my %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
+ );
125
+ my %sVendorInfo = (
126
+ STRUCT_NAME => 'VendorInfo',
127
+ NAMESPACE => { VendorInfo => 'http://ns.google.com/photos/dd/1.0/vendorinfo/' },
128
+ Model => { },
129
+ Manufacturer => { },
130
+ Notes => { },
131
+ );
132
+ my %sAppInfo = (
133
+ STRUCT_NAME => 'AppInfo',
134
+ NAMESPACE => { AppInfo => 'http://ns.google.com/photos/dd/1.0/appinfo/' },
135
+ Application => { },
136
+ Version => { },
137
+ ItemURI => { },
138
+ );
79
139
 
80
140
  # camera-raw defaults
81
141
  %Image::ExifTool::XMP::crd = (
@@ -1167,7 +1227,7 @@ my %prismPublicationDate = (
1167
1227
  NAMESPACE => 'PixelLive',
1168
1228
  AVOID => 1,
1169
1229
  NOTES => q{
1170
- PixelLive namespace tags. These tags are not writable becase they are very
1230
+ PixelLive namespace tags. These tags are not writable because they are very
1171
1231
  uncommon and I haven't been able to locate a reference which gives the
1172
1232
  namespace URI.
1173
1233
  },
@@ -1789,6 +1849,158 @@ my %sSubVersion = (
1789
1849
  CameraBurstID => { },
1790
1850
  );
1791
1851
 
1852
+ # Google depth-map Device namespace (ref 13)
1853
+ %Image::ExifTool::XMP::Device = (
1854
+ %xmpTableDefaults,
1855
+ GROUPS => { 1 => 'XMP-Device', 2 => 'Camera' },
1856
+ NAMESPACE => { Device => 'http://ns.google.com/photos/dd/1.0/device/' },
1857
+ NOTES => q{
1858
+ Google depth-map Device tags. See
1859
+ L<https://developer.android.com/training/camera2/Dynamic-depth-v1.0.pdf> for
1860
+ the specification.
1861
+ },
1862
+ Container => {
1863
+ Struct => {
1864
+ STRUCT_NAME => 'DeviceContainer',
1865
+ NAMESPACE => { Container => 'http://ns.google.com/photos/dd/1.0/container/' },
1866
+ Directory => {
1867
+ List => 'Seq',
1868
+ Struct => {
1869
+ STRUCT_NAME => 'DeviceDirectory',
1870
+ NAMESPACE => { Container => 'http://ns.google.com/photos/dd/1.0/container/' },
1871
+ Item => {
1872
+ Struct => {
1873
+ STRUCT_NAME => 'DeviceItem',
1874
+ NAMESPACE => { Item => 'http://ns.google.com/photos/dd/1.0/item/' },
1875
+ Mime => { },
1876
+ Length => { Writable => 'integer' },
1877
+ Padding => { Writable => 'integer' },
1878
+ DataURI => { },
1879
+ },
1880
+ },
1881
+ },
1882
+ }
1883
+ },
1884
+ },
1885
+ Profiles => {
1886
+ List => 'Seq',
1887
+ FlatName => '',
1888
+ Struct => {
1889
+ STRUCT_NAME => 'DeviceProfiles',
1890
+ NAMESPACE => { Device => 'http://ns.google.com/photos/dd/1.0/device/' },
1891
+ Profile => {
1892
+ Struct => {
1893
+ STRUCT_NAME => 'DeviceProfile',
1894
+ NAMESPACE => { Profile => 'http://ns.google.com/photos/dd/1.0/profile/' },
1895
+ CameraIndices => { List => 'Seq', Writable => 'integer' },
1896
+ Type => { },
1897
+ },
1898
+ },
1899
+ },
1900
+ },
1901
+ Cameras => {
1902
+ List => 'Seq',
1903
+ FlatName => '',
1904
+ Struct => {
1905
+ STRUCT_NAME => 'DeviceCameras',
1906
+ NAMESPACE => { Device => 'http://ns.google.com/photos/dd/1.0/device/' },
1907
+ Camera => {
1908
+ Struct => {
1909
+ STRUCT_NAME => 'DeviceCamera',
1910
+ NAMESPACE => { Camera => 'http://ns.google.com/photos/dd/1.0/camera/' },
1911
+ DepthMap => {
1912
+ Struct => {
1913
+ STRUCT_NAME => 'DeviceDepthMap',
1914
+ NAMESPACE => { DepthMap => 'http://ns.google.com/photos/dd/1.0/depthmap/' },
1915
+ ConfidenceURI => { },
1916
+ DepthURI => { },
1917
+ Far => { Writable => 'real' },
1918
+ Format => { },
1919
+ ItemSemantic=> { },
1920
+ MeasureType => { },
1921
+ Near => { Writable => 'real' },
1922
+ Units => { },
1923
+ Software => { },
1924
+ FocalTableEntryCount => { Writable => 'integer' },
1925
+ FocalTable => { }, # (base64)
1926
+ },
1927
+ },
1928
+ Image => {
1929
+ Struct => {
1930
+ STRUCT_NAME => 'DeviceImage',
1931
+ NAMESPACE => { Image => 'http://ns.google.com/photos/dd/1.0/image/' },
1932
+ ItemSemantic=> { },
1933
+ ItemURI => { },
1934
+ },
1935
+ },
1936
+ ImagingModel => {
1937
+ Struct => {
1938
+ STRUCT_NAME => 'DeviceImagingModel',
1939
+ NAMESPACE => { ImagingModel => 'http://ns.google.com/photos/dd/1.0/imagingmodel/' },
1940
+ Distortion => { }, # (base64)
1941
+ DistortionCount => { Writable => 'integer' },
1942
+ FocalLengthX => { Writable => 'real' },
1943
+ FocalLengthY => { Writable => 'real' },
1944
+ ImageHeight => { Writable => 'integer' },
1945
+ ImageWidth => { Writable => 'integer' },
1946
+ PixelAspectRatio=> { Writable => 'real' },
1947
+ PrincipalPointX => { Writable => 'real' },
1948
+ PrincipalPointY => { Writable => 'real' },
1949
+ Skew => { Writable => 'real' },
1950
+ },
1951
+ },
1952
+ PointCloud => {
1953
+ Struct => {
1954
+ STRUCT_NAME => 'DevicePointCloud',
1955
+ NAMESPACE => { PointCloud => 'http://ns.google.com/photos/dd/1.0/pointcloud/' },
1956
+ PointCloud => { Writable => 'integer' },
1957
+ Points => { },
1958
+ Metric => { Writable => 'boolean' },
1959
+ },
1960
+ },
1961
+ Pose => { Struct => \%sPose },
1962
+ LightEstimate => {
1963
+ Struct => {
1964
+ STRUCT_NAME => 'DeviceLightEstimate',
1965
+ NAMESPACE => { LightEstimate => 'http://ns.google.com/photos/dd/1.0/lightestimate/' },
1966
+ ColorCorrectionR => { Writable => 'real' },
1967
+ ColorCorrectionG => { Writable => 'real' },
1968
+ ColorCorrectionB => { Writable => 'real' },
1969
+ PixelIntensity => { Writable => 'real' },
1970
+ },
1971
+ },
1972
+ VendorInfo => { Struct => \%sVendorInfo },
1973
+ AppInfo => { Struct => \%sAppInfo },
1974
+ Trait => { },
1975
+ },
1976
+ },
1977
+ },
1978
+ },
1979
+ VendorInfo => { Struct => \%sVendorInfo },
1980
+ AppInfo => { Struct => \%sAppInfo },
1981
+ EarthPos => { Struct => \%sEarthPose },
1982
+ Pose => { Struct => \%sPose },
1983
+ Planes => {
1984
+ List => 'Seq',
1985
+ FlatName => '',
1986
+ Struct => {
1987
+ STRUCT_NAME => 'DevicePlanes',
1988
+ NAMESPACE => { Device => 'http://ns.google.com/photos/dd/1.0/device/' },
1989
+ Plane => {
1990
+ Struct => {
1991
+ STRUCT_NAME => 'DevicePlane',
1992
+ NAMESPACE => { Plane => 'http://ns.google.com/photos/dd/1.0/plane/' },
1993
+ Pose => { Struct => \%sPose },
1994
+ ExtentX => { Writable => 'real' },
1995
+ ExtentZ => { Writable => 'real' },
1996
+ BoundaryVertexCount => { Writable => 'integer' },
1997
+ Boundary => { },
1998
+ },
1999
+ },
2000
+ },
2001
+ },
2002
+ );
2003
+
1792
2004
  # Getty Images namespace (ref PH)
1793
2005
  %Image::ExifTool::XMP::GettyImages = (
1794
2006
  %xmpTableDefaults,