exiftool_vendored 13.04.0 → 13.08.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +48 -0
  3. data/bin/MANIFEST +1 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +2 -2
  7. data/bin/exiftool +30 -23
  8. data/bin/lib/Image/ExifTool/AIFF.pm +1 -1
  9. data/bin/lib/Image/ExifTool/APE.pm +1 -1
  10. data/bin/lib/Image/ExifTool/ASF.pm +1 -1
  11. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +4 -3
  12. data/bin/lib/Image/ExifTool/Canon.pm +19 -1
  13. data/bin/lib/Image/ExifTool/DJI.pm +91 -29
  14. data/bin/lib/Image/ExifTool/Exif.pm +2 -2
  15. data/bin/lib/Image/ExifTool/FITS.pm +2 -2
  16. data/bin/lib/Image/ExifTool/FLIF.pm +2 -2
  17. data/bin/lib/Image/ExifTool/FlashPix.pm +11 -11
  18. data/bin/lib/Image/ExifTool/Font.pm +1 -1
  19. data/bin/lib/Image/ExifTool/Geolocation.pm +2 -1
  20. data/bin/lib/Image/ExifTool/GoPro.pm +3 -3
  21. data/bin/lib/Image/ExifTool/HP.pm +1 -1
  22. data/bin/lib/Image/ExifTool/ID3.pm +3 -3
  23. data/bin/lib/Image/ExifTool/IPTC.pm +2 -2
  24. data/bin/lib/Image/ExifTool/InDesign.pm +1 -1
  25. data/bin/lib/Image/ExifTool/JPEG.pm +19 -4
  26. data/bin/lib/Image/ExifTool/Jpeg2000.pm +6 -6
  27. data/bin/lib/Image/ExifTool/M2TS.pm +39 -9
  28. data/bin/lib/Image/ExifTool/MXF.pm +2 -2
  29. data/bin/lib/Image/ExifTool/Matroska.pm +1 -1
  30. data/bin/lib/Image/ExifTool/Microsoft.pm +1 -1
  31. data/bin/lib/Image/ExifTool/PDF.pm +15 -15
  32. data/bin/lib/Image/ExifTool/PLIST.pm +1 -1
  33. data/bin/lib/Image/ExifTool/PNG.pm +4 -4
  34. data/bin/lib/Image/ExifTool/Panasonic.pm +1 -1
  35. data/bin/lib/Image/ExifTool/PhaseOne.pm +3 -3
  36. data/bin/lib/Image/ExifTool/Photoshop.pm +63 -3
  37. data/bin/lib/Image/ExifTool/Protobuf.pm +242 -0
  38. data/bin/lib/Image/ExifTool/QuickTime.pm +23 -14
  39. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +395 -109
  40. data/bin/lib/Image/ExifTool/README +4 -1
  41. data/bin/lib/Image/ExifTool/RIFF.pm +3 -3
  42. data/bin/lib/Image/ExifTool/RTF.pm +1 -1
  43. data/bin/lib/Image/ExifTool/Ricoh.pm +3 -3
  44. data/bin/lib/Image/ExifTool/Sony.pm +4 -3
  45. data/bin/lib/Image/ExifTool/TagInfoXML.pm +4 -3
  46. data/bin/lib/Image/ExifTool/TagLookup.pm +6988 -6967
  47. data/bin/lib/Image/ExifTool/TagNames.pod +85 -5
  48. data/bin/lib/Image/ExifTool/VCard.pm +2 -2
  49. data/bin/lib/Image/ExifTool/Validate.pm +3 -3
  50. data/bin/lib/Image/ExifTool/WriteExif.pl +2 -2
  51. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +4 -4
  52. data/bin/lib/Image/ExifTool/WriteXMP.pl +2 -2
  53. data/bin/lib/Image/ExifTool/Writer.pl +17 -17
  54. data/bin/lib/Image/ExifTool/XMP.pm +20 -10
  55. data/bin/lib/Image/ExifTool/XMP2.pl +38 -0
  56. data/bin/lib/Image/ExifTool/ZIP.pm +1 -1
  57. data/bin/lib/Image/ExifTool.pm +109 -82
  58. data/bin/lib/Image/ExifTool.pod +8 -7
  59. data/bin/perl-Image-ExifTool.spec +1 -1
  60. data/lib/exiftool_vendored/version.rb +1 -1
  61. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 374e7e5a3d68eeca0ec6cb6a40919d056e0731958606daa8bed45a7c4c70daba
4
- data.tar.gz: 1263e0b2b35852265b4d5352eae7f35d12cffe0277f916799a8498c75482a9be
3
+ metadata.gz: 53adc02bd5bb808506a883f10c449fd0172d7d82c099a4c5d5a4dbbcb9971d68
4
+ data.tar.gz: 76a6795061f0128324568a9907804699dd0635e94bc7042bf5ba1cb3c40c92e2
5
5
  SHA512:
