exiftool_vendored 12.76.1 → 12.80.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 +79 -4
  3. data/bin/MANIFEST +27 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +3 -3
  7. data/bin/config_files/acdsee.config +37 -57
  8. data/bin/config_files/example.config +16 -2
  9. data/bin/exiftool +84 -29
  10. data/bin/lib/Image/ExifTool/Canon.pm +12 -9
  11. data/bin/lib/Image/ExifTool/CanonVRD.pm +7 -1
  12. data/bin/lib/Image/ExifTool/Exif.pm +52 -4
  13. data/bin/lib/Image/ExifTool/FujiFilm.pm +3 -0
  14. data/bin/lib/Image/ExifTool/GPS.pm +5 -3
  15. data/bin/lib/Image/ExifTool/GeoLang/cs.pm +978 -0
  16. data/bin/lib/Image/ExifTool/GeoLang/de.pm +1975 -0
  17. data/bin/lib/Image/ExifTool/GeoLang/en_ca.pm +44 -0
  18. data/bin/lib/Image/ExifTool/GeoLang/en_gb.pm +124 -0
  19. data/bin/lib/Image/ExifTool/GeoLang/es.pm +2921 -0
  20. data/bin/lib/Image/ExifTool/GeoLang/fi.pm +1116 -0
  21. data/bin/lib/Image/ExifTool/GeoLang/fr.pm +3171 -0
  22. data/bin/lib/Image/ExifTool/GeoLang/it.pm +2750 -0
  23. data/bin/lib/Image/ExifTool/GeoLang/ja.pm +10256 -0
  24. data/bin/lib/Image/ExifTool/GeoLang/ko.pm +4499 -0
  25. data/bin/lib/Image/ExifTool/GeoLang/nl.pm +1270 -0
  26. data/bin/lib/Image/ExifTool/GeoLang/pl.pm +3019 -0
  27. data/bin/lib/Image/ExifTool/GeoLang/ru.pm +18220 -0
  28. data/bin/lib/Image/ExifTool/GeoLang/sk.pm +441 -0
  29. data/bin/lib/Image/ExifTool/GeoLang/sv.pm +714 -0
  30. data/bin/lib/Image/ExifTool/GeoLang/tr.pm +452 -0
  31. data/bin/lib/Image/ExifTool/GeoLang/zh_cn.pm +2225 -0
  32. data/bin/lib/Image/ExifTool/GeoLang/zh_tw.pm +72 -0
  33. data/bin/lib/Image/ExifTool/Geolocation.dat +0 -0
  34. data/bin/lib/Image/ExifTool/Geolocation.pm +775 -0
  35. data/bin/lib/Image/ExifTool/Geotag.pm +8 -1
  36. data/bin/lib/Image/ExifTool/HtmlDump.pm +2 -1
  37. data/bin/lib/Image/ExifTool/Import.pm +5 -2
  38. data/bin/lib/Image/ExifTool/JSON.pm +15 -10
  39. data/bin/lib/Image/ExifTool/MWG.pm +1 -0
  40. data/bin/lib/Image/ExifTool/MacOS.pm +19 -4
  41. data/bin/lib/Image/ExifTool/Nikon.pm +2 -2
  42. data/bin/lib/Image/ExifTool/Ogg.pm +3 -2
  43. data/bin/lib/Image/ExifTool/Olympus.pm +3 -1
  44. data/bin/lib/Image/ExifTool/OpenEXR.pm +17 -17
  45. data/bin/lib/Image/ExifTool/PDF.pm +5 -5
  46. data/bin/lib/Image/ExifTool/Pentax.pm +1 -1
  47. data/bin/lib/Image/ExifTool/QuickTime.pm +183 -11
  48. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +253 -237
  49. data/bin/lib/Image/ExifTool/README +6 -5
  50. data/bin/lib/Image/ExifTool/TagLookup.pm +2624 -2520
  51. data/bin/lib/Image/ExifTool/TagNames.pod +184 -4
  52. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +15 -1
  53. data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  54. data/bin/lib/Image/ExifTool/Writer.pl +59 -8
  55. data/bin/lib/Image/ExifTool/XMP.pm +17 -2
  56. data/bin/lib/Image/ExifTool/XMP2.pl +64 -0
  57. data/bin/lib/Image/ExifTool.pm +249 -47
  58. data/bin/lib/Image/ExifTool.pod +57 -25
  59. data/bin/perl-Image-ExifTool.spec +2 -2
  60. data/lib/exiftool_vendored/version.rb +1 -1
  61. metadata +22 -2
@@ -1109,7 +1109,7 @@ sub SetGeoValues($$;$)
1109
1109
  $iExt = $i1;
1110
1110
  }
