exiftool_vendored 12.93.0 → 12.96.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 30869a5b033fa93062cf6f635c5cddb484e8ce9671e8b5b803329edf5d34ee7a
4
- data.tar.gz: 0b886b032d88c6cf22d4052795a6bbc4bd69cc33e40c8a4e308359e5d4ae454f
3
+ metadata.gz: 470de93eb9d8ccb910e0eb1526fb6b9e1e45cbbeb4a88f63c11ddb4bf33d12b8
4
+ data.tar.gz: 90cf2dd30483d655432ef216f8af1751878fc02b140167eb2f301d856c96109d
5
5
  SHA512:
6
- metadata.gz: 4c563c23c4d432f21bbf8ae3ce284fbb7c325540a92bb6c7dd1a693afbe16d3e091b015779094e2f2db5d70ef1e73bc4bc4fb34d8044cb2ae62fa992dc7a085f
7
- data.tar.gz: 8a6cfea51bf26dff8cec28964277ea72446fc6ec3eb877f0c8082c8362dee69b9cb421253af1f3f8b073d067e5b29acb0364ed580ce346880c6541a945a7a706
6
+ metadata.gz: c22dbe664b9eb4ff2327da76ffeea627b45cc47815e3699202d162503c3129c3a31d5b6f2c380dffdedff2a4dccd6a2bd86b68a8ed2e9003b43168788f1df7f8
7
+ data.tar.gz: 1c86569ae1b1a15088e5ff7a9b13b339ecec57b7df35f97d531e29908fe26d10967ccd71b0a4feba0d6a5e37849cbbfea7526000072fe34692141ce694169717
data/bin/Changes CHANGED
@@ -7,13 +7,39 @@ RSS feed: https://exiftool.org/rss.xml
7
7
  Note: The most recent production release is Version 12.76. (Other versions are
8
8
  considered development releases, and are not uploaded to MetaCPAN.)
9
9
 
10
+ Sept. 1, 2024 - Version 12.96
11
+
12
+ - More improvements to handling of trailers on video files (and add ability to
13
+ write videos which have an unknown trailer)
14
+ - Fixed problem geotagging from some newer Google Takeout files
15
+
16
+ Aug. 30, 2024 - Version 12.95
17
+
18
+ - Added a couple of new CanonModelID values
19
+ - Decode ColorData for a couple of new Canon models
20
+ - Fixed problem writing video files which have some known trailer types
21
+
22
+ Aug. 29, 2024 - Version 12.94
23
+
24
+ - Added ability to geotag from new-format Google Takeout JSON files
25
+ - Added a few new Android and Xiaomi QuickTime Keys tags
26
+ - Added ability to read C2PA JUMBF metadata from TTF/OTF files
27
+ - Internal changes to code for creating new directories
28
+ - Changed Windows packages to have the application help text file in the
29
+ exiftool_files folder instead of writing it to a temporary directory
30
+ - Removed new QuickTime Keys tags added in 12.93 because these aren't used in
31
+ top-level metadata (written to the video track by Apple devices)
32
+ - Fixed the group names for synthesized default-language QuickTime tags and
33
+ added a verbose message when generating these tags
34
+ - Fixed warning in Geolocation.t self test
35
+
10
36
  Aug. 20, 2024 - Version 12.93
11
37
 
12
38
  - Added a new Nikon LensID
13
39
  - Added a couple of new OpenEXR Compression types
14
40
  - Added a couple of new QuickTime Keys tags
15
- - Decode timed metadata from E-ACE B44 DashCam videos
16
- - Make "Unrecognized" Samsung Meta warnings minor
41
+ - Decode timed metadata from E-ACE B44 dashcam videos
42
+ - Made "Unrecognized" Samsung Meta warnings minor
17
43
  - Fixed bug in -listg6 option which resulted in "uninitialized value" warnings
18
44
  - Fixed decoding of Func1Button and Func2Button for the Nikon Z6/Z7
19
45
  - Fixed bug reading JUMB metadata from JXL images
data/bin/META.json CHANGED
@@ -50,5 +50,5 @@
50
50
  }
51
51
  },
52
52
  "release_status" : "stable",
53
- "version" : "12.93"
53
+ "version" : "12.96"
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: '12.93'
34
+ version: '12.96'
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-12.93.tar.gz | tar -xf -
113
- cd Image-ExifTool-12.93
112
+ gzip -dc Image-ExifTool-12.96.tar.gz | tar -xf -
113
+ cd Image-ExifTool-12.96
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 = '12.93';
14
+ my $version = '12.96';
15
15
 
16
16
  # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
17
17
  my $exePath;
@@ -232,10 +232,6 @@ my $stayOpen = 0;
232
232
  my $rtnValApp = 0; # app return value (0=success)
233
233
  my $curTitle = ''; # current window title
234
234
 
