exiftool-vendored.exe 12.69.0 → 12.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/exiftool_files/Changes +78 -12
- package/bin/exiftool_files/README +10 -10
- package/bin/exiftool_files/exiftool.pl +32 -27
- package/bin/exiftool_files/lib/Image/ExifTool/AAC.pm +175 -0
- package/bin/exiftool_files/lib/Image/ExifTool/BuildTagLookup.pm +2 -1
- package/bin/exiftool_files/lib/Image/ExifTool/CBOR.pm +18 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +82 -20
- package/bin/exiftool_files/lib/Image/ExifTool/DJI.pm +3 -2
- package/bin/exiftool_files/lib/Image/ExifTool/EXE.pm +54 -6
- package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +111 -11
- package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +145 -20
- package/bin/exiftool_files/lib/Image/ExifTool/GIF.pm +5 -1
- package/bin/exiftool_files/lib/Image/ExifTool/GoPro.pm +16 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ID3.pm +76 -10
- package/bin/exiftool_files/lib/Image/ExifTool/InDesign.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/JPEG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/JSON.pm +4 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +30 -15
- package/bin/exiftool_files/lib/Image/ExifTool/M2TS.pm +21 -16
- package/bin/exiftool_files/lib/Image/ExifTool/MakerNotes.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +203 -102
- package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +7 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +8 -13
- package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +10 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +15 -6
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +59 -13
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +59 -11
- package/bin/exiftool_files/lib/Image/ExifTool/README +7 -2
- package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +53 -9
- package/bin/exiftool_files/lib/Image/ExifTool/Ricoh.pm +109 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Samsung.pm +3 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +177 -37
- package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +6961 -6856
- package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +580 -344
- package/bin/exiftool_files/lib/Image/ExifTool/Text.pm +4 -5
- package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +6 -5
- package/bin/exiftool_files/lib/Image/ExifTool/WriteExif.pl +19 -4
- package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +1 -0
- package/bin/exiftool_files/lib/Image/ExifTool/WriteRIFF.pl +9 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +102 -50
- package/bin/exiftool_files/lib/Image/ExifTool.pm +74 -36
- package/bin/exiftool_files/lib/Image/ExifTool.pod +28 -17
- package/package.json +5 -4
|
@@ -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.
|
|
43
|
+
$VERSION = '2.82';
|
|
44
44
|
|
|
45
45
|
sub PrintLensInfo($$$);
|
|
46
46
|
|
|
@@ -186,7 +186,9 @@ my %olympusLensTypes = (
|
|
|
186
186
|
'2 36 10' => 'Leica DG Elmarit 200mm F2.8 Power OIS', #IB
|
|
187
187
|
'2 37 10' => 'Leica DG Vario-Elmarit 50-200mm F2.8-4 Asph. Power OIS', #IB
|
|
188
188
|
'2 38 10' => 'Leica DG Vario-Summilux 10-25mm F1.7 Asph.', #IB
|
|
189
|
+
'2 39 10' => 'Leica DG Summilux 25mm F1.4 II Asph.', #forum15345
|
|
189
190
|
'2 40 10' => 'Leica DG Vario-Summilux 25-50mm F1.7 Asph.', #IB (H-X2550)
|
|
191
|
+
'2 41 10' => 'Leica DG Summilux 9mm F1.7 Asph.', #forum15345
|
|
190
192
|
'3 01 00' => 'Leica D Vario Elmarit 14-50mm F2.8-3.5 Asph.', #11
|
|
191
193
|
'3 02 00' => 'Leica D Summilux 25mm F1.4 Asph.', #11
|
|
192
194
|
# Tamron lenses
|
|
@@ -358,6 +360,7 @@ my %olympusCameraTypes = (
|
|
|
358
360
|
D4521 => 'SH-25MR',
|
|
359
361
|
D4523 => 'SP-720UZ',
|
|
360
362
|
D4529 => 'VG170',
|
|
363
|
+
D4530 => 'VH210',
|
|
361
364
|
D4531 => 'XZ-2',
|
|
362
365
|
D4535 => 'SP-620UZ',
|
|
363
366
|
D4536 => 'TG-320',
|
|
@@ -383,9 +386,11 @@ my %olympusCameraTypes = (
|
|
|
383
386
|
D4585 => 'SH-2 / SH-3',
|
|
384
387
|
D4586 => 'TG-4',
|
|
385
388
|
D4587 => 'TG-860',
|
|
389
|
+
D4590 => 'TG-TRACKER',
|
|
386
390
|
D4591 => 'TG-870',
|
|
387
391
|
D4593 => 'TG-5', #IB
|
|
388
392
|
D4603 => 'TG-6', #IB
|
|
393
|
+
D4605 => 'TG-7',
|
|
389
394
|
D4809 => 'C2500L',
|
|
390
395
|
D4842 => 'E-10',
|
|
391
396
|
D4856 => 'C-1',
|
|
@@ -431,6 +436,7 @@ my %olympusCameraTypes = (
|
|
|
431
436
|
S0076 => 'E-PL9', #IB
|
|
432
437
|
S0080 => 'E-M1X', #IB
|
|
433
438
|
S0085 => 'E-PL10', #IB
|
|
439
|
+
S0088 => 'E-M10MarkIV',
|
|
434
440
|
S0089 => 'E-M5MarkIII',
|
|
435
441
|
S0092 => 'E-M1MarkIII', #IB
|
|
436
442
|
S0093 => 'E-P7', #IB
|
|
@@ -80,6 +80,7 @@ my %pngMap = (
|
|
|
80
80
|
ICC_Profile => 'PNG',
|
|
81
81
|
Photoshop => 'PNG',
|
|
82
82
|
'PNG-pHYs' => 'PNG',
|
|
83
|
+
JUMBF => 'PNG',
|
|
83
84
|
IPTC => 'Photoshop',
|
|
84
85
|
MakerNotes => 'ExifIFD',
|
|
85
86
|
);
|
|
@@ -341,6 +342,7 @@ my %noLeapFrog = ( SAVE => 1, SEEK => 1, IHDR => 1, JHDR => 1, IEND => 1, MEND =
|
|
|
341
342
|
},
|
|
342
343
|
caBX => { # C2PA metadata
|
|
343
344
|
Name => 'JUMBF',
|
|
345
|
+
Deletable => 1,
|
|
344
346
|
SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::Main' },
|
|
345
347
|
},
|
|
346
348
|
cICP => {
|
|
@@ -973,20 +975,13 @@ sub FoundPNG($$$$;$$$$)
|
|
|
973
975
|
undef $processProc if $wasCompressed and $processProc and $processProc eq \&ProcessPNG_Compressed;
|
|
974
976
|
# rewrite this directory if necessary (but always process TextualData normally)
|
|
975
977
|
if ($outBuff and not $processProc and $subTable ne \%Image::ExifTool::PNG::TextualData) {
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
$
|
|
981
|
-
} else {
|
|
982
|
-
return 1 unless $$et{EDIT_DIRS}{$dirName};
|
|
983
|
-
$$outBuff = $et->WriteDirectory(\%subdirInfo, $subTable);
|
|
984
|
-
if ($tagName eq 'XMP' and $$outBuff) {
|
|
985
|
-
# make sure the XMP is marked as read-only
|
|
986
|
-
Image::ExifTool::XMP::ValidateXMP($outBuff,'r');
|
|
987
|
-
}
|
|
988
|
-
DoneDir($et, $dirName, $outBuff, $$tagInfo{NonStandard});
|
|
978
|
+
return 1 unless $$et{EDIT_DIRS}{$dirName};
|
|
979
|
+
$$outBuff = $et->WriteDirectory(\%subdirInfo, $subTable);
|
|
980
|
+
if ($tagName eq 'XMP' and $$outBuff) {
|
|
981
|
+
# make sure the XMP is marked as read-only
|
|
982
|
+
Image::ExifTool::XMP::ValidateXMP($outBuff,'r');
|
|
989
983
|
}
|
|
984
|
+
DoneDir($et, $dirName, $outBuff, $$tagInfo{NonStandard});
|
|
990
985
|
} else {
|
|
991
986
|
$processed = $et->ProcessDirectory(\%subdirInfo, $subTable, $processProc);
|
|
992
987
|
}
|
|
@@ -37,7 +37,7 @@ use vars qw($VERSION %leicaLensTypes);
|
|
|
37
37
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
38
38
|
use Image::ExifTool::Exif;
|
|
39
39
|
|
|
40
|
-
$VERSION = '2.
|
|
40
|
+
$VERSION = '2.21';
|
|
41
41
|
|
|
42
42
|
sub ProcessLeicaLEIC($$$);
|
|
43
43
|
sub WhiteBalanceConv($;$$);
|
|
@@ -1991,6 +1991,15 @@ my %shootingMode = (
|
|
|
1991
1991
|
},
|
|
1992
1992
|
PrintConvInv => '$_=$val; tr/A-Z0-9//dc; s/(.{3})(19|20)/$1/; $_',
|
|
1993
1993
|
},
|
|
1994
|
+
0x05ff => {
|
|
1995
|
+
Name => 'CameraIFD', # (Leica Q3)
|
|
1996
|
+
Condition => '$$valPt =~ /^(II\x2a\0\x08\0\0\0|MM\0\x2a\0\0\0\x08)/',
|
|
1997
|
+
SubDirectory => {
|
|
1998
|
+
TagTable => 'Image::ExifTool::PanasonicRaw::CameraIFD',
|
|
1999
|
+
Base => '$start',
|
|
2000
|
+
ProcessProc => \&Image::ExifTool::ProcessTIFF,
|
|
2001
|
+
},
|
|
2002
|
+
},
|
|
1994
2003
|
);
|
|
1995
2004
|
|
|
1996
2005
|
# Leica type5 ShotInfo (ref PH) (X2)
|
|
@@ -58,7 +58,7 @@ use Image::ExifTool::Exif;
|
|
|
58
58
|
use Image::ExifTool::GPS;
|
|
59
59
|
use Image::ExifTool::HP;
|
|
60
60
|
|
|
61
|
-
$VERSION = '3.
|
|
61
|
+
$VERSION = '3.45';
|
|
62
62
|
|
|
63
63
|
sub CryptShutterCount($$);
|
|
64
64
|
sub PrintFilter($$$);
|
|
@@ -410,7 +410,8 @@ sub DecodeAFPoints($$$$;$);
|
|
|
410
410
|
#
|
|
411
411
|
# Ricoh lenses
|
|
412
412
|
#
|
|
413
|
-
'31 1' => '
|
|
413
|
+
'31 1' => '18.3mm F2.8', #PH (GR III built-in)
|
|
414
|
+
'31 4' => '26.1mm F2.8', #PH (GR IIIx built-in)
|
|
414
415
|
);
|
|
415
416
|
|
|
416
417
|
# Pentax model ID codes - PH
|
|
@@ -1141,8 +1142,12 @@ my %binaryDataAttrs = (
|
|
|
1141
1142
|
3 => 'Manual',
|
|
1142
1143
|
4 => 'Super Macro', #JD
|
|
1143
1144
|
5 => 'Pan Focus',
|
|
1144
|
-
|
|
1145
|
-
|
|
1145
|
+
6 => 'Auto-area', # (GR III)
|
|
1146
|
+
8 => 'Select', # (GR III)
|
|
1147
|
+
9 => 'Pinpoint', # (GR III)
|
|
1148
|
+
10 => 'Tracking', # (GR III)
|
|
1149
|
+
11 => 'Continuous', # (GR III)
|
|
1150
|
+
12 => 'Snap', # (GR III)
|
|
1146
1151
|
16 => 'AF-S (Focus-priority)', #17
|
|
1147
1152
|
17 => 'AF-C (Focus-priority)', #17
|
|
1148
1153
|
18 => 'AF-A (Focus-priority)', #PH (educated guess)
|
|
@@ -1903,6 +1908,7 @@ my %binaryDataAttrs = (
|
|
|
1903
1908
|
'0 28' => 'Quick Macro', # (Q)
|
|
1904
1909
|
'0 29' => 'Forest', # (Q)
|
|
1905
1910
|
'0 30' => 'Backlight Silhouette', # (Q)
|
|
1911
|
+
'0 32' => 'DOF', #PH (GR III)
|
|
1906
1912
|
# AUTO PICT modes (auto-selected)
|
|
1907
1913
|
'1 4' => 'Auto PICT (Standard)', #13
|
|
1908
1914
|
'1 5' => 'Auto PICT (Portrait)', #7 (K100D)
|
|
@@ -2146,6 +2152,7 @@ my %binaryDataAttrs = (
|
|
|
2146
2152
|
10 => 'Cross Processing', #31 (K-70)
|
|
2147
2153
|
11 => 'Flat', #31 (K-70)
|
|
2148
2154
|
# 256 - seen for GR III
|
|
2155
|
+
# 257 - seen for GR III
|
|
2149
2156
|
# 262 - seen for GR III
|
|
2150
2157
|
32768 => 'n/a',
|
|
2151
2158
|
},
|
|
@@ -2584,8 +2591,10 @@ my %binaryDataAttrs = (
|
|
|
2584
2591
|
PrintConv => {
|
|
2585
2592
|
0 => 'Off',
|
|
2586
2593
|
1 => 'On',
|
|
2587
|
-
'0
|
|
2588
|
-
'1
|
|
2594
|
+
'0 0' => 'Off (Off)', #PH (GR III)
|
|
2595
|
+
'1 1' => 'On (On)', #PH (GR III)
|
|
2596
|
+
'0 2' => 'Off (Auto)', #PH (GR III)
|
|
2597
|
+
'1 2' => 'On (Auto)', #PH (GR III)
|
|
2589
2598
|
},
|
|
2590
2599
|
},
|
|
2591
2600
|
0x008b => { #PH (LS465)
|
|
@@ -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.
|
|
51
|
+
$VERSION = '2.91';
|
|
52
52
|
|
|
53
53
|
sub ProcessMOV($$;$);
|
|
54
54
|
sub ProcessKeys($$$);
|
|
@@ -638,6 +638,33 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
638
638
|
Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/ and $$self{OPTIONS}{ExtractEmbedded}',
|
|
639
639
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Tags360Fly' },
|
|
640
640
|
},
|
|
641
|
+
{ #https://c2pa.org/specifications/
|
|
642
|
+
Name => 'JUMBF',
|
|
643
|
+
Condition => '$$valPt=~/^\xd8\xfe\xc3\xd6\x1b\x0e\x48\x3c\x92\x97\x58\x28\x87\x7e\xc4\x81.{4}manifest\0/s',
|
|
644
|
+
Deletable => 1,
|
|
645
|
+
SubDirectory => {
|
|
646
|
+
TagTable => 'Image::ExifTool::Jpeg2000::Main',
|
|
647
|
+
# 16 bytes uuid
|
|
648
|
+
# +4 bytes 0
|
|
649
|
+
# +9 bytes "manifest\0"
|
|
650
|
+
# +8 bytes absolute(!!!) offset to C2PA uuid "merkle\0" box
|
|
651
|
+
# =37 bytes total
|
|
652
|
+
Start => 37,
|
|
653
|
+
},
|
|
654
|
+
},
|
|
655
|
+
{ #https://c2pa.org/specifications/ (NC)
|
|
656
|
+
Name => 'CBOR',
|
|
657
|
+
Condition => '$$valPt=~/^\xd8\xfe\xc3\xd6\x1b\x0e\x48\x3c\x92\x97\x58\x28\x87\x7e\xc4\x81.{4}merkle\0/s',
|
|
658
|
+
Deletable => 1, # (NC)
|
|
659
|
+
SubDirectory => {
|
|
660
|
+
TagTable => 'Image::ExifTool::CBOR::Main',
|
|
661
|
+
# 16 bytes uuid
|
|
662
|
+
# +4 bytes 0
|
|
663
|
+
# +7 bytes "merkle\0"
|
|
664
|
+
# =27 bytes total
|
|
665
|
+
Start => 27,
|
|
666
|
+
},
|
|
667
|
+
},
|
|
641
668
|
{
|
|
642
669
|
Name => 'SensorData',
|
|
643
670
|
Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/',
|
|
@@ -2311,16 +2338,33 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
2311
2338
|
# RDT9 - only 16-byte header?
|
|
2312
2339
|
# the boxes below all have a similar header (little-endian):
|
|
2313
2340
|
# 0 int32u - number of records
|
|
2314
|
-
# 4
|
|
2341
|
+
# 4 int32u - sample rate (Hz)
|
|
2315
2342
|
# 6 int16u - record length in bytes
|
|
2316
|
-
# 8
|
|
2317
|
-
#
|
|
2318
|
-
#
|
|
2319
|
-
|
|
2320
|
-
|
|
2343
|
+
# 8 int16u - 0x0123 = little-endian, 0x3210 = big endian
|
|
2344
|
+
# 10 int16u[3] - all zeros
|
|
2345
|
+
# 16 - start of records (each record ends in an int64u timestamp "ts" in ns)
|
|
2346
|
+
RDTA => {
|
|
2347
|
+
Name => 'RicohRDTA',
|
|
2348
|
+
SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::RDTA' },
|
|
2349
|
+
},
|
|
2350
|
+
RDTB => {
|
|
2351
|
+
Name => 'RicohRDTB',
|
|
2352
|
+
SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::RDTB' },
|
|
2353
|
+
},
|
|
2354
|
+
RDTC => {
|
|
2355
|
+
Name => 'RicohRDTC',
|
|
2356
|
+
SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::RDTC' },
|
|
2357
|
+
},
|
|
2321
2358
|
# RDTD - int16s[3],ts: "353 -914 16354 0 775.829"
|
|
2322
|
-
|
|
2359
|
+
RDTG => {
|
|
2360
|
+
Name => 'RicohRDTG',
|
|
2361
|
+
SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::RDTG' },
|
|
2362
|
+
},
|
|
2323
2363
|
# RDTI - float[4],ts: "0.00165951 0.005770059 0.06838259 0.1744695 775.862"
|
|
2364
|
+
RDTL => {
|
|
2365
|
+
Name => 'RicohRDTL',
|
|
2366
|
+
SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::RDTL' },
|
|
2367
|
+
},
|
|
2324
2368
|
# ---- Samsung ----
|
|
2325
2369
|
vndr => 'Vendor', #PH (Samsung PL70)
|
|
2326
2370
|
SDLN => 'PlayMode', #PH (NC, Samsung ST80 "SEQ_PLAY")
|
|
@@ -2344,7 +2388,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
2344
2388
|
# edli - 52 bytes all zero (Samsung WB30F)
|
|
2345
2389
|
# @etc - 4 bytes all zero (Samsung WB30F)
|
|
2346
2390
|
# saut - 4 bytes all zero (Samsung SM-N900T)
|
|
2347
|
-
# smrd - string "TRUEBLUE" (Samsung SM-C101)
|
|
2391
|
+
# smrd - string "TRUEBLUE" (Samsung SM-C101, etc)
|
|
2348
2392
|
# ---- TomTom Bandit Action Cam ----
|
|
2349
2393
|
TTMD => {
|
|
2350
2394
|
Name => 'TomTomMetaData',
|
|
@@ -2364,7 +2408,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
2364
2408
|
# opax - 164 bytes unknown (center and affine arrays? ref 26)
|
|
2365
2409
|
# opai - 32 bytes (maybe contains a serial number starting at byte 16? - PH) (rgb gains, degamma, gamma? ref 26)
|
|
2366
2410
|
# intv - 16 bytes all zero
|
|
2367
|
-
# ----
|
|
2411
|
+
# ---- Xiaomi ----
|
|
2368
2412
|
mcvr => {
|
|
2369
2413
|
Name => 'PreviewImage',
|
|
2370
2414
|
Groups => { 2 => 'Preview' },
|
|
@@ -6576,11 +6620,13 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
6576
6620
|
'collection.user' => 'UserCollection', #22
|
|
6577
6621
|
'Encoded_With' => 'EncodedWith',
|
|
6578
6622
|
'content.identifier' => 'ContentIdentifier', #forum14874
|
|
6623
|
+
'encoder' => { }, # forum15418 (written by ffmpeg)
|
|
6579
6624
|
#
|
|
6580
6625
|
# the following tags aren't in the com.apple.quicktime namespace:
|
|
6581
6626
|
#
|
|
6582
6627
|
'com.apple.photos.captureMode' => 'CaptureMode',
|
|
6583
6628
|
'com.android.version' => 'AndroidVersion',
|
|
6629
|
+
'com.android.capture.fps' => 'AndroidCaptureFPS',
|
|
6584
6630
|
#
|
|
6585
6631
|
# also seen
|
|
6586
6632
|
#
|
|
@@ -9504,7 +9550,7 @@ sub ProcessMOV($$;$)
|
|
|
9504
9550
|
# stop processing at mdat/idat if -fast2 is used
|
|
9505
9551
|
last if $fast > 1 and ($tag eq 'mdat' or ($tag eq 'idat' and $$et{FileType} ne 'HEIC'));
|
|
9506
9552
|
# load values only if associated with a tag (or verbose) and not too big
|
|
9507
|
-
if ($size > 0x2000000) { # start to get worried above 32
|
|
9553
|
+
if ($size > 0x2000000) { # start to get worried above 32 MiB
|
|
9508
9554
|
# check for RIFF trailer (written by Auto-Vox dashcam)
|
|
9509
9555
|
if ($buff =~ /^(gpsa|gps0|gsen|gsea)...\0/s) { # (yet seen only gpsa as first record)
|
|
9510
9556
|
$et->VPrint(0, "Found RIFF trailer");
|
|
@@ -9521,9 +9567,9 @@ sub ProcessMOV($$;$)
|
|
|
9521
9567
|
if ($tagInfo and not $$tagInfo{Unknown} and not $eeTag) {
|
|
9522
9568
|
my $t = PrintableTagID($tag,2);
|
|
9523
9569
|
if ($size > 0x8000000) {
|
|
9524
|
-
$et->Warn("Skipping '${t}' atom > 128
|
|
9570
|
+
$et->Warn("Skipping '${t}' atom > 128 MiB", 1);
|
|
9525
9571
|
} else {
|
|
9526
|
-
$et->Warn("Skipping '${t}' atom > 32
|
|
9572
|
+
$et->Warn("Skipping '${t}' atom > 32 MiB", 2) or $ignore = 0;
|
|
9527
9573
|
}
|
|
9528
9574
|
}
|
|
9529
9575
|
}
|
|
@@ -83,7 +83,8 @@ my %processByMetaFormat = (
|
|
|
83
83
|
|
|
84
84
|
# data lengths for each INSV/INSP record type
|
|
85
85
|
my %insvDataLen = (
|
|
86
|
-
|
|
86
|
+
0x000 => 0, # directory table (any size)
|
|
87
|
+
0x200 => 0, # PreviewImage (any size) (a duplicate of PreviewImage in APP2 of INSP files)
|
|
87
88
|
0x300 => 0, # accelerometer (could be either 20 or 56 bytes)
|
|
88
89
|
0x400 => 16, # exposure (ref 6)
|
|
89
90
|
0x600 => 8, # timestamps (ref 6)
|
|
@@ -91,6 +92,8 @@ my %insvDataLen = (
|
|
|
91
92
|
# 0x900 => 48, # ? (Insta360 X3)
|
|
92
93
|
# 0xa00 => 5?, # ? (Insta360 ONE RS)
|
|
93
94
|
# 0xb00 => 10, # ? (Insta360 X3)
|
|
95
|
+
# 0xd00 => 10, # ? (Insta360 Ace Pro)
|
|
96
|
+
# 0x1200 ? # ? (Insta360 Ace Pro)
|
|
94
97
|
);
|
|
95
98
|
|
|
96
99
|
# limit the default amount of data we read for some record types
|
|
@@ -106,7 +109,7 @@ my %insvLimit = (
|
|
|
106
109
|
The tags below are extracted from timed metadata in QuickTime and other
|
|
107
110
|
formats of video files when the ExtractEmbedded option is used. Although
|
|
108
111
|
most of these tags are combined into the single table below, ExifTool
|
|
109
|
-
currently reads
|
|
112
|
+
currently reads 67 different formats of timed GPS metadata from video files.
|
|
110
113
|
},
|
|
111
114
|
VARS => { NO_ID => 1 },
|
|
112
115
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
|
@@ -2043,7 +2046,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2043
2046
|
return 1;
|
|
2044
2047
|
|
|
2045
2048
|
} elsif ($$dataPt =~ /^.{28}A.{11}([NS]).{15}([EW])/s) {
|
|
2046
|
-
|
|
2049
|
+
|
|
2047
2050
|
$debug and $et->FoundTag(GPSType => '2G');
|
|
2048
2051
|
# Vantrue N4 dashcam
|
|
2049
2052
|
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
@@ -2778,7 +2781,7 @@ sub ProcessInsta360($;$)
|
|
|
2778
2781
|
my ($et, $dirInfo) = @_;
|
|
2779
2782
|
my $raf = $$et{RAF};
|
|
2780
2783
|
my $offset = $dirInfo ? $$dirInfo{Offset} || 0 : 0;
|
|
2781
|
-
my $buff;
|
|
2784
|
+
my ($buff, $dirTable, $dirTablePos);
|
|
2782
2785
|
|
|
2783
2786
|
return 0 unless $raf->Seek(-78-$offset, 2) and $raf->Read($buff, 78) == 78 and
|
|
2784
2787
|
substr($buff,-32) eq "8db42d694ccc418790edff439fe026bf"; # check magic number
|
|
@@ -2868,7 +2871,19 @@ sub ProcessInsta360($;$)
|
|
|
2868
2871
|
if ($len % $dlen and $id != 0x700) { # (have seen one 0x700 record which was expected format but not multiple of 53 bytes)
|
|
2869
2872
|
$et->Warn(sprintf('Unexpected Insta360 record 0x%x length',$id));
|
|
2870
2873
|
} elsif ($id == 0x200) {
|
|
2871
|
-
|
|
2874
|
+
# there are 4 types of record 0x200
|
|
2875
|
+
# 1. JPEG preview (starts with ff d8 ff e1)
|
|
2876
|
+
# 2. TIFF preview (starts with 01 00 00 00, then record length)
|
|
2877
|
+
# 3. Unknown 1 (starts with 00 00 00 01)
|
|
2878
|
+
# 4. Unknown 2 (starts with 00 00 01 34)
|
|
2879
|
+
if ($buff =~ /^\xff\xd8\xff/) {
|
|
2880
|
+
$et->FoundTag(PreviewImage => $buff);
|
|
2881
|
+
} elsif ($buff =~ /^\x01\0\0\0(.{4})\x01/s and unpack('V',$1) == $dlen) {
|
|
2882
|
+
my ($w, $h) = unpack('x16V2',$buff);
|
|
2883
|
+
# build the TIFF image (could the 1 at byte 9 be the SamplesPerPixel?)
|
|
2884
|
+
my $hdr = Image::ExifTool::MakeTiffHeader($w, $h, 1, 8);
|
|
2885
|
+
$et->FoundTag(PreviewTIFF => $hdr . substr($buff, 40));
|
|
2886
|
+
}
|
|
2872
2887
|
} elsif ($id == 0x300) {
|
|
2873
2888
|
for ($p=0; $p<$len; $p+=$dlen) {
|
|
2874
2889
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
@@ -2899,7 +2914,7 @@ sub ProcessInsta360($;$)
|
|
|
2899
2914
|
my $tmp = substr($buff, $p, $dlen);
|
|
2900
2915
|
my @a = unpack('VVvaa8aa8aa8a8a8', $tmp);
|
|
2901
2916
|
unless (($a[5] eq 'N' or $a[5] eq 'S') and # (quick validation)
|
|
2902
|
-
($a[7] eq 'E' or $a[7] eq 'W' or
|
|
2917
|
+
($a[7] eq 'E' or $a[7] eq 'W' or
|
|
2903
2918
|
# (odd, but I've seen "O" instead of "W". Perhaps
|
|
2904
2919
|
# when the language is french? ie. "Ouest"?)
|
|
2905
2920
|
$a[7] eq 'O'))
|
|
@@ -2913,13 +2928,15 @@ sub ProcessInsta360($;$)
|
|
|
2913
2928
|
$a[$_] = GetDouble(\$a[$_], 0) foreach 4,6,8,9,10;
|
|
2914
2929
|
$a[4] = -abs($a[4]) if $a[5] eq 'S'; # (abs just in case it was already signed)
|
|
2915
2930
|
$a[6] = -abs($a[6]) if $a[7] ne 'E';
|
|
2916
|
-
|
|
2931
|
+
my $ms = '';
|
|
2932
|
+
$a[2] and ($ms = sprintf('.%.3d', $a[2])) =~ s/0+$//;
|
|
2933
|
+
$et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($a[0]) . $ms . 'Z');
|
|
2917
2934
|
$et->HandleTag($tagTbl, GPSLatitude => $a[4]);
|
|
2918
2935
|
$et->HandleTag($tagTbl, GPSLongitude => $a[6]);
|
|
2919
2936
|
$et->HandleTag($tagTbl, GPSSpeed => $a[8] * $mpsToKph);
|
|
2920
2937
|
$et->HandleTag($tagTbl, GPSTrack => $a[9]);
|
|
2921
2938
|
$et->HandleTag($tagTbl, GPSAltitude => $a[10]);
|
|
2922
|
-
$et->HandleTag($tagTbl, Unknown02 =>
|
|
2939
|
+
$et->HandleTag($tagTbl, Unknown02 => $a[1]) if $unknown;
|
|
2923
2940
|
}
|
|
2924
2941
|
}
|
|
2925
2942
|
} elsif ($id == 0x101) {
|
|
@@ -2932,10 +2949,41 @@ sub ProcessInsta360($;$)
|
|
|
2932
2949
|
$et->HandleTag($tagTablePtr, $t, $val);
|
|
2933
2950
|
$p += 2 + $n;
|
|
2934
2951
|
}
|
|
2952
|
+
} elsif ($id == 0x0) {
|
|
2953
|
+
last if not $len;
|
|
2954
|
+
# example directory table for record locations from Insta360AcePro MP4 video:
|
|
2955
|
+
# vv vv - record ID
|
|
2956
|
+
# vv vv vv vv - record size
|
|
2957
|
+
# vv vv vv vv - offset from start of footer
|
|
2958
|
+
# 00 00 00 00 00 00 00 00 00 00
|
|
2959
|
+
# 01 01 82 04 00 00 1b 45 62 00
|
|
2960
|
+
# 02 00 28 46 05 00 ed fe 5c 00
|
|
2961
|
+
# 03 00 40 aa 24 00 ed fe 34 00
|
|
2962
|
+
# 04 00 00 c1 01 00 ed fe 30 00
|
|
2963
|
+
# [...]
|
|
2964
|
+
unless ($dirTable) {
|
|
2965
|
+
$dirTable = $buff;
|
|
2966
|
+
$dirTablePos = 0;
|
|
2967
|
+
}
|
|
2935
2968
|
}
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2969
|
+
# step through directory table instead of sequential scanning if possible
|
|
2970
|
+
if ($dirTable) {
|
|
2971
|
+
undef $epos;
|
|
2972
|
+
for (;;) {
|
|
2973
|
+
last if $dirTablePos + 10 > length($dirTable);
|
|
2974
|
+
my ($id, $siz, $off) = unpack("x${dirTablePos}vVV", $dirTable);
|
|
2975
|
+
$dirTablePos += 10;
|
|
2976
|
+
if ($id and $siz and $off + $siz < $trailerLen) {
|
|
2977
|
+
$epos = $off + $siz - $trailerLen;
|
|
2978
|
+
last;
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
last unless defined $epos;
|
|
2982
|
+
} else {
|
|
2983
|
+
($epos -= 6) + $trailerLen < 0 and last; # step back to previous record
|
|
2984
|
+
}
|
|
2985
|
+
$raf->Seek($epos, 2) or last; # seek to start of next footer
|
|
2986
|
+
$raf->Read($buff, 6) == 6 or last; # read footer
|
|
2939
2987
|
}
|
|
2940
2988
|
$$et{DOC_NUM} = 0;
|
|
2941
2989
|
SetByteOrder('MM');
|
|
@@ -616,9 +616,9 @@ numerical, and generated automatically otherwise.
|
|
|
616
616
|
arguments: the value, a flag which is set for the inverse
|
|
617
617
|
conversion, and a reference to the PrintConv hash, and returns
|
|
618
618
|
the converted value or undef on error -- it may call warn() to
|
|
619
|
-
return an error message.
|
|
619
|
+
return an error message. The lookup hash may also contain a
|
|
620
620
|
'Notes' entry which is used for documentation if the
|
|
621
|
-
SeparateTable flag is set).
|
|
621
|
+
SeparateTable flag is set). In an expression, $self is a
|
|
622
622
|
reference to the current ExifTool object, $val is the Raw
|
|
623
623
|
value, and $tag is the tag key. The subroutine takes 2
|
|
624
624
|
arguments: the Raw value and a reference to the current
|
|
@@ -894,6 +894,11 @@ numerical, and generated automatically otherwise.
|
|
|
894
894
|
writing this tag. Only needed if tag can be written to
|
|
895
895
|
groups other than the normal groups for this tag (very rare).
|
|
896
896
|
|
|
897
|
+
Deletable : [Writable SubDirectory's only] Overrides internal test for
|
|
898
|
+
metadata types with permanent directories (currently QuickTime
|
|
899
|
+
and Jpeg2000), allowing the tag containing these directories
|
|
900
|
+
to be deleted
|
|
901
|
+
|
|
897
902
|
OffsetPair : Used in EXIF table to specify the tagID for the corresponding
|
|
898
903
|
offset or length tag.
|
|
899
904
|
|
|
@@ -30,7 +30,7 @@ use strict;
|
|
|
30
30
|
use vars qw($VERSION $AUTOLOAD);
|
|
31
31
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
32
32
|
|
|
33
|
-
$VERSION = '1.
|
|
33
|
+
$VERSION = '1.67';
|
|
34
34
|
|
|
35
35
|
sub ConvertTimecode($);
|
|
36
36
|
sub ProcessSGLT($$$);
|
|
@@ -500,6 +500,11 @@ my %code2charset = (
|
|
|
500
500
|
Name => 'OldXMP',
|
|
501
501
|
Binary => 1,
|
|
502
502
|
},
|
|
503
|
+
C2PA => { #https://c2pa.org/specifications/
|
|
504
|
+
Name => 'JUMBF',
|
|
505
|
+
Deletable => 1,
|
|
506
|
+
SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::Main' },
|
|
507
|
+
},
|
|
503
508
|
olym => {
|
|
504
509
|
Name => 'Olym',
|
|
505
510
|
SubDirectory => { TagTable => 'Image::ExifTool::Olympus::WAV' },
|
|
@@ -1069,7 +1074,16 @@ my %code2charset = (
|
|
|
1069
1074
|
},
|
|
1070
1075
|
1 => {
|
|
1071
1076
|
Name => 'MaxDataRate',
|
|
1072
|
-
|
|
1077
|
+
Notes => q{
|
|
1078
|
+
converted using SI byte prefixes unles the API ByteUnit option is set to
|
|
1079
|
+
"Binary"
|
|
1080
|
+
},
|
|
1081
|
+
PrintConv => q{
|
|
1082
|
+
my ($unit, $div) = $self->Options('ByteUnit') eq 'Binary' ? ('KiB/s',1024) : ('kB/s',1000);
|
|
1083
|
+
my $tmp = $val / $div;
|
|
1084
|
+
$tmp > 9999 and $tmp /= $div, $unit =~ s/^./M/;
|
|
1085
|
+
sprintf('%.4g %s', $tmp, $unit);
|
|
1086
|
+
},
|
|
1073
1087
|
},
|
|
1074
1088
|
# 2 => 'PaddingGranularity',
|
|
1075
1089
|
# 3 => 'Flags',
|
|
@@ -1989,7 +2003,7 @@ sub ProcessRIFF($$)
|
|
|
1989
2003
|
{
|
|
1990
2004
|
my ($et, $dirInfo) = @_;
|
|
1991
2005
|
my $raf = $$dirInfo{RAF};
|
|
1992
|
-
my ($buff, $buf2, $type, $mime, $err, $rf64);
|
|
2006
|
+
my ($buff, $buf2, $type, $mime, $err, $rf64, $moviEnd);
|
|
1993
2007
|
my $verbose = $et->Options('Verbose');
|
|
1994
2008
|
my $unknown = $et->Options('Unknown');
|
|
1995
2009
|
my $validate = $et->Options('Validate');
|
|
@@ -2023,8 +2037,34 @@ sub ProcessRIFF($$)
|
|
|
2023
2037
|
# Read chunks in RIFF image
|
|
2024
2038
|
#
|
|
2025
2039
|
for (;;) {
|
|
2040
|
+
if ($err) {
|
|
2041
|
+
last unless $moviEnd;
|
|
2042
|
+
# we arrived here because there was a problem parsing the movie data
|
|
2043
|
+
# so seek to the end to continue processing
|
|
2044
|
+
if ($moviEnd > 0x7fffffff and not $et->Options('LargeFileSupport')) {
|
|
2045
|
+
$et->Warn('Possibly corrupt LIST_movi data');
|
|
2046
|
+
$et->Warn('Stopped parsing at large LIST_movi chunk (LargeFileSupport not set)');
|
|
2047
|
+
undef $err;
|
|
2048
|
+
last;
|
|
2049
|
+
}
|
|
2050
|
+
if ($validate) {
|
|
2051
|
+
# (must actually try to read something after seeking to detect error)
|
|
2052
|
+
$raf->Seek($moviEnd-1, 0) and $raf->Read($buff, 1) == 1 or last;
|
|
2053
|
+
} else {
|
|
2054
|
+
$raf->Seek($moviEnd, 0) or last;
|
|
2055
|
+
}
|
|
2056
|
+
$pos = $moviEnd;
|
|
2057
|
+
$et->Warn('Possibly corrupt LIST_movi data');
|
|
2058
|
+
undef $err;
|
|
2059
|
+
undef $moviEnd;
|
|
2060
|
+
}
|
|
2061
|
+
if ($moviEnd) {
|
|
2062
|
+
$pos > $moviEnd and $err = 1, next; # error if we parsed past the end of the movie data
|
|
2063
|
+
undef $moviEnd if $pos == $moviEnd; # parsed all movie data?
|
|
2064
|
+
}
|
|
2026
2065
|
my $num = $raf->Read($buff, 8);
|
|
2027
2066
|
if ($num < 8) {
|
|
2067
|
+
$moviEnd and $err = 1, next;
|
|
2028
2068
|
$err = 1 if $num;
|
|
2029
2069
|
$et->Warn('Incorrect RIFF chunk size' . " $pos vs. $riffEnd") if $validate and $pos != $riffEnd;
|
|
2030
2070
|
last;
|
|
@@ -2035,7 +2075,7 @@ sub ProcessRIFF($$)
|
|
|
2035
2075
|
$et->OverrideFileType('Extended WEBP',undef,'webp') if $tag eq 'VP8X' and $type eq 'WEBP';
|
|
2036
2076
|
# special case: construct new tag name from specific LIST type
|
|
2037
2077
|
if ($tag eq 'LIST') {
|
|
2038
|
-
$raf->Read($buff, 4) == 4 or $err=1,
|
|
2078
|
+
$raf->Read($buff, 4) == 4 or $err=1, next;
|
|
2039
2079
|
$pos += 4;
|
|
2040
2080
|
$tag .= "_$buff";
|
|
2041
2081
|
$len -= 4; # already read 4 bytes (the LIST type)
|
|
@@ -2044,6 +2084,7 @@ sub ProcessRIFF($$)
|
|
|
2044
2084
|
}
|
|
2045
2085
|
$et->VPrint(0, "RIFF '${tag}' chunk ($len bytes of data):\n");
|
|
2046
2086
|
if ($len <= 0) {
|
|
2087
|
+
$moviEnd and $err = 1, next;
|
|
2047
2088
|
if ($len < 0) {
|
|
2048
2089
|
$et->Warn('Invalid chunk length');
|
|
2049
2090
|
} elsif ($tag eq "\0\0\0\0") {
|
|
@@ -2074,7 +2115,7 @@ sub ProcessRIFF($$)
|
|
|
2074
2115
|
my $tagInfo = $$tagTbl{$tag};
|
|
2075
2116
|
# (in LIST_movi chunk: ##db = uncompressed DIB, ##dc = compressed DIB, ##wb = audio data)
|
|
2076
2117
|
if ($tagInfo or (($verbose or $unknown) and $tag !~ /^(data|idx1|LIST_movi|RIFF|\d{2}(db|dc|wb))$/)) {
|
|
2077
|
-
$raf->Read($buff, $len2) == $len2 or $err=1,
|
|
2118
|
+
$raf->Read($buff, $len2) == $len2 or $err=1, next;
|
|
2078
2119
|
if ($hash and $isImageData{$tag}) {
|
|
2079
2120
|
$hash->add($buff);
|
|
2080
2121
|
$et->VPrint(0, "$$et{INDENT}(ImageDataHash: '${tag}' chunk, $len2 bytes)\n");
|
|
@@ -2100,7 +2141,7 @@ sub ProcessRIFF($$)
|
|
|
2100
2141
|
$et->Warn('Incorrect RIFF chunk size') if $validate and $pos - 8 != $riffEnd;
|
|
2101
2142
|
$riffEnd += $len2 + 8;
|
|
2102
2143
|
# don't read into RIFF chunk (eg. concatenated video file)
|
|
2103
|
-
$raf->Read($buff, 4) == 4 or $err=1,
|
|
2144
|
+
$raf->Read($buff, 4) == 4 or $err=1, next; # (skip RIFF type word)
|
|
2104
2145
|
$pos += 4;
|
|
2105
2146
|
# extract information from remaining file as an embedded file
|
|
2106
2147
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
@@ -2113,18 +2154,21 @@ sub ProcessRIFF($$)
|
|
|
2113
2154
|
$et->ImageDataHash($raf, $len2, "'${tag}' chunk");
|
|
2114
2155
|
}
|
|
2115
2156
|
if ($tag eq 'LIST_movi' and $ee) {
|
|
2116
|
-
$raf->Seek($rewind, 0) or $err = 1,
|
|
2157
|
+
$raf->Seek($rewind, 0) or $err = 1, next if $rewind;
|
|
2158
|
+
# save end-of-movie offset so we can seek there if we get errors parsing the movie data
|
|
2159
|
+
$moviEnd = $raf->Tell() + $len2;
|
|
2117
2160
|
next; # parse into movi chunk
|
|
2118
2161
|
} elsif (not $rewind) {
|
|
2119
2162
|
if ($len > 0x7fffffff and not $et->Options('LargeFileSupport')) {
|
|
2163
|
+
$tag =~ s/([\0-\x1f\x7f-\xff])/sprintf('\\x%.2x',ord $1)/eg;
|
|
2120
2164
|
$et->Warn("Stopped parsing at large $tag chunk (LargeFileSupport not set)");
|
|
2121
2165
|
last;
|
|
2122
2166
|
}
|
|
2123
2167
|
if ($validate and $len2) {
|
|
2124
2168
|
# (must actually try to read something after seeking to detect error)
|
|
2125
|
-
$raf->Seek($len2-1, 1) and $raf->Read($buff, 1) == 1 or $err = 1,
|
|
2169
|
+
$raf->Seek($len2-1, 1) and $raf->Read($buff, 1) == 1 or $err = 1, next;
|
|
2126
2170
|
} else {
|
|
2127
|
-
$raf->Seek($len2, 1) or $err=1,
|
|
2171
|
+
$raf->Seek($len2, 1) or $err=1, next;
|
|
2128
2172
|
}
|
|
2129
2173
|
}
|
|
2130
2174
|
}
|