1111
1111
  if (abs($time - $tn) > $geoMaxExtSecs) {
1112
- $err or $err = 'Time is too far from nearest GPS fix'.' '.abs($time-$tn).' '.$geoMaxExtSecs;
1112
+ $err or $err = 'Time is too far from nearest GPS fix'.' '.abs($time-$tn).' > '.$geoMaxExtSecs;
1113
1113
  $et->VPrint(2, ' Nearest fix: ', PrintFixTime($tn), "\n") if $verbose > 2;
1114
1114
  $fix = { } if $$geotag{DateTimeOnly};
1115
1115
  } else {
@@ -1218,6 +1218,13 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
1218
1218
  $coords .= " $alt";
1219
1219
  }
1220
1220
  @r = $et->SetNewValue(GPSCoordinates => $coords, %opts);
1221
+ # also Geolocate if specified
1222
+ my $nvHash;
1223
+ my $geoloc = $et->GetNewValue('Geolocate', \$nvHash);
1224
+ if ($geoloc and lc($geoloc) eq 'geotag') {
1225
+ $geoloc = ($$nvHash{WantGroup} ? "$$nvHash{WantGroup}:" : '') . 'Geolocate';
1226
+ $et->SetNewValue($geoloc => "$$fix{lat},$$fix{lon}");
1227
+ }
1221
1228
  return $err if $qt; # all done if writing to QuickTime only
1222
1229
  # (capture error messages by calling SetNewValue in list context)
1223
1230
  @r = $et->SetNewValue(GPSLatitude => $$fix{lat}, %opts);
@@ -13,7 +13,7 @@ use vars qw($VERSION);
13
13
  use Image::ExifTool; # only for FinishTiffDump()
14
14
  use Image::ExifTool::HTML qw(EscapeHTML);
15
15
 
16
- $VERSION = '1.41';
16
+ $VERSION = '1.42';
17
17
 
18
18
  sub DumpTable($$$;$$$$$$);
19
19
  sub Open($$$;@);
@@ -769,6 +769,7 @@ sub FinishTiffDump($$$)
769
769
  PreviewImageStart => 'PreviewImageLength',
770
770
  JpgFromRawStart => 'JpgFromRawLength',
771
771
  OtherImageStart => 'OtherImageLength',
772
+ PreviewJXLStart => 'PreviewJXLLength',
772
773
  ImageOffset => 'ImageByteCount',
773
774
  AlphaOffset => 'AlphaByteCount',
774
775
  MPImageStart => 'MPImageLength',
@@ -12,7 +12,7 @@ require Exporter;
12
12
 
13
13
  use vars qw($VERSION @ISA @EXPORT_OK);
14
14
 
15
- $VERSION = '1.11';
15
+ $VERSION = '1.12';
16
16
  @ISA = qw(Exporter);
17
17
  @EXPORT_OK = qw(ReadCSV ReadJSON);
18
18
 
@@ -238,7 +238,7 @@ Tok: for (;;) {
238
238
 
239
239
  #------------------------------------------------------------------------------
240
240
  # Read JSON file
241
- # Inputs: 0) JSON file name, file ref or RAF ref, 1) database hash ref,
241
+ # Inputs: 0) JSON file name, file ref, RAF ref or SCALAR ref, 1) database hash ref,
242
242
  # 2) flag to delete "-" tags, 3) character set
243
243
  # Returns: undef on success, or error string
244
244
  sub ReadJSON($$;$$)
@@ -255,6 +255,9 @@ sub ReadJSON($$;$$)
255
255
  } elsif (ref $file eq 'GLOB') {
256
256
  $raf = File::RandomAccess->new($file);
257
257
  $file = 'JSON file';
258
+ } elsif (ref $file eq 'SCALAR') {
259
+ $raf = File::RandomAccess->new($file);
260
+ $file = 'in memory';
258
261
  } else {
259
262
  open JSONFILE, $file or return "Error opening JSON file '${file}'";
260
263
  binmode JSONFILE;
@@ -14,7 +14,7 @@ use vars qw($VERSION);
14
14
  use Image::ExifTool qw(:DataAccess :Utils);
15
15
  use Image::ExifTool::Import;
16
16
 
17
- $VERSION = '1.07';
17
+ $VERSION = '1.08';
18
18
 
19
19
  sub ProcessJSON($$);
20
20
  sub ProcessTag($$$$%);
@@ -60,15 +60,20 @@ sub FoundTag($$$$%)
60
60
  # avoid conflict with special table entries
61
61
  $tag .= '!' if $Image::ExifTool::specialTags{$tag};
62
62
 
63
- # use underline instead of colon if necessary in tag name
64
- $tag =~ s/([A-Z]):([A-Z]{2})/${1}_$2/g;
65
-
66
- AddTagToTable($tagTablePtr, $tag, {
67
- Name => Image::ExifTool::MakeTagName($tag),
68
- %flags,
69
- Temporary => 1,
70
- }) unless $$tagTablePtr{$tag};
71
-
63
+ unless ($$tagTablePtr{$tag}) {
64
+ my $name = $tag;
65
+ $name =~ tr/:/_/; # use underlines in place of colons in tag name
66
+ $name =~ s/^c2pa/C2PA/i; # hack to fix "C2PA" case
67
+ $name = Image::ExifTool::MakeTagName($name);
68
+ my $desc = Image::ExifTool::MakeDescription($name);
69
+ $desc =~ s/^C2 PA/C2PA/; # hack to get "C2PA" correct
70
+ AddTagToTable($tagTablePtr, $tag, {
71
+ Name => $name,
72
+ Description => $desc,
73
+ %flags,
74
+ Temporary => 1,
75
+ });
76
+ }
72
77
  $et->HandleTag($tagTablePtr, $tag, $val);
73
78
  }