235
- # lookup for O/S names which may use a backslash as a directory separator
236
- # (ref File::Spec of PathTools-3.2701)
237
- my %hasBackslash = ( MSWin32 => 1, os2 => 1, dos => 1, NetWare => 1, symbian => 1, cygwin => 1 );
238
-
239
235
  # lookup for O/S names which use CR/LF newlines
240
236
  my $isCRLF = { MSWin32 => 1, os2 => 1, dos => 1 }->{$^O};
241
237
 
@@ -1615,7 +1611,7 @@ if ($argFormat) {
1615
1611
  }
1616
1612
 
1617
1613
  # change to forward slashes if necessary in all filenames (like CleanFilename)
1618
- if ($hasBackslash{$^O}) {
1614
+ if (Image::ExifTool::IsPC()) {
1619
1615
  tr/\\/\// foreach @files;
1620
1616
  }
1621
1617
 
@@ -3774,7 +3770,7 @@ sub DoSetFromFile($$$)
3774
3770
  # Returns: nothing, but changes filename if necessary
3775
3771
  sub CleanFilename($)
3776
3772
  {
3777
- $_[0] =~ tr/\\/\// if $hasBackslash{$^O};
3773
+ $_[0] =~ tr/\\/\// if Image::ExifTool::IsPC();
3778
3774
  }
3779
3775
 
3780
3776
  #------------------------------------------------------------------------------
@@ -4097,7 +4093,7 @@ sub AbsPath($)
4097
4093
  $path = eval { Cwd::abs_path($file) };
4098
4094
  # make the delimiters and case consistent
4099
4095
  # (abs_path is very inconsistent about what it returns in Windows)
4100
- if (defined $path and $hasBackslash{$^O}) {
4096
+ if (defined $path and Image::ExifTool::IsPC()) {
4101
4097
  $path =~ tr/\\/\//;
4102
4098
  $path = lc $path;
4103
4099
  }
@@ -4353,46 +4349,21 @@ sub NextUnusedFilename($;$)
4353
4349
  # Create directory for specified file
4354
4350
  # Inputs: 0) complete file name including path
4355
4351
  # Returns: true if a directory was created
4356
- my $k32CreateDir;
4357
4352
  sub CreateDirectory($)
4358
4353
  {
4359
4354
  my $file = shift;
4360
- my ($dir, $created);
4361
- ($dir = $file) =~ s/[^\/]*$//; # remove filename from path specification
4362
- if ($dir and not $mt->IsDirectory($dir)) {
4363
- my @parts = split /\//, $dir;
4364
- $dir = '';
4365
- foreach (@parts) {
4366
- $dir .= $_;
4367
- if (length $dir and not $mt->IsDirectory($dir) and
4368
- # don't try to create a network drive root directory
4369
- not ($hasBackslash{$^O} and $dir =~ m{^//[^/]*$}))
4370
- {
4371
- my $success;
4372
- # create directory since it doesn't exist
4373
- my $d2 = $dir; # (must make a copy in case EncodeFileName recodes it)
4374
- if ($mt->EncodeFileName($d2)) {
4375
- # handle Windows Unicode directory names
4376
- unless (eval { require Win32::API }) {
4377
- Error('Install Win32::API to create directories with Unicode names');
4378
- return 0;
4379
- }
4380
- unless ($k32CreateDir) {
4381
- $k32CreateDir = Win32::API->new('KERNEL32', 'CreateDirectoryW', 'PP', 'I');
4382
- }
4383
- $success = $k32CreateDir->Call($d2, 0) if $k32CreateDir;
4384
- } else {
4385
- $success = mkdir($d2, 0777);
4386
- }
4387
- $success or Error("Error creating directory $dir\n"), return 0;
4388
- $verbose and print $vout "Created directory $dir\n";
4389
- $created = 1;
4390
- }
4391
- $dir .= '/';
4355
+ my $err = $mt->CreateDirectory($file);
4356
+ if (defined $err) {
4357
+ $err and Error("$err\n"), return 0;
4358
+ if ($verbose) {
4359
+ my $dir;
4360
+ ($dir = $file) =~ s(/[^/]*$)();
4361
+ print $vout "Created directory $dir\n";
4392
4362
  }
4393
- ++$countNewDir if $created;
4363
+ ++$countNewDir;
4364
+ return 1;
4394
4365
  }
4395
- return $created;
4366
+ return 0;
4396
4367
  }
4397
4368
 
4398
4369
  #------------------------------------------------------------------------------
@@ -5684,7 +5655,7 @@ with this command:
5684
5655
 
5685
5656
  produces output like this:
5686
5657
 
5687
- -- Generated by ExifTool 12.93 --
5658
+ -- Generated by ExifTool 12.96 --
5688
5659
  File: a.jpg - 2003:10:31 15:44:19
5689
5660
  (f/5.6, 1/60s, ISO 100)
5690
5661
  File: b.jpg - 2006:05:23 11:57:38
@@ -88,7 +88,7 @@ sub ProcessCTMD($$$);
88
88
  sub ProcessExifInfo($$$);
89
89
  sub SwapWords($);
90
90
 
91
- $VERSION = '4.80';
91
+ $VERSION = '4.81';
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)
@@ -995,6 +995,8 @@ $VERSION = '4.80';
995
995
  0x80000481 => 'EOS R6 Mark II', #42
996
996
  0x80000487 => 'EOS R8', #42
997
997
  0x80000491 => 'PowerShot V10', #25
998
+ 0x80000495 => 'EOS R1', #PH
999
+ 0x80000496 => 'R5 Mark II', #forum16406
998
1000
  0x80000498 => 'EOS R100', #25
999
1001
  0x80000520 => 'EOS D2000C', #IB
1000
1002
  0x80000560 => 'EOS D6000C', #PH (guess)
@@ -1978,6 +1980,11 @@ my %offOn = ( 0 => 'Off', 1 => 'On' );
1978
1980
  Name => 'ColorData11',
1979
1981
  SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData11' },
1980
1982
  },
1983
+ { # (int16u[4528]) - R1/R5mkII ref forum16406
1984
+ Condition => '$count == 4528',
1985
+ Name => 'ColorData12',
1986
+ SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData12' },
1987
+ },
1981
1988
  {
1982
1989
  Name => 'ColorDataUnknown',
1983
1990
  SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorDataUnknown' },
@@ -8613,6 +8620,126 @@ my %ciMaxFocal = (
8613
8620
  },
8614
8621
  );
8615
8622
 
8623
+ # Color data (MakerNotes tag 0x4001, count=4528, ref PH)
8624
+ %Image::ExifTool::Canon::ColorData12 = (
8625
+ %binaryDataAttrs,
8626
+ NOTES => 'These tags are used by the EOS R1 and R5mkII',
8627
+ FORMAT => 'int16s',
8628
+ FIRST_ENTRY => 0,
8629
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8630
+ DATAMEMBER => [ 0 ],
8631
+ IS_SUBDIR => [ 0x140 ],
8632
+ 0x00 => {
8633
+ Name => 'ColorDataVersion',
8634
+ DataMember => 'ColorDataVersion',
8635
+ RawConv => '$$self{ColorDataVersion} = $val',
8636
+ PrintConv => {
8637
+ 64 => '64 (R1, R5 Mark II)',
8638
+ },
8639
+ },
8640
+ 0x69 => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, # (NC)
8641
+ 0x6d => 'ColorTempAsShot', # (NC)
8642
+ 0x6e => { Name => 'WB_RGGBLevelsDaylight', Format => 'int16s[4]' },
8643
+ 0x72 => 'ColorTempDaylight',
8644
+ 0x73 => { Name => 'WB_RGGBLevelsShade', Format => 'int16s[4]' },
8645
+ 0x77 => 'ColorTempShade',
8646
+ 0x78 => { Name => 'WB_RGGBLevelsCloudy', Format => 'int16s[4]' },
8647
+ 0x7c => 'ColorTempCloudy',
8648
+ 0x7d => { Name => 'WB_RGGBLevelsTungsten', Format => 'int16s[4]' },
8649
+ 0x81 => 'ColorTempTungsten',
8650
+ 0x82 => { Name => 'WB_RGGBLevelsFluorescent',Format=> 'int16s[4]' },
8651
+ 0x86 => 'ColorTempFluorescent' ,
8652
+ 0x87 => { Name => 'WB_RGGBLevelsFlash', Format => 'int16s[4]' },
8653
+ 0x8b => 'ColorTempFlash',
8654
+ 0x8c => { Name => 'WB_RGGBLevelsUnknown2', Format => 'int16s[4]', Unknown => 1 },
8655
+ 0x90 => { Name => 'ColorTempUnknown2', Unknown => 1 },
8656
+ 0x91 => { Name => 'WB_RGGBLevelsUnknown3', Format => 'int16s[4]', Unknown => 1 },
8657
+ 0x95 => { Name => 'ColorTempUnknown3', Unknown => 1 },
8658
+ 0x96 => { Name => 'WB_RGGBLevelsUnknown4', Format => 'int16s[4]', Unknown => 1 },
8659
+ 0x9a => { Name => 'ColorTempUnknown4', Unknown => 1 },
8660
+ 0x9b => { Name => 'WB_RGGBLevelsUnknown5', Format => 'int16s[4]', Unknown => 1 },
8661
+ 0x9f => { Name => 'ColorTempUnknown5', Unknown => 1 },
8662
+ 0xa0 => { Name => 'WB_RGGBLevelsUnknown6', Format => 'int16s[4]', Unknown => 1 },
8663
+ 0xa4 => { Name => 'ColorTempUnknown6', Unknown => 1 },
8664
+ 0xa5 => { Name => 'WB_RGGBLevelsUnknown7', Format => 'int16s[4]', Unknown => 1 },
8665
+ 0xa9 => { Name => 'ColorTempUnknown7', Unknown => 1 },
8666
+ 0xaa => { Name => 'WB_RGGBLevelsUnknown8', Format => 'int16s[4]', Unknown => 1 },
8667
+ 0xae => { Name => 'ColorTempUnknown8', Unknown => 1 },
8668
+ 0xaf => { Name => 'WB_RGGBLevelsUnknown9', Format => 'int16s[4]', Unknown => 1 },
8669
+ 0xb3 => { Name => 'ColorTempUnknown9', Unknown => 1 },
8670
+ 0xb4 => { Name => 'WB_RGGBLevelsUnknown10', Format => 'int16s[4]', Unknown => 1 },
8671
+ 0xb8 => { Name => 'ColorTempUnknown10', Unknown => 1 },
8672
+ 0xb9 => { Name => 'WB_RGGBLevelsUnknown11', Format => 'int16s[4]', Unknown => 1 },
8673
+ 0xbd => { Name => 'ColorTempUnknown11', Unknown => 1 },
8674
+ 0xbe => { Name => 'WB_RGGBLevelsUnknown12', Format => 'int16s[4]', Unknown => 1 },
8675
+ 0xc2 => { Name => 'ColorTempUnknown12', Unknown => 1 },
8676
+ 0xc3 => { Name => 'WB_RGGBLevelsUnknown13', Format => 'int16s[4]', Unknown => 1 },
8677
+ 0xc7 => { Name => 'ColorTempUnknown13', Unknown => 1 },
8678
+ 0xc8 => { Name => 'WB_RGGBLevelsUnknown14', Format => 'int16s[4]', Unknown => 1 },
8679
+ 0xcc => { Name => 'ColorTempUnknown14', Unknown => 1 },
8680
+ 0xcd => { Name => 'WB_RGGBLevelsUnknown15', Format => 'int16s[4]', Unknown => 1 },
8681
+ 0xd1 => { Name => 'ColorTempUnknown15', Unknown => 1 },
8682
+ 0xd2 => { Name => 'WB_RGGBLevelsUnknown16', Format => 'int16s[4]', Unknown => 1 },
8683
+ 0xd6 => { Name => 'ColorTempUnknown16', Unknown => 1 },
8684
+ 0xd7 => { Name => 'WB_RGGBLevelsUnknown17', Format => 'int16s[4]', Unknown => 1 },
8685
+ 0xdb => { Name => 'ColorTempUnknown17', Unknown => 1 },
8686
+ 0xdc => { Name => 'WB_RGGBLevelsUnknown18', Format => 'int16s[4]', Unknown => 1 },
8687
+ 0xe0 => { Name => 'ColorTempUnknown18', Unknown => 1 },
8688
+ 0xe1 => { Name => 'WB_RGGBLevelsUnknown19', Format => 'int16s[4]', Unknown => 1 },
8689
+ 0xe5 => { Name => 'ColorTempUnknown19', Unknown => 1 },
8690
+ 0xe6 => { Name => 'WB_RGGBLevelsUnknown20', Format => 'int16s[4]', Unknown => 1 },
8691
+ 0xea => { Name => 'ColorTempUnknown20', Unknown => 1 },
8692
+ 0xeb => { Name => 'WB_RGGBLevelsUnknown21', Format => 'int16s[4]', Unknown => 1 },
8693
+ 0xef => { Name => 'ColorTempUnknown21', Unknown => 1 },
8694
+ 0xf0 => { Name => 'WB_RGGBLevelsUnknown22', Format => 'int16s[4]', Unknown => 1 },
8695
+ 0xf4 => { Name => 'ColorTempUnknown22', Unknown => 1 },
8696
+ 0xf5 => { Name => 'WB_RGGBLevelsUnknown23', Format => 'int16s[4]', Unknown => 1 },
8697
+ 0xf9 => { Name => 'ColorTempUnknown23', Unknown => 1 },
8698
+ 0xfa => { Name => 'WB_RGGBLevelsUnknown24', Format => 'int16s[4]', Unknown => 1 },
8699
+ 0xfe => { Name => 'ColorTempUnknown24', Unknown => 1 },
8700
+ 0xff => { Name => 'WB_RGGBLevelsUnknown25', Format => 'int16s[4]', Unknown => 1 },
8701
+ 0x103 => { Name => 'ColorTempUnknown25', Unknown => 1 },
8702
+ 0x104 => { Name => 'WB_RGGBLevelsUnknown26',Format => 'int16s[4]', Unknown => 1 },
8703
+ 0x108 => { Name => 'ColorTempUnknown26', Unknown => 1 },
8704
+ 0x109 => { Name => 'WB_RGGBLevelsUnknown27',Format => 'int16s[4]', Unknown => 1 },
8705
+ 0x10d => { Name => 'ColorTempUnknown27', Unknown => 1 },
8706
+ 0x10e => { Name => 'WB_RGGBLevelsUnknown28',Format => 'int16s[4]', Unknown => 1 },
8707
+ 0x112 => { Name => 'ColorTempUnknown28', Unknown => 1 },
8708
+ 0x113 => { Name => 'WB_RGGBLevelsUnknown29',Format => 'int16s[4]', Unknown => 1 },
8709
+ 0x117 => { Name => 'ColorTempUnknown29', Unknown => 1 },
8710
+ 0x118 => { Name => 'WB_RGGBLevelsUnknown30',Format => 'int16s[4]', Unknown => 1 },
8711
+ 0x11c => { Name => 'ColorTempUnknown30', Unknown => 1 },
8712
+ 0x11d => { Name => 'WB_RGGBLevelsUnknown31',Format => 'int16s[4]', Unknown => 1 },
8713
+ 0x121 => { Name => 'ColorTempUnknown31', Unknown => 1 },
8714
+ 0x122 => { Name => 'WB_RGGBLevelsUnknown32',Format => 'int16s[4]', Unknown => 1 },
8715
+ 0x126 => { Name => 'ColorTempUnknown32', Unknown => 1 },
8716
+ 0x127 => { Name => 'WB_RGGBLevelsUnknown33',Format => 'int16s[4]', Unknown => 1 },
8717
+ 0x12b => { Name => 'ColorTempUnknown33', Unknown => 1 },
8718
+ 0x140 => {
8719
+ Name => 'ColorCalib',
8720
+ Format => 'undef[120]',
8721
+ Unknown => 1,
8722
+ SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorCalib' }
8723
+ },
8724
+ 0x17f => {
8725
+ Name => 'PerChannelBlackLevel',
8726
+ Format => 'int16u[4]',
8727
+ },
8728
+ 0x294 => {
8729
+ Name => 'NormalWhiteLevel',
8730
+ Format => 'int16u',
8731
+ RawConv => '$val || undef',
8732
+ },
8733
+ 0x295 => {
8734
+ Name => 'SpecularWhiteLevel',
8735
+ Format => 'int16u',
8736
+ },
8737
+ 0x296 => {
8738
+ Name => 'LinearityUpperMargin',
8739
+ Format => 'int16u',
8740
+ },
8741
+ );
8742
+
8616
8743
  # Unknown color data (MakerNotes tag 0x4001)
8617
8744
  %Image::ExifTool::Canon::ColorDataUnknown = (
8618
8745
  PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
@@ -19,7 +19,7 @@ use strict;
19
19
  use vars qw($VERSION %ttLang);
20
20
  use Image::ExifTool qw(:DataAccess :Utils);
21
21
 
22
- $VERSION = '1.10';
22
+ $VERSION = '1.11';
23
23
 
24
24
  sub ProcessOTF($$);
25
25
 
@@ -189,6 +189,9 @@ my %ttCharset = (
189
189
  name => {
190
190
  SubDirectory => { TagTable => 'Image::ExifTool::Font::Name' },
191
191
  },
192
+ C2PA => {
193
+ SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::Main', Start => 20 },
194
+ },
192
195
  PFM => {
193
196
  Name => 'PFMHeader',
194
197
  SubDirectory => { TagTable => 'Image::ExifTool::Font::PFM' },
@@ -389,10 +392,12 @@ sub ProcessOTF($$)
389
392
  $$et{INDENT} .= '| ';
390
393
  $et->VerboseDir('TrueType', $numTables) if $verbose;
391
394
 
395
+ my %processTag = ( name => 1, C2PA => 1 ); # tags to process (skip all others)
396
+
392
397
  for ($pos=0; $pos<$len; $pos+=16) {
393
- # look for 'name' table
398
+ # look for tags to process
394
399
  my $tag = substr($tbl, $pos, 4);
395
- next unless $tag eq 'name' or $verbose;
400
+ next unless $processTag{$tag} or $verbose;
396
401
  my $offset = Get32u(\$tbl, $pos + 8);
397
402
  my $size = Get32u(\$tbl, $pos + 12);
398
403
  unless ($raf->Seek($offset+$base, 0) and $raf->Read($buff, $size) == $size) {
@@ -405,9 +410,15 @@ sub ProcessOTF($$)
405
410
  $$et{INDENT}, $pos/16, $tag, $offset, $size);
406
411
  $et->VPrint(0, $str);
407
412
  $et->VerboseDump(\$buff, Addr => $offset) if $verbose > 2;
408
- next unless $tag eq 'name';
413
+ next unless $processTag{$tag};
409
414
  }
410
415
  next unless $size >= 8;
416
+ unless ($tag eq 'name') {
417
+ my $tagTablePtr = GetTagTable('Image::ExifTool::Font::Main');
418
+ $et->HandleTag($tagTablePtr, $tag, undef, DataPt => \$buff, Size => length($buff));
419
+ next;
420
+ }
421
+ # process the 'name' tag
411
422
  my $entries = Get16u(\$buff, 2);
412
423
  my $recEnd = 6 + $entries * 12;
413
424
  if ($recEnd > $size) {
@@ -16,6 +16,7 @@
16
16
  # 2020/12/01 - PH Added ability to read DJI CSV log files
17
17
  # 2022/06/21 - PH Added ability to read Google Takeout JSON files
18
18
  # 2024/04/23 - PH Added ability to read more OpenTracks GPS tags
19
+ # 2024/08/28 - PH Added support for new Google Takeout JSON format
19
20
  #
20
21
  # References: 1) http://www.topografix.com/GPX/1/1/
21
22
  # 2) http://www.gpsinformation.org/dale/nmea.htm#GSA
@@ -30,7 +31,7 @@ use vars qw($VERSION);
30
31
  use Image::ExifTool qw(:Public);
31
32
  use Image::ExifTool::GPS;
32
33
 
33
- $VERSION = '1.76';
34
+ $VERSION = '1.78';
34
35
 
35
36
  sub JITTER() { return 2 } # maximum time jitter
36
37
 
@@ -151,7 +152,7 @@ sub LoadTrackLog($$;$)
151
152
  my ($raf, $from, $time, $isDate, $noDate, $noDateChanged, $lastDate, $dateFlarm);
152
153
  my ($nmeaStart, $fixSecs, @fixTimes, $lastFix, %nmea, @csvHeadings, $sortFixes);
153
154
  my ($canCut, $cutPDOP, $cutHDOP, $cutSats, $e0, $e1, @tmp, $trackFile, $trackTime);
154
- my $scaleSpeed;
155
+ my ($scaleSpeed, $startTime);
155
156
 
156
157
  unless (eval { require Time::Local }) {
157
158
  return 'Geotag feature requires Time::Local installed';
@@ -318,10 +319,13 @@ sub LoadTrackLog($$;$)
318
319
  }
319
320
  }
320
321
  next;
321
- } elsif (/"(timelineObjects|placeVisit|activitySegment|latitudeE7)":/) {
322
+ } elsif (/"(timelineObjects|placeVisit|activitySegment|latitudeE7)"\s*:/) {
322
323
  # Google Takeout JSON format
323
324
  $format = 'JSON';
324
325
  $sortFixes = 1; # (fixes are not all in order for this format)
326
+ } elsif (/"(durationMinutesOffsetFromStartTime|startTime)"\s*:/) {
327
+ $format = 'JSON'; # new Google Takeout JSON format (fixes seem to be in order)
328
+ $raf->Seek(0,0); # rewind to start of file
325
329
  } else {
326
330
  # search only first 50 lines of file for a valid fix
327
331
  last if ++$skipped > 50;
@@ -558,14 +562,24 @@ DoneFix: $isDate = 1;
558
562
  next;
559
563
  } elsif ($format eq 'JSON') {
560
564
  # Google Takeout JSON format
561
- if (/"(latitudeE7|longitudeE7|latE7|lngE7|timestamp)":\s*"?(.*?)"?,?\s*[\x0d\x0a]/) {
565
+ if (/"(latitudeE7|longitudeE7|latE7|lngE7|timestamp|startTime|point|durationMinutesOffsetFromStartTime)"\s*:\s*"?(.*?)"?,?\s*[\x0d\x0a]/) {
562
566
  if ($1 eq 'timestamp') {
563
567
  $time = GetTime($2);
564
568
  goto DoneFix if $time and $$fix{lat} and $$fix{lon};
569
+ } elsif ($1 eq 'startTime') { # (new format)
570
+ $startTime = GetTime($2);
565
571
  } elsif ($1 eq 'latitudeE7' or $1 eq 'latE7') {
566
572
  $$fix{lat} = $2 * 1e-7;
567
- } else {
573
+ } elsif ($1 eq 'longitudeE7' or $1 eq 'lngE7') {
568
574
  $$fix{lon} = $2 * 1e-7;
575
+ } elsif ($1 eq 'point') { # (new format)
576
+ my $point = $2;
577
+ my @coords = $point =~ /[-+]?\d+\.\d+/g;
578
+ @$fix{'lat','lon'} = @coords[0,1] if @coords == 2;
579
+ } elsif ($1 eq 'durationMinutesOffsetFromStartTime' and defined $startTime) { # (new format)
580
+ $time = $startTime + $2 * 60;
581
+ # note: this assumes that "point" comes first, which it does in my sample
582
+ goto DoneFix if $time and $$fix{lat} and $$fix{lon};
569
583
  }
570
584
  }
571
585
  next;
@@ -16,7 +16,7 @@ use strict;
16
16
  use vars qw($VERSION $AUTOLOAD);
17
17
  use Image::ExifTool qw(:DataAccess :Utils);
18
18
 
19
- $VERSION = '1.45';
19
+ $VERSION = '1.46';
20
20
 
21
21
  sub WritePS($$);
22
22
  sub ProcessPS($$;$);
@@ -156,15 +156,6 @@ sub AUTOLOAD
156
156
  return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_);
157
157
  }
158
158
 
159
- #------------------------------------------------------------------------------
160
- # Is this a PC system
161
- # Returns: true for PC systems
162
- my %isPC = (MSWin32 => 1, os2 => 1, dos => 1, NetWare => 1, symbian => 1, cygwin => 1);
163
- sub IsPC()
164
- {
165
- return $isPC{$^O};
166
- }
167
-
168
159
  #------------------------------------------------------------------------------
169
160
  # Get image width or height
170
161
  # Inputs: 0) value list ref (ImageData, BoundingBox), 1) true to get height
@@ -284,7 +275,7 @@ sub GetNextLine($$)
284
275
  $$raf{PSEnd} and CheckPSEnd($raf, \$data);
285
276
  # split line if it contains other newline sequences
286
277
  if ($data =~ /$altnl/) {
287
- if (length($data) > 500000 and IsPC()) {
278
+ if (length($data) > 500000 and Image::ExifTool::IsPC()) {
288
279
  # patch for Windows memory problem
289
280
  unless ($changedNL) {
290
281
  $changedNL = $/;
@@ -537,7 +528,7 @@ sub ProcessPS($$;$)
537
528
  $raf->ReadLine($data) or last;
538
529
  # check for alternate newlines as efficiently as possible
539
530
  if ($data =~ /$altnl/) {
540
- if (length($data) > 500000 and IsPC()) {
531
+ if (length($data) > 500000 and Image::ExifTool::IsPC()) {
541
532
  # Windows can't split very long lines due to poor memory handling,
542
533
  # so re-read the file with the other newline character instead
543
534
  # (slower but uses less memory)
@@ -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 = '3.00';
51
+ $VERSION = '3.02';
52
52
 
53
53
  sub ProcessMOV($$;$);
54
54
  sub ProcessKeys($$$);
@@ -6552,7 +6552,7 @@ my %userDefined = (
6552
6552
  PROCESS_PROC => \&ProcessKeys,
6553
6553
  WRITE_PROC => \&WriteKeys,
6554
6554
  CHECK_PROC => \&CheckQTValue,
6555
- VARS => { LONG_TAGS => 7 },
6555
+ VARS => { LONG_TAGS => 8 },
6556
6556
  WRITABLE => 1,
6557
6557
  # (not PREFERRED when writing)
6558
6558
  GROUPS => { 1 => 'Keys' },
@@ -6606,12 +6606,8 @@ my %userDefined = (
6606
6606
  PrintConv => '$val * 1e6 . " microseconds"',
6607
6607
  PrintConvInv => '$val =~ s/ .*//; $val * 1e-6',
6608
6608
  },
6609
- 'camera.focal_length.35mm_equivalent' => {
6610
- Name => 'FocalLengthIn35mmFormat',
6611
- PrintConv => '"$val mm"',
6612
- PrintConvInv => '$val=~s/\s*mm$//;$val',
6613
- },
6614
- 'camera.lens_model' => { Name => 'LensModel' },
6609
+ # 'camera.focal_length.35mm_equivalent' - not top level (written to Keys in video track)
6610
+ # 'camera.lens_model' - not top level (written to Keys in video track)
6615
6611
  'location.ISO6709' => {
6616
6612
  Name => 'GPSCoordinates',
6617
6613
  Groups => { 2 => 'Location' },
@@ -6674,7 +6670,12 @@ my %userDefined = (
6674
6670
  #
6675
6671
  'com.apple.photos.captureMode' => 'CaptureMode',
6676
6672
  'com.android.version' => 'AndroidVersion',
6677
- 'com.android.capture.fps' => 'AndroidCaptureFPS',
6673
+ 'com.android.capture.fps' => { Name => 'AndroidCaptureFPS', Writable => 'float' },
6674
+ 'com.android.manufacturer' => 'AndroidMake',
6675
+ 'com.android.model' => 'AndroidModel',
6676
+ 'com.xiaomi.preview_video_cover' => { Name => 'XiaomiPreviewVideoCover', Writable => 'int32s' },
6677
+ 'xiaomi.exifInfo.videoinfo' => 'XiaomiExifInfo',
6678
+ 'com.xiaomi.hdr10' => { Name => 'XiaomiHDR10', Writable => 'int32s' },
6678
6679
  #
6679
6680
  # also seen
6680
6681
  #
@@ -9490,7 +9491,7 @@ sub ProcessKeys($$$)
9490
9491
  $$newInfo{KeysID} = $tag; # save original ID for use in family 7 group name
9491
9492
  AddTagToTable($itemList, $id, $newInfo);
9492
9493
  $msg or $msg = '';
9493
- $out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $tag$msg\n";
9494
+ $out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $full$msg\n";
9494
9495
  }
9495
9496
  $pos += $len;
9496
9497
  ++$index;
@@ -9527,7 +9528,7 @@ sub ProcessMOV($$;$)
9527
9528
  my $dirID = $$dirInfo{DirID} || '';
9528
9529
  my $charsetQuickTime = $et->Options('CharsetQuickTime');
9529
9530
  my ($buff, $tag, $size, $track, $isUserData, %triplet, $doDefaultLang, $index);
9530
- my ($dirEnd, $unkOpt, %saveOptions, $atomCount, $warnStr);
9531
+ my ($dirEnd, $unkOpt, %saveOptions, $atomCount, $warnStr, $trailer);
9531
9532
 
9532
9533
  my $topLevel = not $$et{InQuickTime};
9533
9534
  $$et{InQuickTime} = 1;
@@ -9556,6 +9557,17 @@ sub ProcessMOV($$;$)
9556
9557
  $tagTablePtr = GetTagTable('Image::ExifTool::QuickTime::Main');
9557
9558
  }
9558
9559
  ($size, $tag) = unpack('Na4', $buff);
9560
+ my $fast = $$et{OPTIONS}{FastScan} || 0;
9561
+ # check for Insta360 trailer
9562
+ if ($topLevel and not $fast) {
9563
+ my $pos = $raf->Tell();
9564
+ if ($raf->Seek(-40, 2) and $raf->Read($buff, 40) == 40 and
9565
+ substr($buff, 8) eq '8db42d694ccc418790edff439fe026bf')
9566
+ {
9567
+ $trailer = [ 'Insta360', $raf->Tell() - unpack('V',$buff) ];
9568
+ }
9569
+ $raf->Seek($pos,0) or return 0;
9570
+ }
9559
9571
  if ($dataPt) {
9560
9572
  $verbose and $et->VerboseDir($$dirInfo{DirName});
9561
9573
  } else {
@@ -9594,7 +9606,6 @@ sub ProcessMOV($$;$)
9594
9606
  # have XMP take priority except for HEIC
9595
9607
  $$et{PRIORITY_DIR} = 'XMP' unless $fileType and $fileType eq 'HEIC';
9596
9608
  }
9597
- my $fast = $$et{OPTIONS}{FastScan} || 0;
9598
9609
  $$raf{NoBuffer} = 1 if $fast; # disable buffering in FastScan mode
9599
9610
 
9600
9611
  my $ee = $$et{OPTIONS}{ExtractEmbedded};
@@ -10135,6 +10146,10 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10135
10146
  $dataPos += $size + 8; # point to start of next atom data
10136
10147
  last if $dirEnd and $dataPos >= $dirEnd; # (note: ignores last value if 0 bytes)
10137
10148
  $lastPos = $raf->Tell() + $dirBase;
10149
+ if ($trailer and $lastPos >= $$trailer[1]) {
10150
+ $et->Warn(sprintf('%s trailer at offset 0x%x', @$trailer), 1);
10151
+ last;
10152
+ }
10138
10153
  $raf->Read($buff, 8) == 8 or last;
10139
10154
  $lastTag = $tag if $$tagTablePtr{$tag} and $tag ne 'free'; # (Insta360 sometimes puts free block before trailer)
10140
10155
  ($size, $tag) = unpack('Na4', $buff);
@@ -10143,14 +10158,10 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10143
10158
  if ($warnStr) {
10144
10159
  # assume this is an unknown trailer if it comes immediately after
10145
10160
  # mdat or moov and has a tag name we don't recognize
10146
- if (($lastTag eq 'mdat' or $lastTag eq 'moov') and (not $$tagTablePtr{$tag} or
10147
- ref $$tagTablePtr{$tag} eq 'HASH' and $$tagTablePtr{$tag}{Unknown}))
10161
+ if (($lastTag eq 'mdat' or $lastTag eq 'moov') and
10162
+ (not $$tagTablePtr{$tag} or ref $$tagTablePtr{$tag} eq 'HASH' and $$tagTablePtr{$tag}{Unknown}))
10148
10163
  {
10149
- if ($size == 0x1000000 - 8 and $tag =~ /^(\x94\xc0\x7e\0|\0\x02\0\0)/) {
10150
- $et->Warn(sprintf('Insta360 trailer at offset 0x%x', $lastPos), 1);
10151
- } else {
10152
- $et->Warn('Unknown trailer with '.lcfirst($warnStr));
10153
- }
10164
+ $et->Warn('Unknown trailer with '.lcfirst($warnStr));
10154
10165
  } else {
10155
10166
  $et->Warn($warnStr);
10156
10167
  }
@@ -10177,7 +10188,10 @@ QTLang: foreach $tag (@{$$et{QTLang}}) {
10177
10188
  for ($i=0, $key=$name; $$infoHash{$key}; ++$i, $key="$name ($i)") {
10178
10189
  next QTLang if $et->GetGroup($key, 0) eq 'QuickTime';
10179
10190
  }
10180
- $et->FoundTag($tagInfo, $$et{VALUE}{$tag});
10191
+ $key = $et->FoundTag($tagInfo, $$et{VALUE}{$tag});
10192
+ # copy extra tag information (groups, etc) to the synthetic tag
10193
+ $$et{TAG_EXTRA}{$key} = $$et{TAG_EXTRA}{$tag};
10194
+ $et->VPrint(0, "(synthesized default-language tag for QuickTime:$$tagInfo{Name})");
10181
10195
  }
10182
10196
  delete $$et{QTLang};
10183
10197
  }