6
- metadata.gz: 7b5d47b1383f939d76af17239fb4f1e1a486ae619b0d728a010bde7e8ed044de0bfc93d755f8c0a22dfa098ddf997d84f1d7a3f562f07153d1486eee68744929
7
- data.tar.gz: b8ba0c1b6c02546df4e54c6d5c4fe072cbb98bc4b6c5b1d0f1ac323ded4ca43e06ff5bcaaaf879005d37533df86f53262cba0dd87d1a09684f360a50a6d4834c
6
+ metadata.gz: bd68829340a5e18d410b4485e0789bef799d78d2fb7d6ff49612fa4a596b918c86b3515c2cd0ef0d90a0a04c72403a7a2113b86d882c93d5a4e0495d01573bbd
7
+ data.tar.gz: d44cfcbc7dd21d7e74bc26ea46fcdf19f724ccffcb08e7375f21ae58f1544fcc753804348bb61f3dc706b984e5b8bdc43437f296e85a7e8767c1a168be879df9
data/bin/Changes CHANGED
@@ -7,6 +7,52 @@ RSS feed: https://exiftool.org/rss.xml
7
7
  Note: The most recent production release is Version 13.00. (Other versions are
8
8
  considered development releases, and are not uploaded to MetaCPAN.)
9
9
 
10
+ Dec. 14, 2024 - Version 13.08
11
+
12
+ - Decode ShutterCount for Canon EOS R6 Mark II (thanks Agoston Kapitany)
13
+ - Decode a few new Photoshop tags
14
+ - Suppress all duplicate Warning tags and add count to end of message
15
+ - Changed format of bitmask keys in -list x output
16
+ - Internal streamlining of LIGOGPSINFO decoding
17
+ - Fixed issue where some tags were incorrectly shown as writable in -listx
18
+ output
19
+ - Fixed incorrect scaling for GPSSpeed in one LIGOGPSINFO variant
20
+ - Fixed an issue with filename encoding when the -L option is used and the API
21
+ WindowsLongPath option is active
22
+
23
+ Dec. 11, 2024 - Version 13.07
24
+
25
+ - Decode a number of LIGOGPSINFO encrypted and enciphered timed GPS types
26
+ (long overdue, but it took me a couple of years to acquire enough sample
27
+ videos to have a good cross-section of the different formats)
28
+ - Fixed another place where FileSequence could be incremented twice when a -if
29
+ condition was used
30
+ - Fixed a few places where character 0x7f may not have been escaped in string
31
+ values
32
+ - API Changes:
33
+ - Changed default WindowsLongPath option back to 1 after adding a patch to
34
+ fix issue with piping from stdin
35
+
36
+ Dec. 5, 2024 - Version 13.06
37
+
38
+ - Decode timed metadata from MP4 videos of yet another dashcam model
39
+ - Patched issue where FileSequence could increment twice for each file when a
40
+ -if condition was used
41
+ - API Changes:
42
+ - Revert default WindowsLongPath option to the pre-13.05 setting
43
+ until we can solve the pipe problem
44
+
45
+ Dec. 4, 2024 - Version 13.05
46
+
47
+ - Added a new SonyModelID
48
+ - Added support for XMP HDRGainMap and apdi namespaces
49
+ - Decode DJI timed djmd and dbgi protobuf-format metadata
50
+ - Decode APP10 AROT HDRGainCurve and APP2 URN UniformResourceName
51
+ - Decode a couple of new GoPro tags
52
+ - API Changes:
53
+ - Changed default WindowsLongPath option to 1 (please report if this
54
+ causes any problems)
55
+
10
56
  Nov. 26, 2024 - Version 13.04
11
57
 
12
58
  - Added the ability to write GPSDOP and GPSMeasureMode from the -geotag option
@@ -21,6 +67,8 @@ Nov. 26, 2024 - Version 13.04
21
67
  - Renamed an Unknown Photoshop tag
22
68
  - Convert GoPro GPSSpeed and GPSSpeed3D from m/s to km/h
23
69
  - Patched to tolerate XML header in DOCX xml files
70
+ - Fixed incorrect file offsets for tags in some embedded files of -htmldump
71
+ output
24
72
  - Fixed -htmldump output to show the same names for unknown EXIF tags as with
25
73
  the -u option
26
74
 
data/bin/MANIFEST CHANGED
@@ -397,6 +397,7 @@ lib/Image/ExifTool/PhotoMechanic.pm
397
397
  lib/Image/ExifTool/Photoshop.pm
398
398
  lib/Image/ExifTool/PostScript.pm
399
399
  lib/Image/ExifTool/PrintIM.pm
400
+ lib/Image/ExifTool/Protobuf.pm
400
401
  lib/Image/ExifTool/Qualcomm.pm
401
402
  lib/Image/ExifTool/QuickTime.pm
402
403
  lib/Image/ExifTool/QuickTimeStream.pl
data/bin/META.json CHANGED
@@ -50,5 +50,5 @@
50
50
  }
51
51
  },
52
52
  "release_status" : "stable",
53
- "version" : "13.04"
53
+ "version" : "13.08"
54
54
  }
data/bin/META.yml CHANGED
@@ -31,4 +31,4 @@ recommends:
31
31
  Time::HiRes: '0'
32
32
  requires:
33
33
  perl: '5.004'
34
- version: '13.04'
34
+ version: '13.08'
data/bin/README CHANGED
@@ -109,8 +109,8 @@ your home directory, then you would type the following commands in a
109
109
  terminal window to extract and run ExifTool:
110
110
 
111
111
  cd ~/Desktop
112
- gzip -dc Image-ExifTool-13.04.tar.gz | tar -xf -
113
- cd Image-ExifTool-13.04
112
+ gzip -dc Image-ExifTool-13.08.tar.gz | tar -xf -
113
+ cd Image-ExifTool-13.08
114
114
  ./exiftool t/images/ExifTool.jpg
115
115
 
116
116
  Note: These commands extract meta information from one of the test images.