74
79
 
@@ -441,6 +441,7 @@ my %sRegionStruct = (
441
441
  Writable => 'real',
442
442
  Notes => 'not part of MWG 2.0 spec',
443
443
  },
444
+ # Title - seen in sample XMP of MWG 2.0 specification, but not in spec itself
444
445
  seeAlso => { Namespace => 'rdfs', Resource => 1 },
445
446
  );
446
447
  my %sKeywordStruct;
@@ -12,7 +12,7 @@ use strict;
12
12
  use vars qw($VERSION);
13
13
  use Image::ExifTool qw(:DataAccess :Utils);
14
14
 
15
- $VERSION = '1.12';
15
+ $VERSION = '1.13';
16
16
 
17
17
  sub MDItemLocalTime($);
18
18
  sub ProcessATTR($$$);
@@ -22,6 +22,11 @@ my %mdDateInfo = (
22
22
  PrintConv => '$self->ConvertDateTime($val)',
23
23
  );
24
24
 
25
+ my %delXAttr = (
26
+ XAttrQuarantine => 'com.apple.quarantine',
27
+ XAttrMDItemWhereFroms => 'com.apple.metadata:kMDItemWhereFroms',
28
+ );
29
+
25
30
  # Information decoded from Mac OS sidecar files
26
31
  %Image::ExifTool::MacOS::Main = (
27
32
  GROUPS => { 0 => 'File', 1 => 'MacOS' },
@@ -320,7 +325,17 @@ my %mdDateInfo = (
320
325
  Groups => { 2 => 'Time' },
321
326
  },
322
327
  'com.apple.metadata:kMDItemFinderComment' => { Name => 'XAttrMDItemFinderComment' },
323
- 'com.apple.metadata:kMDItemWhereFroms' => { Name => 'XAttrMDItemWhereFroms' },
328
+ 'com.apple.metadata:kMDItemWhereFroms' => {
329
+ Name => 'XAttrMDItemWhereFroms',
330
+ Writable => 1,
331
+ WritePseudo => 1,
332
+ WriteCheck => '"May only delete this tag"',
333
+ Protected => 1,
334
+ Notes => q{
335
+ information about where the file came from. May only be deleted when
336
+ writing
337
+ },
338
+ },
324
339
  'com.apple.metadata:kMDLabel' => { Name => 'XAttrMDLabel', Binary => 1 },
325
340
  'com.apple.ResourceFork' => { Name => 'XAttrResourceFork', Binary => 1 },
326
341
  'com.apple.lastuseddate#PS' => {
@@ -407,9 +422,9 @@ sub SetMacOSTags($$$)
407
422
  $et->VPrint(1," - $tag = (all)\n") if $overwrite > 0;
408
423
  undef $val if $val eq '';
409
424
  }
410
- } elsif ($tag eq 'XAttrQuarantine') {
425
+ } elsif ($delXAttr{$tag}) {
411
426
  ($f = $file) =~ s/'/'\\''/g;
412
- $cmd = "/usr/bin/xattr -d com.apple.quarantine '${f}'";
427
+ $cmd = "/usr/bin/xattr -d $delXAttr{$tag} '${f}'";
413
428
  $silentErr = 256; # (will get this error if attribute doesn't exist)
414
429
  } else {
415
430
  ($f = $file) =~ s/(["\\])/\\$1/g; # escape necessary characters for script
@@ -703,8 +703,8 @@ sub GetAFPointGrid($$;$);
703
703
  #
704
704
  '00 54 56 56 30 30 00 00' => 'Coastal Optical Systems 60mm 1:4 UV-VIS-IR Macro Apo',
705
705
  #
706
- 'BF 4E 26 26 1E 1E 01 04' => 'Irix 15mm f/2.4 Firefly', #30
707
- 'BF 3C 1B 1B 30 30 01 04' => 'Irix 11mm f/4 Firefly', #30
706
+ 'BF 4E 26 26 1E 1E 01 04' => 'Irix 15mm f/2.4 Firefly', #30 (guessing the Blackstone version may be the same ID - PH)
707
+ 'BF 3C 1B 1B 30 30 01 04' => 'Irix 11mm f/4 Firefly', #30 (guessing the Blackstone version may be the same ID - PH)
708
708
  #
709
709
  '4A 40 11 11 2C 0C 4D 02' => 'Samyang 8mm f/3.5 Fish-Eye CS',
710
710
  '4A 48 24 24 24 0C 4D 02.1' => 'Samyang 10mm f/2.8 ED AS NCS CS',
@@ -17,7 +17,7 @@ use strict;
17
17
  use vars qw($VERSION);
18
18
  use Image::ExifTool qw(:DataAccess :Utils);
19
19
 
20
- $VERSION = '1.03';
20
+ $VERSION = '1.04';
21
21
 
22
22
  my $MAX_PACKETS = 2; # maximum packets to scan from each stream at start of file
23
23
 
@@ -145,6 +145,7 @@ sub ProcessOGG($$)
145
145
  # calculate total data length
146
146
  my $dataLen = Get8u(\$buff, 27);
147
147
  if ($nseg) {
148
+ last unless $raf;
148
149
  $raf->Read($buff, $nseg-1) == $nseg-1 or last;
149
150
  my @segs = unpack('C*', $buff);
150
151
  # could check that all these (but the last) are 255...
@@ -160,7 +161,7 @@ sub ProcessOGG($$)
160
161
  }
161
162
  }
162
163
  # read page data
163
- $raf->Read($buff, $dataLen) == $dataLen or last;
164
+ last unless $raf and $raf->Read($buff, $dataLen) == $dataLen;
164
165
  if ($verbose > 1) {
165
166
  printf $out "Page %d, stream 0x%x, flag 0x%x (%d bytes)\n",
166
167
  $pageNum, $stream, $flag, $dataLen;
@@ -40,7 +40,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
40
40
  use Image::ExifTool::Exif;
41
41
  use Image::ExifTool::APP12;
42
42
 
43
- $VERSION = '2.82';
43
+ $VERSION = '2.83';
44
44
 
45
45
  sub PrintLensInfo($$$);
46
46
 
@@ -117,6 +117,7 @@ my %olympusLensTypes = (
117
117
  '0 36 10' => 'Olympus M.Zuiko Digital ED 8-25mm F4 Pro', #IB
118
118
  '0 37 10' => 'Olympus M.Zuiko Digital ED 40-150mm F4.0 Pro', #forum3833
119
119
  '0 39 10' => 'Olympus M.Zuiko Digital ED 90mm F3.5 Macro IS Pro', #forum3833
120
+ '0 40 10' => 'Olympus M.Zuiko Digital ED 150-600mm F5.0-6.3', #forum15652
120
121
  # Sigma lenses
121
122
  '1 01 00' => 'Sigma 18-50mm F3.5-5.6 DC', #8
122
123
  '1 01 10' => 'Sigma 30mm F2.8 EX DN', #NJ
@@ -442,6 +443,7 @@ my %olympusCameraTypes = (
442
443
  S0093 => 'E-P7', #IB
443
444
  S0095 => 'OM-1', #IB
444
445
  S0101 => 'OM-5', #IB
446
+ S0121 => 'OM-1MarkII', #forum15652
445
447
  SR45 => 'D220',
446
448
  SR55 => 'D320L',
447
449
  SR83 => 'D340L',
@@ -16,7 +16,7 @@ use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
  use Image::ExifTool::GPS;
18
18
 
19
- $VERSION = '1.04';
19
+ $VERSION = '1.05';
20
20
 
21
21
  # supported EXR value format types (other types are extracted as undef binary data)
22
22
  my %formatType = (
@@ -134,7 +134,7 @@ my %formatType = (
134
134
  multiView => { },
135
135
  owner => { Groups => { 2 => 'Author' } },
136
136
  pixelAspectRatio => { },
137
- preview => { },
137
+ preview => { Groups => { 2 => 'Preview' } },
138
138
  renderingTransform => { },
139
139
  screenWindowCenter => { },
140
140
  screenWindowWidth => { },
@@ -219,25 +219,25 @@ sub ProcessEXR($$)
219
219
  AddTagToTable($tagTablePtr, $tag, $tagInfo);
220
220
  $et->VPrint(0, $$et{INDENT}, "[adding $tag]\n");
221
221
  }
222
- my ($val, $success);
222
+ my ($val, $success, $buf2);
223
223
  my $format = $formatType{$type};
224
224
  if ($format or $binary) {
225
- $raf->Read($buff, $size) == $size and $success = 1;
225
+ $raf->Read($buf2, $size) == $size and $success = 1;
226
226
  if (not $format) {
227
- $val = \$buff; # treat as undef binary data
227
+ $val = \$buf2; # treat as undef binary data
228
228
  } elsif ($format ne '1') {
229
229
  # handle formats which map nicely into ExifTool format codes
230
230
  if ($format =~ /^(\w+)\[?(\d*)/) {
231
231
  my ($fmt, $cnt) = ($1, $2);
232
232
  $cnt = $fmt eq 'string' ? $size : 1 unless $cnt;
233
- $val = ReadValue(\$buff, 0, $fmt, $cnt, $size);
233
+ $val = ReadValue(\$buf2, 0, $fmt, $cnt, $size);
234
234
  }
235
235
  # handle other format types
236
236
  } elsif ($type eq 'tiledesc') {
237
237
  if ($size >= 9) {
238
- my $x = Get32u(\$buff, 0);
239
- my $y = Get32u(\$buff, 4);
240
- my $mode = Get8u(\$buff, 8);
238
+ my $x = Get32u(\$buf2, 0);
239
+ my $y = Get32u(\$buf2, 4);
240
+ my $mode = Get8u(\$buf2, 8);
241
241
  my $lvl = { 0 => 'One Level', 1 => 'MIMAP Levels', 2 => 'RIPMAP Levels' }->{$mode & 0x0f};
242
242
  $lvl or $lvl = 'Unknown Levels (' . ($mode & 0xf) . ')';
243
243
  my $rnd = { 0 => 'Round Down', 1 => 'Round Up' }->{$mode >> 4};
@@ -246,7 +246,7 @@ sub ProcessEXR($$)
246
246
  }
247
247
  } elsif ($type eq 'chlist') {
248
248
  $val = [ ];
249
- while ($buff =~ /\G([^\0]{1,31})\0(.{16})/sg) {
249
+ while ($buf2 =~ /\G([^\0]{1,31})\0(.{16})/sg) {
250
250
  my ($str, $dat) = ($1, $2);
251
251
  my ($pix,$lin,$x,$y) = unpack('VCx3VV', $dat);
252
252
  $pix = { 0 => 'int8u', 1 => 'half', 2 => 'float' }->{$pix} || "unknown($pix)";
@@ -255,14 +255,14 @@ sub ProcessEXR($$)
255
255
  } elsif ($type eq 'stringvector') {
256
256
  $val = [ ];
257
257
  my $pos = 0;
258
- while ($pos + 4 <= length($buff)) {
259
- my $len = Get32u(\$buff, $pos);
260
- last if $pos + 4 + $len > length($buff);
261
- push @$val, substr($buff, $pos + 4, $len);
258
+ while ($pos + 4 <= length($buf2)) {
259
+ my $len = Get32u(\$buf2, $pos);
260
+ last if $pos + 4 + $len > length($buf2);
261
+ push @$val, substr($buf2, $pos + 4, $len);
262
262
  $pos += 4 + $len;
263
263
  }
264
264
  } else {
265
- $val = \$buff; # (shouldn't happen)
265
+ $val = \$buf2; # (shouldn't happen)
266
266
  }
267
267
  } else {
268
268
  # avoid loading binary data
@@ -282,13 +282,13 @@ sub ProcessEXR($$)
282
282
  $dim = [$3 - $1 + 1, $4 - $2 + 1];
283
283
  }
284
284
  if ($verbose) {
285
- my $dataPt = ref $val ? $val : \$val,
285
+ my $dataPt = ref $val eq 'SCALAR' ? $val : \$buf2;
286
286
  $et->VerboseInfo($tag, $tagInfo,
287
287
  Table => $tagTablePtr,
288
288
  Value => $val,
289
289
  Size => $size,
290
290
  Format => $type,
291
- DataPt => \$buff,
291
+ DataPt => $dataPt,
292
292
  Addr => $raf->Tell() - $size,
293
293
  );
294
294
  }
@@ -114,11 +114,11 @@ my %supportedFilter = (
114
114
  Notes => q{
115
115
  stored as a string but treated as a comma- or semicolon-separated list of
116
116
  items when reading if the string contains commas or semicolons, whichever is
117
- more numerous, otherwise it is treated a space-separated list of items.
118
- Written as a comma-separated list. The list behaviour may be defeated by
119
- setting the API NoPDFList option. Note that the corresponding
120
- XMP-pdf:Keywords tag is not treated as a list, so the NoPDFList option
121
- should be used when copying between these two.
117
+ more numerous, otherwise it is treated a space-separated list of items. The
118
+ list behaviour may be defeated by setting the API NoPDFList option. Written
119
+ as a comma-separated string. Note that the corresponding XMP-pdf:Keywords
120
+ tag is not treated as a list, so the NoPDFList option should be used when
121
+ copying between these two.
122
122
  },
123
123
  },
124
124
  Creator => { },
@@ -177,7 +177,7 @@ sub DecodeAFPoints($$$$;$);
177
177
  '4 6' => 'smc PENTAX-FA 35-80mm F4-5.6',
178
178
  '4 7' => 'Irix 45mm F1.4', #27
179
179
  '4 8' => 'Irix 150mm F2.8 Macro', #exiv2 issue 1084
180
- '4 9' => 'Irix 11mm F4 Firefly', #27
180
+ '4 9' => 'Irix 11mm F4 Firefly', #27 (guessing the Blackstone version may be the same ID - PH)
181
181
  '4 10' => 'Irix 15mm F2.4', #27
182
182
  '4 12' => 'smc PENTAX-FA 50mm F1.4', #17
183
183
  '4 15' => 'smc PENTAX-FA 28-105mm F4-5.6 [IF]',
@@ -48,7 +48,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
48
48
  use Image::ExifTool::Exif;
49
49
  use Image::ExifTool::GPS;
50
50
 
51
- $VERSION = '2.93';
51
+ $VERSION = '2.94';
52
52
 
53
53
  sub ProcessMOV($$;$);
54
54
  sub ProcessKeys($$$);
@@ -58,11 +58,14 @@ sub ProcessEncodingParams($$$);
58
58
  sub ProcessSampleDesc($$$);
59
59
  sub ProcessHybrid($$$);
60
60
  sub ProcessRights($$$);
61
+ sub ProcessNextbase($$$);
61
62
  # ++vvvvvvvvvvvv++ (in QuickTimeStream.pl)
62
63
  sub Process_mebx($$$);
63
64
  sub Process_3gf($$$);
64
65
  sub Process_gps0($$$);
65
66
  sub Process_gsen($$$);
67
+ sub Process_gdat($$$);
68
+ sub Process_nbmt($$$);
66
69
  sub ProcessKenwood($$$);
67
70
  sub ProcessLIGO_JSON($$$);
68
71
  sub ProcessRIFFTrailer($$$);
@@ -88,6 +91,7 @@ sub UnpackLang($;$);
88
91
  sub WriteKeys($$$);
89
92
  sub WriteQuickTime($$$);
90
93
  sub WriteMOV($$);
94
+ sub WriteNextbase($$$);
91
95
  sub GetLangInfo($$);
92
96
  sub CheckQTValue($$$);
93
97
 
@@ -656,6 +660,14 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
656
660
  Name => 'SensorData', # sensor data for the 360Fly
657
661
  Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/ and $$self{OPTIONS}{ExtractEmbedded}',
658
662
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Tags360Fly' },
663
+ },{
664
+ Name => 'SensorData',
665
+ Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/',
666
+ Notes => 'raw 360Fly sensor data without ExtractEmbedded option',
667
+ RawConv => q{
668
+ $self->WarnOnce('Use the ExtractEmbedded option to decode timed SensorData',3);
669
+ return \$val;
670
+ },
659
671
  },
660
672
  { #https://c2pa.org/specifications/
661
673
  Name => 'JUMBF',
@@ -685,18 +697,9 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
685
697
  Start => 27,
686
698
  },
687
699
  },
688
- {
689
- Name => 'SensorData',
690
- Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/',
691
- Notes => 'raw 360Fly sensor data without ExtractEmbedded option',
692
- RawConv => q{
693
- $self->WarnOnce('Use the ExtractEmbedded option to decode timed SensorData',3);
694
- return \$val;
695
- },
696
- },
697
700
  { #PH (Canon CR3)
698
701
  Name => 'PreviewImage',
699
- Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16/',
702
+ Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16.{32}/s',
700
703
  Groups => { 2 => 'Preview' },
701
704
  PreservePadding => 1,
702
705
  # 0x00 - undef[16]: UUID
@@ -711,6 +714,25 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
711
714
  # 0x3c - int32u: preview length
712
715
  RawConv => '$val = substr($val, 0x30); $self->ValidateImage(\$val, $tag)',
713
716
  },
717
+ { #PH (Garmin MP4)
718
+ Name => 'ThumbnailImage',
719
+ Condition => '$$valPt=~/^\x11\x6e\x40\xdc\xb1\x86\x46\xe4\x84\x7c\xd9\xc0\xc3\x49\x10\x81.{8}\xff\xd8\xff/s',
720
+ Groups => { 2 => 'Preview' },
721
+ Binary => 1,
722
+ # 0x00 - undef[16]: UUID
723
+ # 0x10 - int32u[2]: ThumbnailLength
724
+ # 0x14 - int16u[2]: width/height of image (160/120)
725
+ RawConv => q{
726
+ my $len = Get32u(\$val, 0x10);
727
+ return undef unless length($val) >= $len + 0x18;
728
+ return substr($val, 0x18, $len);
729
+ },
730
+ },
731
+ # also seen 120-byte record in Garmin MP4's, starting like this (model name at byte 9):
732
+ # 0000: 47 52 4d 4e 00 00 00 01 00 44 43 35 37 00 00 00 [GRMN.....DC57...]
733
+ # 0000: 47 52 4d 4e 00 00 00 01 00 44 43 36 36 57 00 00 [GRMN.....DC66W..]
734
+ # and this in Garmin, followed by 8 bytes of 0's:
735
+ # 0000: db 11 98 3d 8f 65 43 8c bb b8 e1 ac 56 fe 6b 04
714
736
  { #8
715
737
  Name => 'UUID-Unknown',
716
738
  %unknownInfo,
@@ -835,6 +857,20 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
835
857
  },
836
858
  # gpsa - seen hex "01 20 00 00" (DuDuBell M1, VSYS M6L)
837
859
  # gsea - 20 bytes hex "05 00's..." (DuDuBell M1) "05 08 02 01 ..." (VSYS M6L)
860
+ gdat => { # Base64-encoded JSON-format timed GPS (Nextbase software)
861
+ Name => 'GPSData',
862
+ SubDirectory => {
863
+ TagTable => 'Image::ExifTool::QuickTime::Stream',
864
+ ProcessProc => \&Process_gdat,
865
+ },
866
+ },
867
+ nbmt => { # (Nextbase)
868
+ Name => 'NextbaseMeta',
869
+ SubDirectory => {
870
+ TagTable => 'Image::ExifTool::QuickTime::Stream',
871
+ ProcessProc => \&Process_nbmt,
872
+ },
873
+ },
838
874
  'GPS ' => { # GPS data written by 70mai dashcam (parsed in QuickTimeStream.pl)
839
875
  Name => 'GPSDataList2',
840
876
  Unknown => 1,
@@ -2090,8 +2126,21 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
2090
2126
  Condition => '$$valPt =~ /^VIRBactioncamera/',
2091
2127
  RawConv => 'substr($val, 16)',
2092
2128
  RawConvInv => '"VIRBactioncamera$val"',
2129
+ },{
2130
+ Name => 'GarminModel', # (NC)
2131
+ Condition => '$$valPt =~ /^\xf7\x6c\xd7\x6a\x07\x5b\x4a\x1e\xb3\x1c\x0e\x7f\xab\x7e\x09\xd4/',
2132
+ Writable => 0,
2133
+ RawConv => q{
2134
+ return undef unless length($val) > 25;
2135
+ my $len = unpack('x24C', $val);
2136
+ return undef unless length($val) >= 25 + $len;
2137
+ return substr($val, 25, $len);
2138
+ },
2093
2139
  },{
2094
2140
  # have seen "28 f3 11 e2 b7 91 4f 6f 94 e2 4f 5d ea cb 3c 01" for RicohThetaZ1 accelerometer RADT data (not yet decoded)
2141
+ # also seen in Garmin MP4:
2142
+ # 51 0b 63 46 6c fd 4a 17 87 42 ea c9 ea ae b3 bd - seems to contain a duplicate of the trak atom
2143
+ # b3 e8 21 f4 fe 33 4e 10 8f 92 f5 e1 d4 36 c9 8a - 8 bytes of zeros
2095
2144
  Name => 'UUID-Unknown',
2096
2145
  Writable => 0,
2097
2146
  %unknownInfo,
@@ -2399,6 +2448,30 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
2399
2448
  Groups => { 2 => 'Preview' },
2400
2449
  Binary => 1,
2401
2450
  },
2451
+ # ---- Nextbase ----
2452
+ info => 'FirmwareVersion',
2453
+ 'time' => {
2454
+ Name => 'TimeStamp',
2455
+ Format => 'int32u', # (followed by 4 unknown bytes 00 0d 00 00)
2456
+ Writable => 0,
2457
+ Groups => { 2 => 'Time' },
2458
+ ValueConv => '$val =~ s/ .*//; ConvertUnixTime($val)',
2459
+ PrintConv => '$self->ConvertDateTime($val)',
2460
+ },
2461
+ infi => {
2462
+ Name => 'CameraInfo',
2463
+ SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Nextbase' },
2464
+ },
2465
+ finm => {
2466
+ Name => 'OriginalFileName',
2467
+ Writable => 0,
2468
+ },
2469
+ # AMBA ? - (133 bytes)
2470
+ # nbpl ? - "FP-433-KC"
2471
+ nbpl => { Name => 'Unknown_nbpl', Unknown => 1, Hidden => 1 },
2472
+ # maca ? - b8 2d 28 15 f1 48
2473
+ # sern ? - 0d 69 42 74
2474
+ # nbid ? - 0d 69 42 74 65 df 72 65 03 de c0 fb 01 01 00 00
2402
2475
  # ---- Unknown ----
2403
2476
  # CDET - 128 bytes (unknown origin)
2404
2477
  # mtyp - 4 bytes all zero (some drone video)
@@ -8087,6 +8160,88 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
8087
8160
  },
8088
8161
  );
8089
8162
 
8163
+ # Nextbase tags (ref PH)
8164
+ %Image::ExifTool::QuickTime::Nextbase = (
8165
+ GROUPS => { 1 => 'Nextbase', 2 => 'Camera' },
8166
+ PROCESS_PROC => \&ProcessNextbase,
8167
+ WRITE_PROC => \&WriteNextbase,
8168
+ VARS => { LONG_TAGS => 3 },
8169
+ NOTES => q{
8170
+ Tags found in 'infi' atom from some Nextbase videos. As well as these tags,
8171
+ other existing tags are also extracted. These tags are not currently
8172
+ writable but they may all be removed by deleting the Nextbase group.
8173
+ },
8174
+ 'Wi-Fi SSID' => { },
8175
+ 'Wi-Fi Password' => { },
8176
+ 'Wi-Fi MAC Address' => { },
8177
+ 'Model' => { },
8178
+ 'Firmware' => { },
8179
+ 'Serial No' => { Name => 'SerialNumber' },
8180
+ 'FCC-ID' => { },
8181
+ 'Battery Status' => { },
8182
+ 'SD Card Manf ID' => { },
8183
+ 'SD Card OEM ID' => { },
8184
+ 'SD Card Model No' => { },
8185
+ 'SD Card Serial No' => { },
8186
+ 'SD Card Manf Date' => { },
8187
+ 'SD Card Type' => { },
8188
+ 'SD Card Used Space' => { },
8189
+ 'SD Card Class' => { },
8190
+ 'SD Card Size' => { },
8191
+ 'SD Card Format' => { },
8192
+ 'Wi-Fi SSID' => { },
8193
+ 'Wi-Fi Password' => { },
8194
+ 'Wi-Fi MAC Address' => { },
8195
+ 'Bluetooth Name' => { },
8196
+ 'Bluetooth MAC Address' => { },
8197
+ 'Resolution' => { },
8198
+ 'Exposure' => { },
8199
+ 'Video Length' => { },
8200
+ 'Audio' => { },
8201
+ 'Time Stamp' => { Name => 'VideoTimeStamp' },
8202
+ 'Speed Stamp' => { },
8203
+ 'GPS Stamp' => { },
8204
+ 'Model Stamp' => { },
8205
+ 'Dual Files' => { },
8206
+ 'Time Lapse' => { },
8207
+ 'Number / License Plate' => { },
8208
+ 'G Sensor' => { },
8209
+ 'Image Stabilisation' => { },
8210
+ 'Extreme Weather Mode' => { },
8211
+ 'Screen Saver' => { },
8212
+ 'Alerts' => { },
8213
+ 'Recording History' => { },
8214
+ 'Parking Mode' => { },
8215
+ 'Language' => { },
8216
+ 'Country' => { },
8217
+ 'Time Zone / DST' => { Groups => { 2 => 'Time' } },
8218
+ 'Time & Date' => { Name => 'TimeAndDate', Groups => { 2 => 'Time' } },
8219
+ 'Speed Units' => { },
8220
+ 'Device Sounds' => { },
8221
+ 'Screen Dimming' => { },
8222
+ 'Auto Power Off' => { },
8223
+ 'Keep User Settings' => { },
8224
+ 'System Info' => { },
8225
+ 'Format SD Card' => { },
8226
+ 'Default Settings' => { },
8227
+ 'Emergency SOS' => { },
8228
+ 'Reversing Camera' => { },
8229
+ 'what3words' => { Name => 'What3Words' },
8230
+ 'MyNextbase - Pairing' => { },
8231
+ 'MyNextbase - Paired Device Name' => { },
8232
+ 'Alexa' => { },
8233
+ 'Alexa - Pairing' => { },
8234
+ 'Alexa - Paired Device Name' => { },
8235
+ 'Alexa - Privacy Mode' => { },
8236
+ 'Alexa - Wake Word Language' => { },
8237
+ 'Firmware Version' => { },
8238
+ 'RTOS' => { },
8239
+ 'Linux' => { },
8240
+ 'NBCD' => { },
8241
+ 'Alexa' => { },
8242
+ '2nd Cam' => { Name => 'SecondCam' },
8243
+ );
8244
+
8090
8245
  # QuickTime composite tags
8091
8246
  %Image::ExifTool::QuickTime::Composite = (
8092
8247
  GROUPS => { 2 => 'Video' },
@@ -9149,6 +9304,23 @@ sub ProcessRights($$$)
9149
9304
  return 1;
9150
9305
  }
9151
9306
 
9307
+ #------------------------------------------------------------------------------
9308
+ # Process Nextbase 'infi' atom (ref PH)
9309
+ # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
9310
+ # Returns: 1 on success
9311
+ sub ProcessNextbase($$$)
9312
+ {
9313
+ my ($et, $dirInfo, $tagTbl) = @_;
9314
+ my $dataPt = $$dirInfo{DataPt};
9315
+ $et->VerboseDir('Nextbase', undef, length($$dataPt));
9316
+ while ($$dataPt =~ /(.*?): +(.*)\x0d/g) {
9317
+ my ($id, $val) = ($1, $2);
9318
+ $$tagTbl{$id} or AddTagToTable($tagTbl, $id, { Name => Image::ExifTool::MakeTagName($id) });
9319
+ $et->HandleTag($tagTbl, $id, $val, Size => length($val));
9320
+ }
9321
+ return 1;
9322
+ }
9323
+
9152
9324
  #------------------------------------------------------------------------------
9153
9325
  # Process iTunes Encoding Params (ref PH)
9154
9326
  # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref