exiftool_vendored 12.17.1 → 12.32.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +225 -1
  3. data/bin/MANIFEST +23 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +45 -43
  7. data/bin/arg_files/xmp2exif.args +2 -1
  8. data/bin/config_files/acdsee.config +193 -6
  9. data/bin/config_files/convert_regions.config +25 -14
  10. data/bin/config_files/cuepointlist.config +70 -0
  11. data/bin/config_files/example.config +2 -9
  12. data/bin/exiftool +142 -87
  13. data/bin/fmt_files/gpx.fmt +2 -2
  14. data/bin/fmt_files/gpx_wpt.fmt +2 -2
  15. data/bin/fmt_files/kml.fmt +1 -1
  16. data/bin/fmt_files/kml_track.fmt +1 -1
  17. data/bin/lib/Image/ExifTool/Apple.pm +3 -2
  18. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +30 -12
  19. data/bin/lib/Image/ExifTool/CBOR.pm +277 -0
  20. data/bin/lib/Image/ExifTool/Canon.pm +49 -18
  21. data/bin/lib/Image/ExifTool/DJI.pm +6 -6
  22. data/bin/lib/Image/ExifTool/DPX.pm +13 -2
  23. data/bin/lib/Image/ExifTool/DjVu.pm +6 -5
  24. data/bin/lib/Image/ExifTool/Exif.pm +28 -11
  25. data/bin/lib/Image/ExifTool/FITS.pm +13 -2
  26. data/bin/lib/Image/ExifTool/FlashPix.pm +35 -10
  27. data/bin/lib/Image/ExifTool/FujiFilm.pm +19 -8
  28. data/bin/lib/Image/ExifTool/GPS.pm +22 -11
  29. data/bin/lib/Image/ExifTool/Geotag.pm +13 -2
  30. data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
  31. data/bin/lib/Image/ExifTool/ICC_Profile.pm +2 -2
  32. data/bin/lib/Image/ExifTool/ID3.pm +15 -3
  33. data/bin/lib/Image/ExifTool/JPEG.pm +74 -4
  34. data/bin/lib/Image/ExifTool/JSON.pm +27 -4
  35. data/bin/lib/Image/ExifTool/Jpeg2000.pm +393 -16
  36. data/bin/lib/Image/ExifTool/LIF.pm +153 -0
  37. data/bin/lib/Image/ExifTool/Lang/nl.pm +60 -59
  38. data/bin/lib/Image/ExifTool/M2TS.pm +137 -5
  39. data/bin/lib/Image/ExifTool/MIE.pm +4 -3
  40. data/bin/lib/Image/ExifTool/MRC.pm +341 -0
  41. data/bin/lib/Image/ExifTool/MWG.pm +3 -3
  42. data/bin/lib/Image/ExifTool/MXF.pm +1 -1
  43. data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
  44. data/bin/lib/Image/ExifTool/Microsoft.pm +298 -82
  45. data/bin/lib/Image/ExifTool/Nikon.pm +19 -8
  46. data/bin/lib/Image/ExifTool/NikonSettings.pm +28 -11
  47. data/bin/lib/Image/ExifTool/Olympus.pm +6 -3
  48. data/bin/lib/Image/ExifTool/Other.pm +93 -0
  49. data/bin/lib/Image/ExifTool/PDF.pm +9 -12
  50. data/bin/lib/Image/ExifTool/PNG.pm +8 -7
  51. data/bin/lib/Image/ExifTool/Panasonic.pm +28 -3
  52. data/bin/lib/Image/ExifTool/Pentax.pm +28 -5
  53. data/bin/lib/Image/ExifTool/PhaseOne.pm +4 -3
  54. data/bin/lib/Image/ExifTool/Photoshop.pm +6 -0
  55. data/bin/lib/Image/ExifTool/QuickTime.pm +247 -88
  56. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +283 -141
  57. data/bin/lib/Image/ExifTool/README +3 -0
  58. data/bin/lib/Image/ExifTool/RIFF.pm +89 -12
  59. data/bin/lib/Image/ExifTool/Samsung.pm +48 -10
  60. data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -0
  61. data/bin/lib/Image/ExifTool/Sony.pm +237 -78
  62. data/bin/lib/Image/ExifTool/TagInfoXML.pm +1 -0
  63. data/bin/lib/Image/ExifTool/TagLookup.pm +4125 -4028
  64. data/bin/lib/Image/ExifTool/TagNames.pod +644 -286
  65. data/bin/lib/Image/ExifTool/Torrent.pm +18 -11
  66. data/bin/lib/Image/ExifTool/WriteExif.pl +1 -1
  67. data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
  68. data/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
  69. data/bin/lib/Image/ExifTool/WritePNG.pl +2 -0
  70. data/bin/lib/Image/ExifTool/WritePostScript.pl +1 -0
  71. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +55 -21
  72. data/bin/lib/Image/ExifTool/WriteXMP.pl +7 -3
  73. data/bin/lib/Image/ExifTool/Writer.pl +47 -10
  74. data/bin/lib/Image/ExifTool/XMP.pm +39 -14
  75. data/bin/lib/Image/ExifTool/XMP2.pl +2 -1
  76. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  77. data/bin/lib/Image/ExifTool/ZISRAW.pm +121 -2
  78. data/bin/lib/Image/ExifTool.pm +223 -72
  79. data/bin/lib/Image/ExifTool.pod +114 -93
  80. data/bin/perl-Image-ExifTool.spec +43 -42
  81. data/lib/exiftool_vendored/version.rb +1 -1
  82. metadata +28 -13
@@ -5,6 +5,7 @@
5
5
  #
6
6
  # Revisions: 2010/10/01 - P. Harvey Created
7
7
  # 2011/10/05 - PH Added ProcessXtra()
8
+ # 2021/02/23 - PH Added abiltity to write Xtra tags
8
9
  #
9
10
  # References: 1) http://research.microsoft.com/en-us/um/redmond/groups/ivm/hdview/hdmetadataspec.htm
10
11
  #------------------------------------------------------------------------------
@@ -16,9 +17,11 @@ use vars qw($VERSION);
16
17
  use Image::ExifTool qw(:DataAccess :Utils);
17
18
  use Image::ExifTool::XMP;
18
19
 
19
- $VERSION = '1.20';
20
+ $VERSION = '1.23';
20
21
 
21
22
  sub ProcessXtra($$$);
23
+ sub WriteXtra($$$);
24
+ sub CheckXtra($$$);
22
25
 
23
26
  # tags written by Microsoft HDView (ref 1)
24
27
  %Image::ExifTool::Microsoft::Stitch = (
@@ -196,11 +199,20 @@ my %sRegions = (
196
199
  # and Image::ExifTool::WTV::Metadata
197
200
  %Image::ExifTool::Microsoft::Xtra = (
198
201
  PROCESS_PROC => \&ProcessXtra,
202
+ WRITE_PROC => \&WriteXtra,
203
+ CHECK_PROC => \&CheckXtra,
204
+ WRITE_GROUP => 'Microsoft',
205
+ AVOID => 1,
199
206
  GROUPS => { 0 => 'QuickTime', 2 => 'Video' },
200
207
  VARS => { NO_ID => 1 },
201
208
  NOTES => q{
202
- Tags extracted from the Microsoft "Xtra" atom of QuickTime videos. Tag ID's
203
- are not shown because some are unruly GUID's.
209
+ Tags found in the Microsoft "Xtra" atom of QuickTime videos. Tag ID's are
210
+ not shown because some are unruly GUID's. Currently most of these tags are
211
+ not writable because the Microsoft documentation is poor and samples were
212
+ not available, but more tags may be made writable in the future if samples
213
+ are provided. Note that writable tags in this table are are flagged to
214
+ "Avoid", which means that other more common tags will be written instead if
215
+ possible unless the Microsoft group is specified explicitly.
204
216
  },
205
217
  Abstract => { },
206
218
  AcquisitionTime => { Groups => { 2 => 'Time' } },
@@ -327,30 +339,34 @@ my %sRegions = (
327
339
  UserServiceRating => { },
328
340
  VideoBitrate => { },
329
341
  VideoFormat => { },
330
- 'WM/AlbumArtist' => 'AlbumArtist',
331
- 'WM/AlbumCoverURL' => 'AlbumCoverURL',
332
- 'WM/AlbumTitle' => 'AlbumTitle',
342
+ 'WM/AlbumArtist' => { Name => 'AlbumArtist', Writable => 'Unicode' }, # (NC)
343
+ 'WM/AlbumCoverURL' => { Name => 'AlbumCoverURL', Writable => 'Unicode' }, # (NC)
344
+ 'WM/AlbumTitle' => { Name => 'AlbumTitle', Writable => 'Unicode' }, # (NC)
333
345
  'WM/BeatsPerMinute' => 'BeatsPerMinute',
334
- 'WM/Category' => 'Category',
335
- 'WM/Composer' => 'Composer',
336
- 'WM/Conductor' => 'Conductor',
337
- 'WM/ContentDistributor' => 'ContentDistributor',
346
+ 'WM/Category' => { Name => 'Category', Writable => 'Unicode', List => 1 },
347
+ 'WM/Composer' => { Name => 'Composer', Writable => 'Unicode' }, # (NC)
348
+ 'WM/Conductor' => { Name => 'Conductor', Writable => 'Unicode', List => 1 },
349
+ 'WM/ContentDistributor' => { Name => 'ContentDistributor', Writable => 'Unicode' },
338
350
  'WM/ContentDistributorType' => 'ContentDistributorType',
339
351
  'WM/ContentGroupDescription'=> 'ContentGroupDescription',
340
- 'WM/Director' => 'Director',
352
+ 'WM/Director' => { Name => 'Director', Writable => 'Unicode', List => 1 },
341
353
  'WM/EncodingTime' => {
342
354
  Name => 'EncodingTime',
343
355
  Groups => { 2 => 'Time' },
356
+ Shift => 'Time',
357
+ Writable => 'date',
344
358
  PrintConv => '$self->ConvertDateTime($val)',
359
+ PrintConvInv => '$self->InverseDateTime($val)',
345
360
  },
346
361
  'WM/Genre' => 'Genre',
347
362
  'WM/GenreID' => 'GenreID',
348
- 'WM/InitialKey' => 'InitialKey',
363
+ 'WM/InitialKey' => { Name => 'InitialKey', Writable => 'Unicode' },
349
364
  'WM/Language' => 'Language',
350
365
  'WM/Lyrics' => 'Lyrics',
351
366
  'WM/MCDI' => 'MCDI',
352
367
  'WM/MediaClassPrimaryID' => {
353
368
  Name => 'MediaClassPrimaryID',
369
+ Writable => 'GUID',
354
370
  PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx
355
371
  'D1607DBC-E323-4BE2-86A1-48A42A28441E' => 'Music',
356
372
  'DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B' => 'Video',
@@ -360,6 +376,7 @@ my %sRegions = (
360
376
  },
361
377
  'WM/MediaClassSecondaryID' => {
362
378
  Name => 'MediaClassSecondaryID',
379
+ Writable => 'GUID',
363
380
  PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx
364
381
  'E0236BEB-C281-4EDE-A36D-7AF76A3D45B5' => 'Audio Book',
365
382
  '3A172A13-2BD9-4831-835B-114F6A95943F' => 'Spoken Word',
@@ -385,22 +402,22 @@ my %sRegions = (
385
402
  },
386
403
  'WM/MediaOriginalChannel' => 'MediaOriginalChannel',
387
404
  'WM/MediaStationName' => 'MediaStationName',
388
- 'WM/Mood' => 'Mood',
389
- 'WM/OriginalAlbumTitle' => 'OriginalAlbumTitle',
390
- 'WM/OriginalArtist' => 'OriginalArtist',
391
- 'WM/OriginalLyricist' => 'OriginalLyricist',
392
- 'WM/ParentalRating' => 'ParentalRating',
405
+ 'WM/Mood' => { Name => 'Mood', Writable => 'Unicode' },
406
+ 'WM/OriginalAlbumTitle' => { Name => 'OriginalAlbumTitle', Writable => 'Unicode' }, # (NC)
407
+ 'WM/OriginalArtist' => { Name => 'OriginalArtist', Writable => 'Unicode' }, # (NC)
408
+ 'WM/OriginalLyricist' => { Name => 'OriginalLyricist', Writable => 'Unicode' }, # (NC)
409
+ 'WM/ParentalRating' => { Name => 'ParentalRating', Writable => 'Unicode' },
393
410
  'WM/PartOfSet' => 'PartOfSet',
394
- 'WM/Period' => 'Period',
395
- 'WM/Producer' => 'Producer',
411
+ 'WM/Period' => { Name => 'Period', Writable => 'Unicode' },
412
+ 'WM/Producer' => { Name => 'Producer', Writable => 'Unicode', List => 1 },
396
413
  'WM/ProtectionType' => 'ProtectionType',
397
- 'WM/Provider' => 'Provider',
414
+ 'WM/Provider' => { Name => 'Provider', Writable => 'Unicode' }, # (NC)
398
415
  'WM/ProviderRating' => 'ProviderRating',
399
416
  'WM/ProviderStyle' => 'ProviderStyle',
400
- 'WM/Publisher' => 'Publisher',
401
- 'WM/SharedUserRating' => 'SharedUserRating',
417
+ 'WM/Publisher' => { Name => 'Publisher', Writable => 'Unicode' }, # (multiple entries separated by semicolon)
418
+ 'WM/SharedUserRating' => { Name => 'SharedUserRating', Writable => 'int64u' },
402
419
  'WM/SubscriptionContentID' => 'SubscriptionContentID',
403
- 'WM/SubTitle' => 'Subtitle',
420
+ 'WM/SubTitle' => { Name => 'Subtitle', Writable => 'Unicode' },
404
421
  'WM/SubTitleDescription' => 'SubtitleDescription',
405
422
  'WM/TrackNumber' => 'TrackNumber',
406
423
  'WM/UniqueFileIdentifier' => 'UniqueFileIdentifier',
@@ -412,8 +429,11 @@ my %sRegions = (
412
429
  'WM/WMContentID' => 'WMContentID',
413
430
  'WM/WMShadowFileSourceDRMType' => 'WMShadowFileSourceDRMType',
414
431
  'WM/WMShadowFileSourceFileType' => 'WMShadowFileSourceFileType',
415
- 'WM/Writer' => 'Writer',
416
- 'WM/Year' => { Name => 'Year', Groups => { 2 => 'Time' } },
432
+ 'WM/Writer' => { Name => 'Writer', Groups => { 2 => 'Author' }, Writable => 'Unicode' }, # (NC)
433
+ 'WM/Year' => { Name => 'Year', Groups => { 2 => 'Time' } },
434
+ 'WM/PromotionURL' => { Name => 'PromotionURL',Writable => 'Unicode' },
435
+ 'WM/AuthorURL' => { Name => 'AuthorURL', Groups => { 2 => 'Author' }, Writable => 'Unicode' },
436
+ 'WM/EncodedBy', => { Name => 'EncodedBy', Writable => 'Unicode' },
417
437
 
418
438
  # I can't find documentation for the following tags in videos,
419
439
  # but the tag ID's correspond to Microsoft property GUID+ID's
@@ -422,9 +442,12 @@ my %sRegions = (
422
442
  # http://multi-rename-script.googlecode.com/svn-history/r4/trunk/plugins/ShellDetails/ShellDetails.ini
423
443
  # I have observed only 1 so far:
424
444
  '{2CBAA8F5-D81F-47CA-B17A-F8D822300131} 100' => {
425
- Name => 'DateAcquired',
445
+ Name => 'DateAcquired', # (seems to be when videos are downloaded from the camera)
426
446
  Groups => { 2 => 'Time' },
447
+ Shift => 'Time',
448
+ Writable => 'vt_filetime',
427
449
  PrintConv => '$self->ConvertDateTime($val)',
450
+ PrintConvInv => '$self->InverseDateTime($val,undef)',
428
451
  },
429
452
  # the following have not yet been observed...
430
453
  '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 10' => 'Name',
@@ -764,6 +787,245 @@ my %sRegions = (
764
787
  '{64440491-4C8B-11D1-8B70-080036B11A03} 43' => 'TotalBitrate',
765
788
  );
766
789
 
790
+ #------------------------------------------------------------------------------
791
+ # check new value for Xtra tag
792
+ # Inputs: 0) ExifTool object ref, 1) tagInfo hash ref, 2) raw value ref
793
+ # Returns: error string, or undef on success
794
+ sub CheckXtra($$$)
795
+ {
796
+ my ($et, $tagInfo, $valPt) = @_;
797
+ my $format = $$tagInfo{Writable};
798
+ return 'Unknown format' unless $format;
799
+ if ($format =~ /^int/) {
800
+ return 'Not an integer' unless Image::ExifTool::IsInt($$valPt);
801
+ } elsif ($format ne 'Unicode') {
802
+ my @vals = ($$valPt);
803
+ return 'Invalid format' unless WriteXtraValue($et, $tagInfo, \@vals);
804
+ }
805
+ return undef;
806
+ }
807
+
808
+ #------------------------------------------------------------------------------
809
+ # Decode value(s) in Microsoft Xtra tag
810
+ # Inputs: 0) ExifTool object ref, 1) value data
811
+ # Returns: Scalar context: decoded value, List context: 0) decoded value, 1) format string
812
+ sub ReadXtraValue($$)
813
+ {
814
+ my ($et, $data) = @_;
815
+ my ($format, $i, @vals);
816
+
817
+ return undef if length($data) < 10;
818
+
819
+ # (version flags according to the reference, but looks more like a count - PH)
820
+ my $count = Get32u(\$data, 0);
821
+ # point to start of first value (after 4-byte count, 4-byte length and 2-byte type)
822
+ my $valPos = 10;
823
+ for ($i=0; ;) {
824
+ # (stored value includes size of $valLen and $valType, so subtract 6)
825
+ my $valLen = Get32u(\$data, $valPos - 6) - 6;
826
+ last if $valPos + $valLen > length($data);
827
+ my $valType = Get16u(\$data, $valPos - 2);
828
+ my $val = substr($data, $valPos, $valLen);
829
+ # Note: all dumb Microsoft values are little-endian inside a big-endian-format file
830
+ SetByteOrder('II');
831
+ if ($valType == 8) {
832
+ $format = 'Unicode';
833
+ $val = $et->Decode($val, 'UCS2');
834
+ } elsif ($valType == 19 and $valLen == 8) {
835
+ $format = 'int64u';
836
+ $val = Get64u(\$val, 0);
837
+ } elsif ($valType == 21 and $valLen == 8) {
838
+ $format = 'date';
839
+ $val = Get64u(\$val, 0);
840
+ # convert time from 100 ns intervals since Jan 1, 1601
841
+ $val = $val * 1e-7 - 11644473600 if $val;
842
+ # (the Nikon S100 uses UTC timezone, same as ASF - PH)
843
+ $val = Image::ExifTool::ConvertUnixTime($val, 1);
844
+ } elsif ($valType == 72 and $valLen == 16) {
845
+ $format = 'GUID';
846
+ $val = uc unpack('H*',pack('NnnNN',unpack('VvvNN',$val)));
847
+ $val =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/;
848
+ } elsif ($valType == 65 and $valLen > 4) { #PH (empirical)
849
+ $format = 'variant';
850
+ require Image::ExifTool::FlashPix;
851
+ my $vPos = 0; # (necessary because ReadFPXValue updates this)
852
+ # read entry as a VT_VARIANT (use FlashPix module for this)
853
+ $val = Image::ExifTool::FlashPix::ReadFPXValue($et, \$val, $vPos,
854
+ Image::ExifTool::FlashPix::VT_VARIANT(), $valLen, 1);
855
+ } else {
856
+ $format = "Unknown($valType)";
857
+ }
858
+ SetByteOrder('MM'); # back to native QuickTime byte ordering
859
+ push @vals, $val;
860
+ last if ++$i >= $count;
861
+ $valPos += $valLen + 6; # step to next value
862
+ last if $valPos > length($data);
863
+ }
864
+ return wantarray ? (\@vals, $format) : \@vals;
865
+ }
866
+
867
+ #------------------------------------------------------------------------------
868
+ # Write a Microsoft Xtra value
869
+ # Inputs: 0) ExifTool object ref, 1) tagInfo ref, 2) reference to list of values
870
+ # Returns: new value binary data (or empty string)
871
+ sub WriteXtraValue($$$)
872
+ {
873
+ my ($et, $tagInfo, $vals) = @_;
874
+ my $format = $$tagInfo{Writable};
875
+ my $buff = '';
876
+ my $count = 0;
877
+ my $val;
878
+ foreach $val (@$vals) {
879
+ SetByteOrder('II');
880
+ my ($type, $dat);
881
+ if ($format eq 'Unicode') {
882
+ $dat = $et->Encode($val,'UCS2','II') . "\0\0"; # (must be null terminated)
883
+ $type = 8;
884
+ } elsif ($format eq 'int64u') {
885
+ if (Image::ExifTool::IsInt($val)) {
886
+ $dat = Set64u($val);
887
+ $type = 19;
888
+ }
889
+ } elsif ($format eq 'date') {
890
+ $dat = Image::ExifTool::GetUnixTime($val, 1); # (convert to UTC, NC)
891
+ if ($dat) {
892
+ # 100ns intervals since Jan 1, 1601
893
+ $dat = Set64u(($dat + 11644473600) * 1e7);
894
+ $type = 21;
895
+ }
896
+ } elsif ($format eq 'vt_filetime') { # 'date' value inside a VT_VARIANT
897
+ $dat = Image::ExifTool::GetUnixTime($val); # (leave as local time, NC)
898
+ if ($dat) {
899
+ # 100ns intervals since Jan 1, 1601
900
+ $dat = Set32u(64) . Set64u(($dat + 11644473600) * 1e7);
901
+ $type = 65;
902
+ }
903
+ } elsif ($format eq 'GUID') {
904
+ ($dat = $val) =~ tr/-//d;
905
+ if (length($dat) == 32) {
906
+ $dat = pack('VvvNN',unpack('NnnNN',pack('H*', $dat)));
907
+ $type = 72;
908
+ }
909
+ } else {
910
+ $et->WarnOnce("Error converting value for Microsoft:$$tagInfo{Name}");
911
+ }
912
+ SetByteOrder('MM');
913
+ if (defined $type) {
914
+ ++$count;
915
+ $buff .= Set32u(length($dat)+6) . Set16u($type) . $dat;
916
+ }
917
+ }
918
+ return $count ? Set32u($count) . $buff : '';
919
+ }
920
+
921
+ #------------------------------------------------------------------------------
922
+ # Add new values to list
923
+ # Inputs: 0) ExifTool ref, 1) new value list ref, 2) nvHash ref
924
+ # Returns: true if something was added
925
+ sub AddNewValues($$$)
926
+ {
927
+ my ($et, $vals, $nvHash) = @_;
928
+ my @newVals = $et->GetNewValue($nvHash) or return undef;
929
+ if ($$et{OPTIONS}{Verbose} > 1) {
930
+ $et->VPrint(1, " + Microsoft:$$nvHash{TagInfo}{Name} = $_\n") foreach @newVals;
931
+ }
932
+ push @$vals, @newVals;
933
+ return 1;
934
+ }
935
+
936
+ #------------------------------------------------------------------------------
937
+ # Write tags to a Microsoft Xtra MP4 atom
938
+ # Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref
939
+ # Returns: Microsoft Xtra data block (may be empty if no Xtra data) or undef on error
940
+ sub WriteXtra($$$)
941
+ {
942
+ my ($et, $dirInfo, $tagTablePtr) = @_;
943
+ $et or return 1; # allow dummy access
944
+
945
+ my $delGroup = ($$et{DEL_GROUP} and $$et{DEL_GROUP}{Microsoft});
946
+ my $newTags = $et->GetNewTagInfoHash($tagTablePtr);
947
+
948
+ return undef unless $delGroup or %$newTags; # don't rewrite if nothing to do
949
+
950
+ my $dataPt = $$dirInfo{DataPt};
951
+ my $dataLen = length $$dataPt;
952
+ my $newData = '';
953
+ my $pos = 0;
954
+ my ($err, %done, $changed, $tag);
955
+
956
+ if ($delGroup) {
957
+ $changed = 1 if $dataLen;
958
+ my $empty = '';
959
+ $dataPt = $empty;
960
+ $dataLen = 0;
961
+ }
962
+ for (;;) {
963
+ last if $pos + 4 > $dataLen;
964
+ my $size = Get32u($dataPt, $pos); # (includes $size word)
965
+ ($size < 8 or $pos + $size > $dataLen) and $err=1, last;
966
+ my $tagLen = Get32u($dataPt, $pos + 4);
967
+ $tagLen + 18 > $size and $err=1, last;
968
+ $tag = substr($$dataPt, $pos + 8, $tagLen);
969
+ my @newVals;
970
+ while ($$newTags{$tag}) {
971
+ my $nvHash = $et->GetNewValueHash($$newTags{$tag});
972
+ $$nvHash{CreateOnly} and delete($$newTags{$tag}), last; # don't edit this tag
973
+ my $valPos = $pos + 8 + $tagLen;
974
+ my $valLen = $size - 8 - $tagLen;
975
+ my $val = ReadXtraValue($et, substr($$dataPt, $valPos, $valLen));
976
+ foreach $val (@$val) {
977
+ my $overwrite = $et->IsOverwriting($nvHash, $val);
978
+ $overwrite or push(@newVals, $val), next;
979
+ $et->VPrint(1, " - Microsoft:$$newTags{$tag}{Name} = $val\n");
980
+ next if $done{$tag};
981
+ $done{$tag} = 1;
982
+ AddNewValues($et, \@newVals, $nvHash);
983
+ }
984
+ # add to the end of the list if this was a List-type tag and we didn't delete anything
985
+ if (not $done{$tag} and $$newTags{$tag}{List}) {
986
+ AddNewValues($et, \@newVals, $nvHash) or last;
987
+ $done{$tag} = 1;
988
+ }
989
+ last; # (it was a cheap goto)
990
+ }
991
+ if ($done{$tag}) {
992
+ $changed = 1;
993
+ # write changed values
994
+ my $buff = WriteXtraValue($et, $$newTags{$tag}, \@newVals);
995
+ if (length $buff) {
996
+ $newData .= Set32u(8+length($tag)+length($buff)) . Set32u(length($tag)) . $tag . $buff;
997
+ }
998
+ } else {
999
+ # nothing changed; just copy over
1000
+ $newData .= substr($$dataPt, $pos, $size);
1001
+ }
1002
+ $pos += $size; # step to next entry
1003
+ }
1004
+ if ($err) {
1005
+ $et->Warn('Microsoft Xtra format error');
1006
+ return undef;
1007
+ }
1008
+ # add any new tags
1009
+ foreach $tag (sort keys %$newTags) {
1010
+ next if $done{$tag};
1011
+ my $nvHash = $et->GetNewValueHash($$newTags{$tag});
1012
+ next unless $$nvHash{IsCreating} and not $$nvHash{EditOnly};
1013
+ my @newVals;
1014
+ AddNewValues($et, \@newVals, $nvHash) or next;
1015
+ my $buff = WriteXtraValue($et, $$newTags{$tag}, \@newVals);
1016
+ if (length $buff) {
1017
+ $newData .= Set32u(8+length($tag)+length($buff)) . Set32u(length($tag)) . $tag . $buff;
1018
+ $changed = 1;
1019
+ }
1020
+ }
1021
+ if ($changed) {
1022
+ ++$$et{CHANGED};
1023
+ } else {
1024
+ undef $newData;
1025
+ }
1026
+ return $newData;
1027
+ }
1028
+
767
1029
  #------------------------------------------------------------------------------
768
1030
  # Extract information from Xtra MP4 atom
769
1031
  # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
@@ -783,61 +1045,13 @@ sub ProcessXtra($$$)
783
1045
  last if $size < 8 or $pos + $size > $dataLen;
784
1046
  my $tagLen = Get32u($dataPt, $pos + 4);
785
1047
  last if $tagLen + 18 > $size;
786
- my $tag = substr($$dataPt, $pos + 8, $tagLen);
787
- # (version flags according to the reference, but looks more like a count - PH)
788
- my $count = Get32u($dataPt, $pos + $tagLen + 8);
789
- my ($i, $valPos, $valLen, $valType, $val, $format, @vals);
790
- # point to start of first value (after 4-byte length and 2-byte type)
791
- $valPos = $pos + $tagLen + 18;
792
- for ($i=0; ;) {
793
- # (stored value includes size of $valLen and $valType, so subtract 6)
794
- $valLen = Get32u($dataPt, $valPos - 6) - 6;
795
- my $more = $pos + $size - $valPos - $valLen;
796
- last if $more < 0;
797
- $valType = Get16u($dataPt, $valPos - 2);
798
- $val = substr($$dataPt, $valPos, $valLen);
799
- # Note: all dumb Microsoft values are little-endian inside a big-endian-format file
800
- SetByteOrder('II');
801
- if ($valType == 8) {
802
- $format = 'Unicode';
803
- $val = $et->Decode($val, 'UCS2');
804
- } elsif ($valType == 19 and $valLen == 8) {
805
- $format = 'int64u';
806
- $val = Get64u(\$val, 0);
807
- } elsif ($valType == 21 and $valLen == 8) {
808
- $format = 'date';
809
- $val = Get64u(\$val, 0);
810
- # convert time from 100 ns intervals since Jan 1, 1601
811
- $val = $val * 1e-7 - 11644473600 if $val;
812
- # (the Nikon S100 uses UTC timezone, same as ASF - PH)
813
- $val = Image::ExifTool::ConvertUnixTime($val) . 'Z';
814
- } elsif ($valType == 72 and $valLen == 16) {
815
- $format = 'GUID';
816
- $val = uc unpack('H*',pack('NnnNN',unpack('VvvNN',$val)));
817
- $val =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/;
818
- } elsif ($valType == 65 && $valLen > 4) { #PH (empirical)
819
- $format = 'variant';
820
- require Image::ExifTool::FlashPix;
821
- my $vPos = $valPos; # (necessary because ReadFPXValue updates this)
822
- # read entry as a VT_VARIANT (use FlashPix module for this)
823
- $val = Image::ExifTool::FlashPix::ReadFPXValue($et, $dataPt, $vPos,
824
- Image::ExifTool::FlashPix::VT_VARIANT(), $valPos+$valLen, 1);
825
- } else {
826
- $format = "Unknown($valType)";
827
- }
828
- SetByteOrder('MM'); # back to native QuickTime byte ordering
829
- last if ++$i >= $count or $more < 6;
830
- push @vals, $val;
831
- undef $val;
832
- $valPos += $valLen + 6; # step to next value
833
- }
834
- if (@vals) {
835
- push @vals, $val if defined $val;
836
- $val = \@vals;
837
- $valPos = $pos + $tagLen + 18;
838
- $valLen = $size - 18 - $tagLen;
839
- }
1048
+ my $valLen = $size - 8 - $tagLen;
840
1049
  if ($tagLen > 0 and $valLen > 0) {
1050
+ my $tag = substr($$dataPt, $pos + 8, $tagLen);
1051
+ my $valPos = $pos + 8 + $tagLen;
1052
+ my ($val, $format) = ReadXtraValue($et, substr($$dataPt, $valPos, $valLen));
1053
+ last unless defined $val;
1054
+ $val = $$val[0] if @$val == 1;
841
1055
  my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
842
1056
  unless ($tagInfo) {
843
1057
  # generate tag information for unrecognized tags
@@ -850,6 +1064,7 @@ sub ProcessXtra($$$)
850
1064
  $et->VPrint(0, $$et{INDENT}, "[adding Microsoft:$tag]\n");
851
1065
  }
852
1066
  }
1067
+ my $count = ref $val ? scalar @$val : 1;
853
1068
  $et->HandleTag($tagTablePtr, $tag, $val,
854
1069
  TagInfo => $tagInfo,
855
1070
  DataPt => $dataPt,
@@ -857,7 +1072,7 @@ sub ProcessXtra($$$)
857
1072
  Start => $valPos,
858
1073
  Size => $valLen,
859
1074
  Format => $format,
860
- Extra => " count=$count type=$valType",
1075
+ Extra => " count=$count",
861
1076
  );
862
1077
  }
863
1078
  $pos += $size; # step to next entry
@@ -880,7 +1095,8 @@ This module is used by Image::ExifTool
880
1095
  =head1 DESCRIPTION
881
1096
 
882
1097
  This module contains definitions required by Image::ExifTool to interpret
883
- Microsoft-specific EXIF and XMP tags.
1098
+ Microsoft-specific EXIF and XMP tags, and routines to read/write Microsoft
1099
+ Xtra tags in videos.
884
1100
 
885
1101
  =head1 AUTHOR
886
1102
 
@@ -62,7 +62,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
62
62
  use Image::ExifTool::Exif;
63
63
  use Image::ExifTool::GPS;
64
64
 
65
- $VERSION = '3.92';
65
+ $VERSION = '4.00';
66
66
 
67
67
  sub LensIDConv($$$);
68
68
  sub ProcessNikonAVI($$$);
@@ -272,6 +272,7 @@ sub GetAFPointGrid($$;$);
272
272
  '9F 58 44 44 14 14 A1 06' => 'AF-S DX Nikkor 35mm f/1.8G', #27
273
273
  'A0 54 50 50 0C 0C A2 06' => 'AF-S Nikkor 50mm f/1.4G',
274
274
  'A1 40 18 37 2C 34 A3 06' => 'AF-S DX Nikkor 10-24mm f/3.5-4.5G ED',
275
+ 'A1 40 2D 53 2C 3C CB 86' => 'AF-P DX Nikkor 18-55mm f/3.5-5.6G', #30
275
276
  'A2 48 5C 80 24 24 A4 0E' => 'AF-S Nikkor 70-200mm f/2.8G ED VR II',
276
277
  'A3 3C 29 44 30 30 A5 0E' => 'AF-S Nikkor 16-35mm f/4G ED VR',
277
278
  'A4 54 37 37 0C 0C A6 06' => 'AF-S Nikkor 24mm f/1.4G ED',
@@ -495,6 +496,7 @@ sub GetAFPointGrid($$;$);
495
496
  '02 46 5C 82 25 25 02 00' => 'Sigma 70-210mm F2.8 APO', #JD
496
497
  '02 40 5C 82 2C 35 02 00' => 'Sigma APO 70-210mm F3.5-4.5',
497
498
  '26 3C 5C 82 30 3C 1C 02' => 'Sigma 70-210mm F4-5.6 UC-II',
499
+ '02 3B 5C 82 30 3C 02 00' => 'Sigma Zoom-K 70-210mm F4-5.6', #30
498
500
  '26 3C 5C 8E 30 3C 1C 02' => 'Sigma 70-300mm F4-5.6 DG Macro',
499
501
  '56 3C 5C 8E 30 3C 1C 02' => 'Sigma 70-300mm F4-5.6 APO Macro Super II',
500
502
  'E0 3C 5C 8E 30 3C 4B 06' => 'Sigma 70-300mm F4-5.6 APO DG Macro HSM', #22
@@ -554,6 +556,7 @@ sub GetAFPointGrid($$;$);
554
556
  'F3 54 2B 50 24 24 84 0E' => 'Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical (IF) (B005)',
555
557
  '00 3F 2D 80 2B 40 00 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) (A14)',
556
558
  '00 3F 2D 80 2C 40 00 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14)',
559
+ 'EC 3E 3C 8E 2C 40 DF 0E' => 'Tamron 28-300mm f/3.5-6.3 Di VC PZD A010', #30
557
560
  '00 40 2D 80 2C 40 00 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)', #NJ
558
561
  'FC 40 2D 80 2C 40 DF 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)', #PH (NC)
559
562
  'E6 40 2D 80 2C 40 DF 0E' => 'Tamron 18-200mm f/3.5-6.3 Di II VC (B018)', #Tanel (removed AF designation, ref 37)
@@ -563,7 +566,7 @@ sub GetAFPointGrid($$;$);
563
566
  'F0 3F 2D 8A 2C 40 DF 0E' => 'Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD (B008)',
564
567
  'E0 40 2D 98 2C 41 DF 4E' => 'Tamron 18-400mm f/3.5-6.3 Di II VC HLD (B028)', # (removed AF designation, ref 37)
565
568
  '07 40 2F 44 2C 34 03 02' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)',
566
- '07 40 30 45 2D 35 03 02' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)',
569
+ '07 40 30 45 2D 35 03 02.1' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)',
567
570
  '00 49 30 48 22 2B 00 02' => 'Tamron SP AF 20-40mm f/2.7-3.5 (166D)',
568
571
  '0E 4A 31 48 23 2D 0E 02' => 'Tamron SP AF 20-40mm f/2.7-3.5 (166D)',
569
572
  'FE 48 37 5C 24 24 DF 0E' => 'Tamron SP 24-70mm f/2.8 Di VC USD (A007)', #24
@@ -595,6 +598,7 @@ sub GetAFPointGrid($$;$);
595
598
  '00 48 5C 8E 30 3C 00 06' => 'Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17NII)', #JD
596
599
  'F1 47 5C 8E 30 3C DF 0E' => 'Tamron SP 70-300mm f/4-5.6 Di VC USD (A005)',
597
600
  'CF 47 5C 8E 31 3D DF 0E' => 'Tamron SP 70-300mm f/4-5.6 Di VC USD (A030)', #forum9773
601
+ 'CC 44 68 98 34 41 DF 0E' => 'Tamron 100-400mm f/4.5-6.3 Di VC USD', #30
598
602
  'EB 40 76 A6 38 40 DF 0E' => 'Tamron SP AF 150-600mm f/5-6.3 VC USD (A011)',
599
603
  'E3 40 76 A6 38 40 DF 4E' => 'Tamron SP 150-600mm f/5-6.3 Di VC USD G2', #30
600
604
  '20 3C 80 98 3D 3D 1E 02' => 'Tamron AF 200-400mm f/5.6 LD IF (75D)',
@@ -612,6 +616,7 @@ sub GetAFPointGrid($$;$);
612
616
  '7A 48 1C 29 24 24 7E 06' => 'Tokina AT-X 116 PRO DX II (AF 11-16mm f/2.8)',
613
617
  '80 48 1C 29 24 24 7A 06' => 'Tokina atx-i 11-16mm F2.8 CF', #exiv2 issue 1078
614
618
  '7A 48 1C 30 24 24 7E 06' => 'Tokina AT-X 11-20 F2.8 PRO DX (AF 11-20mm f/2.8)',
619
+ '8B 48 1C 30 24 24 85 06' => 'Tokina AT-X 11-20 F2.8 PRO DX (AF 11-20mm f/2.8)', #forum12687
615
620
  '00 3C 1F 37 30 30 00 06' => 'Tokina AT-X 124 AF PRO DX (AF 12-24mm f/4)',
616
621
  '7A 3C 1F 37 30 30 7E 06.2' => 'Tokina AT-X 124 AF PRO DX II (AF 12-24mm f/4)',
617
622
  '7A 3C 1F 3C 30 30 7E 06' => 'Tokina AT-X 12-28 PRO DX (AF 12-28mm f/4)',
@@ -640,6 +645,7 @@ sub GetAFPointGrid($$;$);
640
645
  '24 44 60 98 34 3C 1A 02' => 'Tokina AT-X 840 AF-II (AF 80-400mm f/4.5-5.6)',
641
646
  '00 44 60 98 34 3C 00 02' => 'Tokina AT-X 840 D (AF 80-400mm f/4.5-5.6)',
642
647
  '14 48 68 8E 30 30 0B 00' => 'Tokina AT-X 340 AF (AF 100-300mm f/4)',
648
+ '8C 48 29 3C 24 24 86 06' => 'Tokina opera 16-28mm F2.8 FF', #30
643
649
  #
644
650
  '06 3F 68 68 2C 2C 06 00' => 'Cosina AF 100mm F3.5 Macro',
645
651
  '07 36 3D 5F 2C 3C 03 00' => 'Cosina AF Zoom 28-80mm F3.5-5.6 MC Macro',
@@ -655,6 +661,7 @@ sub GetAFPointGrid($$;$);
655
661
  '00 54 48 48 18 18 00 00' => 'Voigtlander Ultron 40mm F2 SLII Aspherical',
656
662
  '00 54 55 55 0C 0C 00 00' => 'Voigtlander Nokton 58mm F1.4 SLII',
657
663
  '00 40 64 64 2C 2C 00 00' => 'Voigtlander APO-Lanthar 90mm F3.5 SLII Close Focus',
664
+ '07 40 30 45 2D 35 03 02.2' => 'Voigtlander Ultragon 19-35mm F3.5-4.5 VMV', #NJ
658
665
  #
659
666
  '00 40 2D 2D 2C 2C 00 00' => 'Carl Zeiss Distagon T* 3.5/18 ZF.2',
660
667
  '00 48 27 27 24 24 00 00' => 'Carl Zeiss Distagon T* 2.8/15 ZF.2', #MykytaKozlov
@@ -716,6 +723,9 @@ sub GetAFPointGrid($$;$);
716
723
  '00 40 11 11 2C 2C 00 00' => 'Samyang 8mm f/3.5 Fish-Eye',
717
724
  '00 58 64 64 20 20 00 00' => 'Soligor C/D Macro MC 90mm f/2.5',
718
725
  '4A 58 30 30 14 0C 4D 02' => 'Rokinon 20mm f/1.8 ED AS UMC', #30
726
+ #
727
+ 'A0 56 44 44 14 14 A2 06' => 'Sony FE 35mm F1.8', #IB (Techart adapter)
728
+ 'A0 37 5C 8E 34 3C A2 06' => 'Sony FE 70-300mm F4.5-5.6 G OSS', #IB (Techart adapter)
719
729
  );
720
730
 
721
731
  # text encoding used in LocationInfo (ref PH)
@@ -4718,6 +4728,9 @@ my %nikonFocalConversions = (
4718
4728
  21 => 'Nikkor Z 50mm f/1.2 S', #IB
4719
4729
  22 => 'Nikkor Z 24-50mm f/4-6.3', #IB
4720
4730
  23 => 'Nikkor Z 14-24mm f/2.8 S', #IB
4731
+ 24 => 'Nikkor Z MC 105mm f/2.8 VR S', #IB
4732
+ 27 => 'Nikkor Z MC 50mm f/2.8', #IB
4733
+ 29 => 'Nikkor Z 28mm f/2.8', #IB
4721
4734
  },
4722
4735
  },
4723
4736
  0x36 => {
@@ -8490,8 +8503,8 @@ my %nikonFocalConversions = (
8490
8503
  # 0x02 - undef[148]
8491
8504
  # 0x03 - undef[284]
8492
8505
  # 0x04 - undef[148,212]
8493
- # 0x05 - undef[84]
8494
- # 0x06 - undef[116]
8506
+ # 0x05 - undef[84] (barrel distortion params at offsets 0x14,0x1c,0x24, ref 28)
8507
+ # 0x06 - undef[116] (vignette correction params at offsets 0x24,0x34,0x44, ref 28)
8495
8508
  # 0x07 - undef[104]
8496
8509
  # 0x08 - undef[24]
8497
8510
  # 0x09 - undef[36]
@@ -9466,7 +9479,7 @@ sub GetAFPointGrid($$;$)
9466
9479
  return undef unless $val =~ /^([A-J])(\d+)$/i;
9467
9480
  return (ord(uc($1))-65) * $ncol + $2 - 1;
9468
9481
  } else {
9469
- my $row = int(($val + 0.5) / $ncol);
9482
+ my $row = int(($val + 0.5) / $ncol) & 0xff;
9470
9483
  my $col = $val - $ncol * $row + 1;
9471
9484
  return chr(65+$row) . $col;
9472
9485
  }
@@ -9945,12 +9958,10 @@ sub PrescanExif($$$)
9945
9958
  $dataLen = length $data;
9946
9959
  $dirStart = 0;
9947
9960
  }
9948
- # loop through necessary IFD entries
9949
- my ($lastTag) = sort { $b <=> $a } keys %$tagHash; # (reverse sort)
9961
+ # loop through Nikon MakerNote IFD entries
9950
9962
  for ($index=0; $index<$numEntries; ++$index) {
9951
9963
  my $entry = $dirStart + 2 + 12 * $index;
9952
9964
  my $tagID = Get16u($dataPt, $entry);
9953
- last if $tagID > $lastTag; # (assuming tags are in order)
9954
9965
  next unless exists $$tagHash{$tagID}; # only extract required tags
9955
9966
  my $format = Get16u($dataPt, $entry+2);
9956
9967
  next if $format < 1 or $format > 13;