data/bin/exiftool CHANGED
@@ -11,7 +11,7 @@ use strict;
11
11
  use warnings;
12
12
  require 5.004;
13
13
 
14
- my $version = '13.04';
14
+ my $version = '13.08';
15
15
 
16
16
  # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
17
17
  my $exePath;
@@ -1918,7 +1918,7 @@ if (@dbKeys) {
1918
1918
  print $vout "Imported entry for '${_}' (full path: '${absPath}')\n";
1919
1919
  }
1920
1920
  } elsif ($verbose and $verbose > 1) {
1921
- print $vout "Imported entry for '${_}' (non-existent file)\n";
1921
+ print $vout "Imported entry for '${_}' (no full path)\n";
1922
1922
  }
1923
1923
  }
1924
1924
  }
@@ -2172,7 +2172,11 @@ sub GetImageInfo($$)
2172
2172
  }
2173
2173
  # can't make use of $info if verbose because we must reprocess
2174
2174
  # the file anyway to generate the verbose output
2175
- undef $info if $verbose or defined $fastCondition or defined $diff;
2175
+ # (also if writing just to avoid double-incrementing FileSequence)
2176
+ if ($isWriting or $verbose or defined $fastCondition or defined $diff) {
2177
+ undef $info;
2178
+ --$$et{FILE_SEQUENCE};
2179
+ }
2176
2180
  } elsif ($file =~ s/^(\@JSON:)(.*)/$1/) {
2177
2181
  # read JSON file from command line
2178
2182
  my $dat = $2;
@@ -3636,7 +3640,7 @@ sub EscapeJSON($;$)
3636
3640
  if ($json < 2) { # JSON
3637
3641
  $str =~ tr/\0//d; # remove all nulls
3638
3642
  # escape other control characters with \u
3639
- $str =~ s/([\0-\x1f])/sprintf("\\u%.4X",ord $1)/sge;
3643
+ $str =~ s/([\0-\x1f\x7f])/sprintf("\\u%.4X",ord $1)/sge;
3640
3644
  # JSON strings must be valid UTF8
3641
3645
  Image::ExifTool::XMP::FixUTF8(\$str) unless $altEnc;
3642
3646
  } else { # PHP
@@ -3644,7 +3648,7 @@ sub EscapeJSON($;$)
3644
3648
  # must escape "$" too for PHP
3645
3649
  $str =~ s/\$/\\\$/sg;
3646
3650
  # escape other control characters with \x
3647
- $str =~ s/([\0-\x1f])/sprintf("\\x%.2X",ord $1)/sge;
3651
+ $str =~ s/([\0-\x1f\x7f])/sprintf("\\x%.2X",ord $1)/sge;
3648
3652
  }
3649
3653
  return '"' . $str . '"'; # return the quoted string
3650
3654
  }
@@ -4163,11 +4167,12 @@ sub ScanDir($$;$)
4163
4167
  }
4164
4168
  $dir =~ /\/$/ or $dir .= '/'; # make sure directory name ends with '/'
4165
4169
  foreach $file (@fileList) {
4170
+ next if $file eq '.' or $file eq '..';
4166
4171
  my $path = "$dir$file";
4167
4172
  if ($et->IsDirectory($path)) {
4168
4173
  next unless $recurse;
4169
4174
  # ignore directories starting with "." by default
4170
- next if $file =~ /^\./ and ($recurse == 1 or $file eq '.' or $file eq '..');
4175
+ next if $file =~ /^\./ and $recurse == 1;
4171
4176
  next if $ignore{$file} or ($ignore{SYMLINKS} and -l $path);
4172
4177
  ScanDir($et, $path, $list);
4173
4178
  last if $end;
@@ -4315,14 +4320,15 @@ sub AbsPath($)
4315
4320
  {
4316
4321
  my $file = shift;
4317
4322
  my $path;
4318
- if (defined $file and eval { require Cwd }) {
4319
- $path = eval { Cwd::abs_path($file) };
4320
- # make the delimiters and case consistent
4321
- # (abs_path is very inconsistent about what it returns in Windows)
4322
- if (defined $path and Image::ExifTool::IsPC()) {
4323
- $path =~ tr/\\/\//;
4324
- $path = lc $path;
4323
+ if (defined $file) {
4324
+ return undef if $file eq '*'; # (CSV SourceFile may be '*' -- no absolute path for that)
4325
+ if ($^O eq 'MSWin32' and $mt->Options('WindowsLongPath')) {
4326
+ $path = $mt->WindowsLongPath($file);
4327
+ } elsif (eval { require Cwd }) {
4328
+ local $SIG{'__WARN__'} = sub { };
4329
+ $path = eval { Cwd::abs_path($file) };
4325
4330
  }
4331
+ $path =~ tr/\\/\// if $^O eq 'MSWin32' and defined $path; # use forward slashes
4326
4332
  }
4327
4333
  return $path;
4328
4334
  }
@@ -5907,7 +5913,7 @@ with this command:
5907
5913
 
5908
5914
  produces output like this:
5909
5915
 
5910
- -- Generated by ExifTool 13.04 --
5916
+ -- Generated by ExifTool 13.08 --
5911
5917
  File: a.jpg - 2003:10:31 15:44:19
5912
5918
  (f/5.6, 1/60s, ISO 100)
5913
5919
  File: b.jpg - 2006:05:23 11:57:38
@@ -6022,7 +6028,8 @@ import). May be combined with B<-s> to print tag names instead of
6022
6028
  descriptions, or B<-S> to print tag values only, tab-delimited on a single
6023
6029
  line. The B<-t> option may be combined with B<-j>, B<-php> or B<-X> to add
6024
6030
  tag table information (C<table>, tag C<id>, and C<index> for cases where
6025
- multiple conditional tags exist with the same ID).
6031
+ multiple conditional tags exist with the same ID), which allows the
6032
+ corresponding tag to be located in the B<-listx> output.
6026
6033
 
6027
6034
  =item B<-T> (B<-table>)
6028
6035
 
@@ -6781,14 +6788,14 @@ written (provided they can be calculated from the track log, and they are
6781
6788
  supported by the destination metadata format): GPSLatitude, GPSLatitudeRef,
6782
6789
  GPSLongitude, GPSLongitudeRef, GPSAltitude, GPSAltitudeRef, GPSDateStamp,
6783
6790
  GPSTimeStamp, GPSDateTime, GPSTrack, GPSTrackRef, GPSSpeed, GPSSpeedRef,
6784
- GPSImgDirection, GPSImgDirectionRef, GPSPitch, GPSRoll, GPSCoordinates,
6785
- AmbientTemperature and CameraElevationAngle. By default, in image files
6786
- tags are created in EXIF, and updated in XMP only if they already exist. In
6787
- QuickTime-format files GPSCoordinates is created in the preferred location
6788
- (ItemList by default) as well as in XMP. However, C<EXIF:Geotime>,
6789
- C<XMP:Geotime> or C<QuickTime:Geotime> may be specified to write to write
6790
- only to one group. Also, C<ItemList:Geotime>, C<Keys:Geotime> or
6791
- C<UserData:Geotime> may be used to write to a specific location in
6791
+ GPSImgDirection, GPSImgDirectionRef, GPSMeasureMode, GPSDOP, GPSPitch,
6792
+ GPSRoll, GPSCoordinates, AmbientTemperature and CameraElevationAngle. By
6793
+ default, in image files tags are created in EXIF, and updated in XMP only if
6794
+ they already exist. In QuickTime-format files GPSCoordinates is created in
6795
+ the preferred location (ItemList by default) as well as in XMP. However,
6796
+ C<EXIF:Geotime>, C<XMP:Geotime> or C<QuickTime:Geotime> may be specified to
6797
+ write to write only to one group. Also, C<ItemList:Geotime>, C<Keys:Geotime>
6798
+ or C<UserData:Geotime> may be used to write to a specific location in
6792
6799
  QuickTime-format files. Note that GPSPitch and GPSRoll are non-standard,
6793
6800
  and require user-defined tags in order to be written.
6794
6801
 
@@ -231,7 +231,7 @@ sub ProcessAIFF($$)
231
231
  $et->Warn('End of processing at large chunk (LargeFileSupport not enabled)');
232
232
  last;
233
233
  } elsif ($et->Options('LargeFileSupport') eq '2') {
234
- $et->WarnOnce('Skipping large chunk (LargeFileSupport is 2)');
234
+ $et->Warn('Skipping large chunk (LargeFileSupport is 2)');
235
235
  }
236
236
  }
237
237
  if ($tagInfo) {
@@ -217,7 +217,7 @@ sub ProcessAPE($$)
217
217
  $val = \$buf2;
218
218
  # extract cover art description separately (hackitty hack)
219
219
  if ($tag =~ /^Cover Art/) {
220
- $buf2 =~ s/^([\x20-\x7f]*)\0//;
220
+ $buf2 =~ s/^([\x20-\x7e]*)\0//;
221
221
  if ($1) {
222
222
  my $t = "$tag Desc";
223
223
  my $v = $1;
@@ -781,7 +781,7 @@ sub ProcessASF($$;$)
781
781
  $err = 'Invalid ASF object size';
782
782
  } elsif ($et->Options('LargeFileSupport')) {
783
783
  if ($et->Options('LargeFileSupport') eq '2') {
784
- $et->WarnOnce('Skipping large ASF object (LargeFileSupport is 2)');
784
+ $et->Warn('Skipping large ASF object (LargeFileSupport is 2)');
785
785
  }
786
786
  if ($raf->Seek($size, 1)) {
787
787
  $et->VPrint(0, " Skipped large ASF object ($size bytes)\n");
@@ -35,7 +35,7 @@ use Image::ExifTool::Sony;
35
35
  use Image::ExifTool::Validate;
36
36
  use Image::ExifTool::MacOS;
37
37
 
38
- $VERSION = '3.58';
38
+ $VERSION = '3.59';
39
39
  @ISA = qw(Exporter);
40
40
 
41
41
  sub NumbersFirst($$);
@@ -869,7 +869,8 @@ sub new
869
869
  my $processBinaryData = ($$table{PROCESS_PROC} and (
870
870
  $$table{PROCESS_PROC} eq \&Image::ExifTool::ProcessBinaryData or
871
871
  $$table{PROCESS_PROC} eq \&Image::ExifTool::Nikon::ProcessNikonEncrypted or
872
- $$table{PROCESS_PROC} eq \&Image::ExifTool::Sony::ProcessEnciphered));
872
+ $$table{PROCESS_PROC} eq \&Image::ExifTool::Sony::ProcessEnciphered) or
873
+ $$table{VARS} and $$table{VARS}{IS_BINARY});
873
874
  if ($$vars{ID_LABEL} or $processBinaryData) {
874
875
  my $s = $$table{FORMAT} ? Image::ExifTool::FormatSize($$table{FORMAT}) || 1 : 1;
875
876
  $binaryTable = 1;
@@ -1248,7 +1249,7 @@ TagID: foreach $tagID (@keys) {
1248
1249
  }
1249
1250
  } elsif ($$tagInfo{PrintString} or not /^[+-]?(?=\d|\.\d)\d*(\.\d*)?$/) {
1250
1251
  # translate unprintable values
1251
- if ($index =~ s/([\x00-\x1f\x80-\xff])/sprintf("\\x%.2x",ord $1)/eg) {
1252
+ if ($index =~ s/([\x00-\x1f\x7f-\xff])/sprintf("\\x%.2x",ord $1)/eg) {
1252
1253
  $index = qq{"$index"};
1253
1254
  } else {
1254
1255
  $index = qq{'${index}'};
@@ -88,7 +88,7 @@ sub ProcessCTMD($$$);
88
88
  sub ProcessExifInfo($$$);
89
89
  sub SwapWords($);
90
90
 
91
- $VERSION = '4.85';
91
+ $VERSION = '4.86';
92
92
 
93
93
  # Note: Removed 'USM' from 'L' lenses since it is redundant - PH
94
94
  # (or is it? Ref 32 shows 5 non-USM L-type lenses)
@@ -1404,6 +1404,11 @@ my %offOn = ( 0 => 'Off', 1 => 'On' );
1404
1404
  Condition => '$$self{Model} =~ /\bEOS R[56]$/',
1405
1405
  SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfoR6' },
1406
1406
  },
1407
+ {
1408
+ Name => 'CanonCameraInfoR6m2',
1409
+ Condition => '$$self{Model} =~ /\bEOS R6m2$/',
1410
+ SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfoR6m2' },
1411
+ },
1407
1412
  {
1408
1413
  Name => 'CanonCameraInfoG5XII',
1409
1414
  Condition => '$$self{Model} =~ /\bG5 X Mark II$/',
@@ -4752,6 +4757,19 @@ my %ciMaxFocal = (
4752
4757
  # 0x0bb7 - counts down during focus stack (ref forum16111)
4753
4758
  );
4754
4759
 
4760
+ %Image::ExifTool::Canon::CameraInfoR6m2 = (
4761
+ %binaryDataAttrs,
4762
+ FIRST_ENTRY => 0,
4763
+ PRIORITY => 0,
4764
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
4765
+ NOTES => 'CameraInfo tags for the EOS R6 Mark II.',
4766
+ 0x0d29 => { #AgostonKapitany
4767
+ Name => 'ShutterCount',
4768
+ Format => 'int32u',
4769
+ Notes => 'includes electronic + mechanical shutter',
4770
+ },
4771
+ );
4772
+
4755
4773
  # ref https://exiftool.org/forum/index.php?topic=15356.0
4756
4774
  %Image::ExifTool::Canon::CameraInfoG5XII = (
4757
4775
  %binaryDataAttrs,
@@ -15,11 +15,11 @@ use Image::ExifTool qw(:DataAccess :Utils);
15
15
  use Image::ExifTool::Exif;
16
16
  use Image::ExifTool::XMP;
17
17
  use Image::ExifTool::GPS;
18
+ use Image::ExifTool::Protobuf;
18
19
 
19
- $VERSION = '1.09';
20
+ $VERSION = '1.10';
20
21
 
21
22
  sub ProcessDJIInfo($$$);
22
- sub Process_djmd($$$);
23
23
 
24
24
  my %convFloat2 = (
25
25
  PrintConv => 'sprintf("%+.2f", $val)',
@@ -187,34 +187,96 @@ my %convFloat2 = (
187
187
  },
188
188
  );
189
189
 
190
- # TODO - eventually add ability to decode this?
191
- %Image::ExifTool::DJI::djmd = (
192
- PROCESS_PROC => \&Process_djmd,
190
+ # metadata in protobuf format (djmd and dbgi meta types, ref PH)
191
+ %Image::ExifTool::DJI::Protobuf = (
192
+ GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Location' },
193
+ TAG_PREFIX => '',
194
+ PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
195
+ NOTES => q{
196
+ Tags found in protobuf-format DJI meta djmd and dbgi timed metadata. Only a
197
+ few tags are currently known, but unknown djmd tags may be extracted by
198
+ setting the Unknown option to 1 (or 2 to also extract unknown dbgi debug
199
+ tags). Tag ID's are composed of the corresponding .proto file name combined
200
+ with the hierarchical protobuf field numbers. The "dvtm_AVATA2.proto" file
201
+ is used by the DJI Avanta 2, and "dvtm_ac203.proto" by the OsmoAction4.
202
+ },
203
+ Protocol => { },
204
+ # dvtm_ac203_1-1-6 - some version number
205
+ 'dvtm_ac203_1-1-10' => 'Model',
206
+ 'dvtm_ac203_2-3-1' => { Name => 'FrameWidth', Format => 'unsigned' },
207
+ 'dvtm_ac203_2-3-2' => { Name => 'FrameHeight', Format => 'unsigned' },
208
+ 'dvtm_ac203_2-3-3' => { Name => 'FrameRate', Format => 'float' },
209
+ # dvtm_ac203_3-4-1-4 - model code?
210
+ 'dvtm_ac203_3-4-2-1-1' => {
211
+ Name => 'CoordinateUnits',
212
+ Format => 'unsigned',
213
+ # don't extract this -- just convert to degrees
214
+ RawConv => '$$self{CoordUnits} = $val; undef',
215
+ Hidden => 1,
216
+ # PrintConv => { 0 => 'Radians', 1 => 'Degrees' },
217
+ },
218
+ 'dvtm_ac203_3-4-2-1-2' => {
219
+ Name => 'GPSLatitude',
220
+ Format => 'double',
221
+ # set ExifTool GPSLatitude/GPSLongitude members so GPSDateTime will be generated if necessary
222
+ RawConv => '$$self{GPSLatitude} = $$self{CoordUnits} ? $val : $val * 180 / 3.141592653589793', # (NC)
223
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
224
+ },
225
+ 'dvtm_ac203_3-4-2-1-3' => {
226
+ Name => 'GPSLongitude',
227
+ Format => 'double',
228
+ RawConv => '$$self{GPSLongitude} = $$self{CoordUnits} ? $val : $val * 180 / 3.141592653589793', # (NC)
229
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
230
+ },
231
+ 'dvtm_ac203_3-4-2-2' => {
232
+ Name => 'GPSAltitude',
233
+ Format => 'unsigned',
234
+ ValueConv => '$val / 1000',
235
+ },
236
+ 'dvtm_ac203_3-4-2-6-1' => {
237
+ Name => 'GPSDateTime',
238
+ Format => 'string',
239
+ Groups => { 2 => 'Time' },
240
+ RawConv => '$$self{GPSDateTime} = $val',
241
+ ValueConv => '$val =~ tr/-/:/; $val',
242
+ PrintConv => '$self->ConvertDateTime($val)',
243
+ },
244
+ # dvtm_AVATA2_1-1-2 - some version number
245
+ # dvtm_AVATA2_1-1-3 - some version number
246
+ 'dvtm_AVATA2_1-1-10' => 'Model',
247
+ 'dvtm_AVATA2_2-2-3-1' => 'SerialNumber', # (NC)
248
+ 'dvtm_AVATA2_2-3-1' => { Name => 'FrameWidth', Format => 'unsigned' },
249
+ 'dvtm_AVATA2_2-3-2' => { Name => 'FrameHeight', Format => 'unsigned' },
250
+ 'dvtm_AVATA2_2-3-3' => { Name => 'FrameRate', Format => 'float' },
251
+ # dvtm_AVATA2_3-1-1 - frame number (starting at 1)
252
+ 'dvtm_AVATA2_3-1-2' => { # (also 3-2-1-6 and 3-4-1-6)
253
+ Name => 'TimeStamp',
254
+ Format => 'unsigned',
255
+ # milliseconds, but I don't know what the zero is
256
+ ValueConv => '$val / 1e6',
257
+ },
258
+ # dvtm_AVATA2_3-2-1-4 - model code?
259
+ # dvtm_AVATA2_3-4-1-4 - model code?
260
+ 'dvtm_AVATA2_3-4-4-1-1' => { # (NC) (default seems to be radians if missing)
261
+ Name => 'CoordinateDegrees',
262
+ Format => 'unsigned',
263
+ RawConv => '$$self{CoordDegrees} = $val; undef',
264
+ Hidden => 1,
265
+ },
266
+ 'dvtm_AVATA2_3-4-4-1-2' => {
267
+ Name => 'GPSLatitude',
268
+ Format => 'double',
269
+ RawConv => '$$self{GPSLatitude} = $$self{CoordDegrees} ? $val : $val * 180 / 3.141592653589793', # (NC)
270
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
271
+ },
272
+ 'dvtm_AVATA2_3-4-4-1-3' => {
273
+ Name => 'GPSLongitude',
274
+ Format => 'double',
275
+ RawConv => '$$self{GPSLongitude} = $$self{CoordDegrees} ? $val : $val * 180 / 3.141592653589793', # (NC)
276
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
277
+ },
193
278
  );
194
279
 
195
- #------------------------------------------------------------------------------
196
- # Process DJI djmd timed data from Action4 videos (ref PH)
197
- # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
198
- # Returns: 1 on success
199
- # TODO: work in progress
200
- sub Process_djmd($$$)
201
- {
202
- my ($et, $dirInfo, $tagTbl) = @_;
203
- my $dataPt = $$dirInfo{DataPt};
204
- my ($pos, $bit, $val) = (6, 0, 0);
205
- for (;;) {
206
- my $v = Get8u($dataPt, $pos);
207
- $val += ($v & 0x7f) << $bit;
208
- last unless $v & 0x80;
209
- ++$pos;
210
- $bit += 7;
211
- }
212
- $pos += 49;
213
- my @a = unpack("x${pos}fxfxfxfx3fxfxf", $$dataPt);
214
- print "$val @a\n";
215
- return 1;
216
- }
217
-
218
280
  #------------------------------------------------------------------------------
219
281
  # Process DJI info (ref PH)
220
282
  # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
@@ -233,7 +295,7 @@ sub ProcessDJIInfo($$$)
233
295
  while ($$dataPt =~ /\G\[(.*?)\](?=(\[|$))/sg) {
234
296
  my ($tag, $val) = split /:/, $1, 2;
235
297
  next unless defined $tag and defined $val;
236
- if ($val =~ /^([\x20-\x7f]+)\0*$/) {
298
+ if ($val =~ /^([\x20-\x7e]+)\0*$/) {
237
299
  $val = $1;
238
300
  } else {
239
301
  my $buff = $val;
@@ -6186,7 +6186,7 @@ sub ProcessExif($$$)
6186
6186
  if ($$dirInfo{DirName} eq 'MakerNotes' and $$et{FileType} eq 'CR3' and
6187
6187
  $$dirInfo{Parent} and $$dirInfo{Parent} eq 'ExifIFD')
6188
6188
  {
6189
- $et->WarnOnce("MakerNotes shouldn't exist ExifIFD of CR3 image", 1);
6189
+ $et->Warn("MakerNotes shouldn't exist ExifIFD of CR3 image", 1);
6190
6190
  }
6191
6191
  # set flag to calculate image data hash if requested
6192
6192
  $doHash = 1 if $$et{ImageDataHash} and (($$et{FILE_TYPE} eq 'TIFF' and not $base and not $inMakerNotes) or
@@ -6656,7 +6656,7 @@ sub ProcessExif($$$)
6656
6656
  if ($count > 500 and $formatStr !~ /^(undef|string|binary)$/ and
6657
6657
  (not $tagInfo or $$tagInfo{LongBinary} or $warned) and not $$et{OPTIONS}{IgnoreMinorErrors})
6658
6658
  {
6659
- $et->WarnOnce('Not decoding some large array(s). Ignore minor errors to decode', 2) unless $warned;
6659
+ $et->Warn('Not decoding some large array(s). Ignore minor errors to decode', 2) unless $warned;
6660
6660
  next if $$et{TAGS_FROM_FILE}; # don't generate bogus value when copying tags
6661
6661
  $val = "(large array of $count $formatStr values)";
6662
6662
  } else {
@@ -61,7 +61,7 @@ sub ProcessFITS($$)
61
61
  my $key = substr($buff, 0, 8);
62
62
  $key =~ s/ +$//; # remove trailing space from key
63
63
  if ($key eq 'CONTINUE') {
64
- defined $continue or $et->WarnOnce('Unexpected FITS CONTINUE keyword'), next;
64
+ defined $continue or $et->Warn('Unexpected FITS CONTINUE keyword'), next;
65
65
  } else {
66
66
  if (defined $continue) {
67
67
  # the previous value wasn't continued, so store with the trailing '&'
@@ -104,7 +104,7 @@ sub ProcessFITS($$)
104
104
  # check for possible continuation, removing trailing '&'
105
105
  $val =~ s/\&$// and $continue = $val, next;
106
106
  } elsif (defined $continue) {
107
- $et->WarnOnce('Invalid FITS CONTINUE value');
107
+ $et->Warn('Invalid FITS CONTINUE value');
108
108
  next;
109
109
  } else {
110
110
  $val =~ s/ *(\/.*)?$//; # remove trailing spaces and comment
@@ -244,7 +244,7 @@ sub WriteFLIF($$)
244
244
  }
245
245
  }
246
246
  } else {
247
- $et->WarnOnce('Install IO::Compress::RawDeflate to write FLIF metadata');
247
+ $et->Warn('Install IO::Compress::RawDeflate to write FLIF metadata');
248
248
  }
249
249
  Write($outfile, $tag, SetVarInt(length $buff), $buff) or return -1;
250
250
  } elsif (not defined $soi) {
@@ -301,7 +301,7 @@ sub ProcessFLIF($$)
301
301
  $et->Warn("Error inflating FLIF $tag chunk");
302
302
  }
303
303
  } else {
304
- $et->WarnOnce('Install IO::Uncompress::RawInflate to decode FLIF metadata');
304
+ $et->Warn('Install IO::Uncompress::RawInflate to decode FLIF metadata');
305
305
  }
306
306
  } else {
307
307
  $raf->Seek($size, 1) or $et->Warn('Seek error'), last;
@@ -1449,7 +1449,7 @@ sub ReadFPXValue($$$$$;$$)
1449
1449
  $noPad = 1; # values sometimes aren't padded inside vectors!!
1450
1450
  my $size = $oleFormatSize{VT_VECTOR};
1451
1451
  if ($valPos + $size > $dirEnd) {
1452
- $et->WarnOnce('Incorrect FPX VT_VECTOR size');
1452
+ $et->Warn('Incorrect FPX VT_VECTOR size');
1453
1453
  last;
1454
1454
  }
1455
1455
  $count = Get32u($dataPt, $valPos);
@@ -1457,14 +1457,14 @@ sub ReadFPXValue($$$$$;$$)
1457
1457
  $valPos += 4;
1458
1458
  } else {
1459
1459
  # can't yet handle this property flag
1460
- $et->WarnOnce('Unknown FPX property');
1460
+ $et->Warn('Unknown FPX property');
1461
1461
  last;
1462
1462
  }
1463
1463
  }
1464
1464
  unless ($format =~ /^VT_/) {
1465
1465
  my $size = Image::ExifTool::FormatSize($format) * $count;
1466
1466
  if ($valPos + $size > $dirEnd) {
1467
- $et->WarnOnce("Incorrect FPX $format size");
1467
+ $et->Warn("Incorrect FPX $format size");
1468
1468
  last;
1469
1469
  }
1470
1470
  @vals = ReadValue($dataPt, $valPos, $format, $count, $size);
@@ -1476,7 +1476,7 @@ sub ReadFPXValue($$$$$;$$)
1476
1476
  my ($item, $val, $len);
1477
1477
  for ($item=0; $item<$count; ++$item) {
1478
1478
  if ($valPos + $size > $dirEnd) {
1479
- $et->WarnOnce("Truncated FPX $format value");
1479
+ $et->Warn("Truncated FPX $format value");
1480
1480
  last;
1481
1481
  }
1482
1482
  # sometimes VT_VECTOR items are padded to even 4-byte boundaries, and sometimes they aren't
@@ -1528,7 +1528,7 @@ sub ReadFPXValue($$$$$;$$)
1528
1528
  $len = Get32u($dataPt, $valPos);
1529
1529
  $len *= 2 if $format eq 'VT_LPWSTR'; # convert to byte count
1530
1530
  if ($valPos + $len + 4 > $dirEnd) {
1531
- $et->WarnOnce("Truncated $format value");
1531
+ $et->Warn("Truncated $format value");
1532
1532
  last;
1533
1533
  }
1534
1534
  $val = substr($$dataPt, $valPos + 4, $len);
@@ -1551,7 +1551,7 @@ sub ReadFPXValue($$$$$;$$)
1551
1551
  } elsif ($format eq 'VT_BLOB' or $format eq 'VT_CF') {
1552
1552
  my $len = Get32u($dataPt, $valPos); # (use local $len because we always expect padding)
1553
1553
  if ($valPos + $len + 4 > $dirEnd) {
1554
- $et->WarnOnce("Truncated $format value");
1554
+ $et->Warn("Truncated $format value");
1555
1555
  last;
1556
1556
  }
1557
1557
  $val = substr($$dataPt, $valPos + 4, $len);
@@ -1627,7 +1627,7 @@ sub ProcessContents($$$)
1627
1627
  while ($$dataPt =~ /\x0bTargetRole1(?:.\x80|\xff\xff.\0.\0Vn(\w+))\0\0\x01.{4}(.{24})/sg) {
1628
1628
  my ($index, @coords) = unpack('Vx4V4', $2);
1629
1629
  next if $index == 0xffffffff;
1630
- $$et{IeImg_lkup}{$index} and $et->WarnOnce('Duplicate image index');
1630
+ $$et{IeImg_lkup}{$index} and $et->Warn('Duplicate image index');
1631
1631
  $$et{IeImg_lkup}{$index} = "@coords";
1632
1632
  $$et{IeImg_class}{$index} = $1 if $1;
1633
1633
  }
@@ -1661,7 +1661,7 @@ sub ProcessWordDocument($$$)
1661
1661
  my $dirLen = length $$dataPt;
1662
1662
  # validate the FIB signature
1663
1663
  unless ($dirLen > 2 and Get16u($dataPt,0) == 0xa5ec) {
1664
- $et->WarnOnce('Invalid FIB signature', 1);
1664
+ $et->Warn('Invalid FIB signature', 1);
1665
1665
  return 0;
1666
1666
  }
1667
1667
  $et->ProcessBinaryData($dirInfo, $tagTablePtr); # process FIB
@@ -2098,7 +2098,7 @@ sub ProcessFPXR($$$)
2098
2098
  my $overlap = length($$obj{Stream}) - $offset;
2099
2099
  my $start = $dirStart + 13;
2100
2100
  if ($overlap < 0 or $dirLen - $overlap < 13) {
2101
- $et->WarnOnce("Bad FPXR stream $index offset",1);
2101
+ $et->Warn("Bad FPXR stream $index offset",1);
2102
2102
  } else {
2103
2103
  # ignore any overlapping data in this segment
2104
2104
  # (this seems to be the convention)
@@ -2338,7 +2338,7 @@ sub ProcessFPX($$)
2338
2338
  $tag =~ s/\0.*//s; # truncate at null (in case length was wrong)
2339
2339
 
2340
2340
  if ($tag eq '0' and not defined $ee) {
2341
- $et->WarnOnce('Use the ExtractEmbedded option to extract embedded information', 3);
2341
+ $et->Warn('Use the ExtractEmbedded option to extract embedded information', 3);
2342
2342
  }
2343
2343
  my $sect = Get32u(\$dir, $pos + 0x74); # start sector number
2344
2344
  my $size = Get32u(\$dir, $pos + 0x78); # stream length
@@ -2441,7 +2441,7 @@ sub ProcessFPX($$)
2441
2441
  my $subTablePtr = GetTagTable($$subdir{TagTable});
2442
2442
  $et->ProcessDirectory(\%dirInfo, $subTablePtr, $$subdir{ProcessProc});
2443
2443
  } elsif (defined $size and $size > length($buff)) {
2444
- $et->WarnOnce('Truncated object');
2444
+ $et->Warn('Truncated object');
2445
2445
  } else {
2446
2446
  $buff = substr($buff, 0, $size) if defined $size and $size < length($buff);
2447
2447
  if ($tag =~ /^IeImg_0*(\d+)$/) {
@@ -405,7 +405,7 @@ sub ProcessOTF($$)
405
405
  next;
406
406
  }
407
407
  if ($verbose) {
408
- $tag =~ s/([\0-\x1f\x80-\xff])/sprintf('\x%.2x',ord $1)/ge;
408
+ $tag =~ s/([\0-\x1f\x7f-\xff])/sprintf('\x%.2x',ord $1)/ge;
409
409
  my $str = sprintf("%s%d) Tag '%s' (offset 0x%.4x, %d bytes)\n",
410
410
  $$et{INDENT}, $pos/16, $tag, $offset, $size);
411
411
  $et->VPrint(0, $str);