exiftool_vendored 12.08.0 → 12.13.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of exiftool_vendored might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/bin/Changes +85 -2
- data/bin/MANIFEST +2 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +43 -43
- data/bin/exiftool +176 -96
- data/bin/lib/Image/ExifTool.pm +15 -9
- data/bin/lib/Image/ExifTool.pod +62 -52
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +14 -4
- data/bin/lib/Image/ExifTool/Canon.pm +181 -15
- data/bin/lib/Image/ExifTool/DarwinCore.pm +7 -5
- data/bin/lib/Image/ExifTool/GIF.pm +2 -2
- data/bin/lib/Image/ExifTool/Geotag.pm +29 -10
- data/bin/lib/Image/ExifTool/GoPro.pm +1 -9
- data/bin/lib/Image/ExifTool/Import.pm +14 -11
- data/bin/lib/Image/ExifTool/JSON.pm +27 -4
- data/bin/lib/Image/ExifTool/MPF.pm +2 -2
- data/bin/lib/Image/ExifTool/MacOS.pm +3 -1
- data/bin/lib/Image/ExifTool/Matroska.pm +3 -1
- data/bin/lib/Image/ExifTool/Minolta.pm +2 -1
- data/bin/lib/Image/ExifTool/Nikon.pm +7 -4
- data/bin/lib/Image/ExifTool/Olympus.pm +3 -1
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +1 -0
- data/bin/lib/Image/ExifTool/Pentax.pm +10 -3
- data/bin/lib/Image/ExifTool/QuickTime.pm +52 -22
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +50 -37
- data/bin/lib/Image/ExifTool/README +5 -2
- data/bin/lib/Image/ExifTool/Radiance.pm +7 -2
- data/bin/lib/Image/ExifTool/Sony.pm +16 -17
- data/bin/lib/Image/ExifTool/Stim.pm +2 -2
- data/bin/lib/Image/ExifTool/TagLookup.pm +5756 -5710
- data/bin/lib/Image/ExifTool/TagNames.pod +210 -19
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +7 -6
- data/bin/lib/Image/ExifTool/Writer.pl +20 -14
- data/bin/lib/Image/ExifTool/XMP.pm +62 -17
- data/bin/lib/Image/ExifTool/XMP2.pl +5 -0
- data/bin/perl-Image-ExifTool.spec +42 -42
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +3 -3
@@ -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.35';
|
62
62
|
|
63
63
|
sub CryptShutterCount($$);
|
64
64
|
sub PrintFilter($$$);
|
@@ -2894,13 +2894,20 @@ my %binaryDataAttrs = (
|
|
2894
2894
|
Writable => 'string',
|
2895
2895
|
Notes => 'left blank by some cameras',
|
2896
2896
|
},
|
2897
|
-
0x022a => { #PH (
|
2897
|
+
0x022a => [{ #PH (RICOH models (GR III))
|
2898
|
+
Name => 'FilterInfo',
|
2899
|
+
Condition => '$$self{Make} =~ /^RICOH/',
|
2900
|
+
SubDirectory => {
|
2901
|
+
TagTable => 'Image::ExifTool::Pentax::FilterInfo',
|
2902
|
+
ByteOrder => 'LittleEndian',
|
2903
|
+
},
|
2904
|
+
},{ #PH (K-5)
|
2898
2905
|
Name => 'FilterInfo',
|
2899
2906
|
SubDirectory => {
|
2900
2907
|
TagTable => 'Image::ExifTool::Pentax::FilterInfo',
|
2901
2908
|
ByteOrder => 'BigEndian',
|
2902
2909
|
},
|
2903
|
-
},
|
2910
|
+
}],
|
2904
2911
|
0x022b => { #PH (K-5)
|
2905
2912
|
Name => 'LevelInfo',
|
2906
2913
|
SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LevelInfo' },
|
@@ -47,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
47
47
|
use Image::ExifTool::Exif;
|
48
48
|
use Image::ExifTool::GPS;
|
49
49
|
|
50
|
-
$VERSION = '2.
|
50
|
+
$VERSION = '2.56';
|
51
51
|
|
52
52
|
sub ProcessMOV($$;$);
|
53
53
|
sub ProcessKeys($$$);
|
@@ -214,11 +214,16 @@ my %ftypLookup = (
|
|
214
214
|
'crx ' => 'Canon Raw (.CRX)', #PH (CR3 or CRM; use Canon CompressorVersion to decide)
|
215
215
|
);
|
216
216
|
|
217
|
-
# information for time
|
217
|
+
# information for int32u date/time tags (time zero is Jan 1, 1904)
|
218
218
|
my %timeInfo = (
|
219
219
|
Notes => 'converted from UTC to local time if the QuickTimeUTC option is set',
|
220
|
+
Shift => 'Time',
|
221
|
+
Writable => 1,
|
222
|
+
Permanent => 1,
|
223
|
+
DelValue => 0,
|
220
224
|
# It is not uncommon for brain-dead software to use the wrong time zero,
|
221
225
|
# so assume a time zero of Jan 1, 1970 if the date is before this
|
226
|
+
# Note: This value will be in UTC if generated by a system that is aware of the time zone
|
222
227
|
RawConv => q{
|
223
228
|
my $offset = (66 * 365 + 17) * 24 * 3600;
|
224
229
|
return $val - $offset if $val >= $offset or $$self{OPTIONS}{QuickTimeUTC};
|
@@ -227,12 +232,17 @@ my %timeInfo = (
|
|
227
232
|
}
|
228
233
|
return $val;
|
229
234
|
},
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
235
|
+
RawConvInv => q{
|
236
|
+
if ($$self{FileType} eq 'CR3' and not $self->Options('QuickTimeUTC')) {
|
237
|
+
# convert to UTC
|
238
|
+
my $offset = (66 * 365 + 17) * 24 * 3600;
|
239
|
+
$val = ConvertUnixTime($val - $offset);
|
240
|
+
$val = GetUnixTime($val, 1) + $offset;
|
241
|
+
}
|
242
|
+
return $val;
|
243
|
+
},
|
244
|
+
# (all CR3 files store UTC times - PH)
|
245
|
+
ValueConv => 'ConvertUnixTime($val, $self->Options("QuickTimeUTC") || $$self{FileType} eq "CR3")',
|
236
246
|
ValueConvInv => 'GetUnixTime($val, $self->Options("QuickTimeUTC")) + (66 * 365 + 17) * 24 * 3600',
|
237
247
|
PrintConv => '$self->ConvertDateTime($val)',
|
238
248
|
PrintConvInv => '$self->InverseDateTime($val)',
|
@@ -672,7 +682,7 @@ my %eeBox = (
|
|
672
682
|
ValueConv => '$val=~tr/-/:/; $val',
|
673
683
|
ValueConvInv => '$val=~s/(\d+):(\d+):/$1-$2-/; $val',
|
674
684
|
PrintConv => '$self->ConvertDateTime($val)',
|
675
|
-
PrintConvInv => '$self->InverseDateTime($val)',
|
685
|
+
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
|
676
686
|
},
|
677
687
|
gps0 => { #PH (DuDuBell M1, VSYS M6L)
|
678
688
|
Name => 'GPSTrack',
|
@@ -1405,7 +1415,7 @@ my %eeBox = (
|
|
1405
1415
|
return $val;
|
1406
1416
|
},
|
1407
1417
|
PrintConv => '$self->ConvertDateTime($val)',
|
1408
|
-
PrintConvInv => '$self->InverseDateTime($val)',
|
1418
|
+
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
|
1409
1419
|
},
|
1410
1420
|
"\xa9ART" => 'Artist', #PH (iTunes 8.0.2)
|
1411
1421
|
"\xa9alb" => 'Album', #PH (iTunes 8.0.2)
|
@@ -1679,7 +1689,7 @@ my %eeBox = (
|
|
1679
1689
|
return $val;
|
1680
1690
|
},
|
1681
1691
|
PrintConv => '$self->ConvertDateTime($val)',
|
1682
|
-
PrintConvInv => '$self->InverseDateTime($val)',
|
1692
|
+
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
|
1683
1693
|
},
|
1684
1694
|
manu => { # (SX280)
|
1685
1695
|
Name => 'Make',
|
@@ -2114,7 +2124,7 @@ my %eeBox = (
|
|
2114
2124
|
return $val;
|
2115
2125
|
},
|
2116
2126
|
PrintConv => '$self->ConvertDateTime($val)',
|
2117
|
-
PrintConvInv => '$self->InverseDateTime($val)',
|
2127
|
+
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
|
2118
2128
|
},
|
2119
2129
|
'@xyz' => { #PH (iPhone 3GS)
|
2120
2130
|
Name => 'GPSCoordinates',
|
@@ -2555,7 +2565,23 @@ my %eeBox = (
|
|
2555
2565
|
Start => 4,
|
2556
2566
|
},
|
2557
2567
|
},
|
2558
|
-
|
2568
|
+
idat => {
|
2569
|
+
Name => 'MetaImageSize', #PH (NC)
|
2570
|
+
Format => 'int16u',
|
2571
|
+
# (don't know what the first two numbers are for)
|
2572
|
+
PrintConv => '$val =~ s/^(\d+) (\d+) (\d+) (\d+)/${3}x$4/; $val',
|
2573
|
+
},
|
2574
|
+
uuid => [
|
2575
|
+
{ #PH (Canon R5/R6 HIF)
|
2576
|
+
Name => 'MetaVersion', # (NC)
|
2577
|
+
Condition => '$$valPt=~/^\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48/',
|
2578
|
+
RawConv => 'substr($val, 0x14)',
|
2579
|
+
},
|
2580
|
+
{
|
2581
|
+
Name => 'UUID-Unknown',
|
2582
|
+
%unknownInfo,
|
2583
|
+
},
|
2584
|
+
],
|
2559
2585
|
);
|
2560
2586
|
|
2561
2587
|
# additional metadata container (ref ISO14496-12:2015)
|
@@ -2867,12 +2893,16 @@ my %eeBox = (
|
|
2867
2893
|
WRITE_PROC => \&WriteQuickTime,
|
2868
2894
|
GROUPS => { 2 => 'Image' },
|
2869
2895
|
# (Note: ExifTool's ItemRefVersion may be used to test the iref version number)
|
2870
|
-
|
2871
|
-
|
2872
|
-
|
2896
|
+
NOTES => q{
|
2897
|
+
The Item reference entries listed in the table below contain information about
|
2898
|
+
the associations between items in the file. This information is used by
|
2899
|
+
ExifTool, but these entries are not extracted as tags.
|
2900
|
+
},
|
2901
|
+
dimg => { Name => 'DerivedImageRef', RawConv => 'undef' },
|
2902
|
+
thmb => { Name => 'ThumbnailRef', RawConv => 'undef' },
|
2903
|
+
auxl => { Name => 'AuxiliaryImageRef', RawConv => 'undef' },
|
2873
2904
|
cdsc => {
|
2874
2905
|
Name => 'ContentDescribes',
|
2875
|
-
Notes => 'parsed, but not extracted as a tag',
|
2876
2906
|
RawConv => \&ParseContentDescribes,
|
2877
2907
|
WriteHook => \&ParseContentDescribes,
|
2878
2908
|
},
|
@@ -2992,7 +3022,7 @@ my %eeBox = (
|
|
2992
3022
|
return $val;
|
2993
3023
|
},
|
2994
3024
|
PrintConv => '$self->ConvertDateTime($val)',
|
2995
|
-
PrintConvInv => '$self->InverseDateTime($val)',
|
3025
|
+
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
|
2996
3026
|
},
|
2997
3027
|
"\xa9des" => 'Description', #4
|
2998
3028
|
"\xa9enc" => 'EncodedBy', #10
|
@@ -6170,7 +6200,7 @@ my %eeBox = (
|
|
6170
6200
|
return $val;
|
6171
6201
|
},
|
6172
6202
|
PrintConv => '$self->ConvertDateTime($val)',
|
6173
|
-
PrintConvInv => '$self->InverseDateTime($val)',
|
6203
|
+
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
|
6174
6204
|
},
|
6175
6205
|
description => { },
|
6176
6206
|
director => { },
|
@@ -6230,7 +6260,7 @@ my %eeBox = (
|
|
6230
6260
|
return $val;
|
6231
6261
|
},
|
6232
6262
|
PrintConv => '$self->ConvertDateTime($val)',
|
6233
|
-
PrintConvInv => '$self->InverseDateTime($val)',
|
6263
|
+
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
|
6234
6264
|
},
|
6235
6265
|
'direction.facing' => { Name => 'CameraDirection', Groups => { 2 => 'Location' } },
|
6236
6266
|
'direction.motion' => { Name => 'CameraMotion', Groups => { 2 => 'Location' } },
|
@@ -8618,10 +8648,10 @@ sub ProcessSampleDesc($$$)
|
|
8618
8648
|
my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $pos);
|
8619
8649
|
return 0 if $pos + 8 > $dirLen;
|
8620
8650
|
|
8621
|
-
my $num = Get32u($dataPt, 4); # get number of sample
|
8651
|
+
my $num = Get32u($dataPt, 4); # get number of sample entries in table
|
8622
8652
|
$pos += 8;
|
8623
8653
|
my $i;
|
8624
|
-
for ($i=0; $i<$num; ++$i) { # loop through sample
|
8654
|
+
for ($i=0; $i<$num; ++$i) { # loop through sample entries
|
8625
8655
|
last if $pos + 8 > $dirLen;
|
8626
8656
|
my $size = Get32u($dataPt, $pos);
|
8627
8657
|
last if $pos + $size > $dirLen;
|
@@ -165,10 +165,17 @@ my %insvLimit = (
|
|
165
165
|
ProcessProc => \&Process_mebx,
|
166
166
|
},
|
167
167
|
},
|
168
|
-
gpmd => {
|
169
|
-
Name => '
|
168
|
+
gpmd => [{
|
169
|
+
Name => 'gpmd_GoPro',
|
170
|
+
Condition => '$$valPt !~ /^\0\0\xf2\xe1\xf0\xeeTT/',
|
170
171
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
|
171
|
-
},
|
172
|
+
},{
|
173
|
+
Name => 'gpmd_Rove', # Rove Stealth 4K encrypted text
|
174
|
+
SubDirectory => {
|
175
|
+
TagTable => 'Image::ExifTool::QuickTime::Stream',
|
176
|
+
ProcessProc => \&Process_text,
|
177
|
+
},
|
178
|
+
}],
|
172
179
|
fdsc => {
|
173
180
|
Name => 'fdsc',
|
174
181
|
Condition => '$$valPt =~ /^GPRO/',
|
@@ -837,15 +844,21 @@ sub HandleTextTags($$$)
|
|
837
844
|
|
838
845
|
#------------------------------------------------------------------------------
|
839
846
|
# Process subtitle 'text'
|
840
|
-
# Inputs: 0) ExifTool ref, 1)
|
847
|
+
# Inputs: 0) ExifTool ref, 1) data ref or dirInfo ref, 2) tag table ref
|
841
848
|
sub Process_text($$$)
|
842
849
|
{
|
843
|
-
my ($et, $
|
850
|
+
my ($et, $dataPt, $tagTbl) = @_;
|
844
851
|
my %tags;
|
845
852
|
|
846
853
|
return if $$et{NoMoreTextDecoding};
|
847
854
|
|
848
|
-
|
855
|
+
if (ref $dataPt eq 'HASH') {
|
856
|
+
my $dirName = $$dataPt{DirName};
|
857
|
+
$dataPt = $$dataPt{DataPt};
|
858
|
+
$et->VerboseDir($dirName, undef, length($$dataPt));
|
859
|
+
}
|
860
|
+
|
861
|
+
while ($$dataPt =~ /\$(\w+)([^\$]*)/g) {
|
849
862
|
my ($tag, $dat) = ($1, $2);
|
850
863
|
if ($tag =~ /^[A-Z]{2}RMC$/ and $dat =~ /^,(\d{2})(\d{2})(\d+(?:\.\d*)),A?,(\d*?)(\d{1,2}\.\d+),([NS]),(\d*?)(\d{1,2}\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/) {
|
851
864
|
my $time = "$1:$2:$3";
|
@@ -936,31 +949,31 @@ sub Process_text($$$)
|
|
936
949
|
# 0110: 31 30 38 30 30 30 58 00 58 00 58 00 58 00 58 00 [108000X.X.X.X.X.]
|
937
950
|
# 0120: 58 00 58 00 58 00 58 00 00 00 00 00 00 00 00 00 [X.X.X.X.........]
|
938
951
|
# 0130: 00 00 00 00 00 00 00 [.......]
|
939
|
-
if ($$
|
940
|
-
my $val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
952
|
+
if ($$dataPt =~ /^\0\0(..\xaa\xaa|\xf2\xe1\xf0\xee)/s and length $$dataPt >= 282) {
|
953
|
+
my $val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 8, 14)));
|
941
954
|
if ($val =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/) {
|
942
955
|
$tags{GPSDateTime} = "$1:$2:$3 $4:$5:$6";
|
943
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
956
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 38, 9)));
|
944
957
|
if ($val =~ /^([NS])(\d{2})(\d+$)$/) {
|
945
958
|
$tags{GPSLatitude} = ($2 + $3 / 600000) * ($1 eq 'S' ? -1 : 1);
|
946
959
|
}
|
947
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
960
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 47, 10)));
|
948
961
|
if ($val =~ /^([EW])(\d{3})(\d+$)$/) {
|
949
962
|
$tags{GPSLongitude} = ($2 + $3 / 600000) * ($1 eq 'W' ? -1 : 1);
|
950
963
|
}
|
951
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
964
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0x39, 5)));
|
952
965
|
$tags{GPSAltitude} = $val + 0 if $val =~ /^[-+]\d+$/;
|
953
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
966
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0x3e, 3)));
|
954
967
|
if ($val =~ /^\d+$/) {
|
955
968
|
$tags{GPSSpeed} = $val + 0;
|
956
969
|
$tags{GPSSpeedRef} = 'K';
|
957
970
|
}
|
958
|
-
if ($$
|
959
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
971
|
+
if ($$dataPt =~ /^\0\0..\xaa\xaa/s) { # (BlueSkySea)
|
972
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0xad, 12)));
|
960
973
|
# the first X,Y,Z accelerometer readings from the AccelerometerData
|
961
974
|
if ($val =~ /^([-+]\d{3})([-+]\d{3})([-+]\d{3})$/) {
|
962
975
|
$tags{Accelerometer} = "$1 $2 $3";
|
963
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
976
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0xba, 96)));
|
964
977
|
my $order = GetByteOrder();
|
965
978
|
SetByteOrder('II');
|
966
979
|
$val = ReadValue(\$val, 0, 'float');
|
@@ -969,7 +982,7 @@ sub Process_text($$$)
|
|
969
982
|
}
|
970
983
|
} else { # (Ambarella)
|
971
984
|
my @acc;
|
972
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
985
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0x41, 195)));
|
973
986
|
push @acc, $1, $2, $3 while $val =~ /\G([-+]\d{3})([-+]\d{3})([-+]\d{3})/g;
|
974
987
|
$tags{Accelerometer} = "@acc" if @acc;
|
975
988
|
}
|
@@ -980,36 +993,36 @@ sub Process_text($$$)
|
|
980
993
|
# check for DJI telemetry data, eg:
|
981
994
|
# "F/3.5, SS 1000, ISO 100, EV 0, GPS (8.6499, 53.1665, 18), D 24.26m,
|
982
995
|
# H 6.00m, H.S 2.10m/s, V.S 0.00m/s \n"
|
983
|
-
if ($$
|
996
|
+
if ($$dataPt =~ /GPS \(([-+]?\d*\.\d+),\s*([-+]?\d*\.\d+)/) {
|
984
997
|
$$et{CreateDateAtEnd} = 1; # set flag indicating the file creation date is at the end
|
985
998
|
$tags{GPSLatitude} = $2;
|
986
999
|
$tags{GPSLongitude} = $1;
|
987
|
-
$tags{GPSAltitude} = $1 if $$
|
988
|
-
if ($$
|
1000
|
+
$tags{GPSAltitude} = $1 if $$dataPt =~ /,\s*H\s+([-+]?\d+\.?\d*)m/;
|
1001
|
+
if ($$dataPt =~ /,\s*H.S\s+([-+]?\d+\.?\d*)/) {
|
989
1002
|
$tags{GPSSpeed} = $1 * $mpsToKph;
|
990
1003
|
$tags{GPSSpeedRef} = 'K';
|
991
1004
|
}
|
992
|
-
$tags{Distance} = $1 * $mpsToKph if $$
|
993
|
-
$tags{VerticalSpeed} = $1 if $$
|
994
|
-
$tags{FNumber} = $1 if $$
|
995
|
-
$tags{ExposureTime} = 1 / $1 if $$
|
996
|
-
$tags{ExposureCompensation} = ($1 / ($2 || 1)) if $$
|
997
|
-
$tags{ISO} = $1 if $$
|
1005
|
+
$tags{Distance} = $1 * $mpsToKph if $$dataPt =~ /,\s*D\s+(\d+\.?\d*)m/;
|
1006
|
+
$tags{VerticalSpeed} = $1 if $$dataPt =~ /,\s*V.S\s+([-+]?\d+\.?\d*)/;
|
1007
|
+
$tags{FNumber} = $1 if $$dataPt =~ /\bF\/(\d+\.?\d*)/;
|
1008
|
+
$tags{ExposureTime} = 1 / $1 if $$dataPt =~ /\bSS\s+(\d+\.?\d*)/;
|
1009
|
+
$tags{ExposureCompensation} = ($1 / ($2 || 1)) if $$dataPt =~ /\bEV\s+([-+]?\d+\.?\d*)(\/\d+)?/;
|
1010
|
+
$tags{ISO} = $1 if $$dataPt =~ /\bISO\s+(\d+\.?\d*)/;
|
998
1011
|
HandleTextTags($et, $tagTbl, \%tags);
|
999
1012
|
return;
|
1000
1013
|
}
|
1001
1014
|
|
1002
1015
|
# check for Mini 0806 dashcam GPS, eg:
|
1003
1016
|
# "A,270519,201555.000,3356.8925,N,08420.2071,W,000.0,331.0M,+01.84,-09.80,-00.61;\n"
|
1004
|
-
if ($$
|
1017
|
+
if ($$dataPt =~ /^A,(\d{2})(\d{2})(\d{2}),(\d{2})(\d{2})(\d{2}(\.\d+)?)/) {
|
1005
1018
|
$tags{GPSDateTime} = "20$3:$2:$1 $4:$5:$6Z";
|
1006
|
-
if ($$
|
1019
|
+
if ($$dataPt =~ /^A,.*?,.*?,(\d{2})(\d+\.\d+),([NS])/) {
|
1007
1020
|
$tags{GPSLatitude} = ($1 + $2/60) * ($3 eq 'S' ? -1 : 1);
|
1008
1021
|
}
|
1009
|
-
if ($$
|
1022
|
+
if ($$dataPt =~ /^A,.*?,.*?,.*?,.*?,(\d{3})(\d+\.\d+),([EW])/) {
|
1010
1023
|
$tags{GPSLongitude} = ($1 + $2/60) * ($3 eq 'W' ? -1 : 1);
|
1011
1024
|
}
|
1012
|
-
my @a = split ',', $$
|
1025
|
+
my @a = split ',', $$dataPt;
|
1013
1026
|
$tags{GPSAltitude} = $a[8] if $a[8] and $a[8] =~ s/M$//;
|
1014
1027
|
$tags{GPSSpeed} = $a[7] if $a[7] and $a[7] =~ /^\d+\.\d+$/; # (NC)
|
1015
1028
|
$tags{Accelerometer} = "$a[9] $a[10] $a[11]" if $a[11] and $a[11] =~ s/;\s*$//;
|
@@ -1022,10 +1035,10 @@ sub Process_text($$$)
|
|
1022
1035
|
# decoded:
|
1023
1036
|
# "X0000.2340Y-000.0720Z0000.9900G0001.0400$GPRMC,082138,A,5330.6683,N,00641.9749,W,012.5,87.86,050213,002.1,A"
|
1024
1037
|
# (note: "002.1" is magnetic variation and is not decoded; it should have ",E" or ",W" afterward for direction)
|
1025
|
-
if ($$
|
1038
|
+
if ($$dataPt =~ /\*[0-9A-F]{2}~$/) {
|
1026
1039
|
# (ref https://reverseengineering.stackexchange.com/questions/11582/how-to-reverse-engineer-dash-cam-metadata)
|
1027
1040
|
my @decode = unpack 'C*', '-I8XQWRVNZOYPUTA0B1C2SJ9K.L,M$D3E4F5G6H7';
|
1028
|
-
my @chars = unpack 'C*', substr($$
|
1041
|
+
my @chars = unpack 'C*', substr($$dataPt, 0, -4);
|
1029
1042
|
foreach (@chars) {
|
1030
1043
|
my $n = $_ - 43;
|
1031
1044
|
$_ = $decode[$n] if $n >= 0 and defined $decode[$n];
|
@@ -1034,14 +1047,14 @@ sub Process_text($$$)
|
|
1034
1047
|
if ($buff =~ /X(.*?)Y(.*?)Z(.*?)G(.*?)\$/) {
|
1035
1048
|
# yup. the decoding worked out
|
1036
1049
|
$tags{Accelerometer} = "$1 $2 $3 $4";
|
1037
|
-
$$
|
1050
|
+
$$dataPt = $buff; # (process GPRMC below)
|
1038
1051
|
}
|
1039
1052
|
}
|
1040
1053
|
|
1041
1054
|
# check for Thinkware format (and other NMEA RMC), eg:
|
1042
1055
|
# "gsensori,4,512,-67,-12,100;GNRMC,161313.00,A,4529.87489,N,07337.01215,W,6.225,35.34,310819,,,A*52..;
|
1043
1056
|
# CAR,0,0,0,0.0,0,0,0,0,0,0,0,0"
|
1044
|
-
if ($$
|
1057
|
+
if ($$dataPt =~ /[A-Z]{2}RMC,(\d{2})(\d{2})(\d+(\.\d*)?),A?,(\d*?)(\d{1,2}\.\d+),([NS]),(\d*?)(\d{1,2}\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/ and
|
1045
1058
|
# do some basic sanity checks on the date
|
1046
1059
|
$13 <= 31 and $14 <= 12 and $15 <= 99)
|
1047
1060
|
{
|
@@ -1058,8 +1071,8 @@ sub Process_text($$$)
|
|
1058
1071
|
$tags{GPSTrackRef} = 'T';
|
1059
1072
|
}
|
1060
1073
|
}
|
1061
|
-
$tags{GSensor} = $1 if $$
|
1062
|
-
$tags{Car} = $1 if $$
|
1074
|
+
$tags{GSensor} = $1 if $$dataPt =~ /\bgsensori,(.*?)(;|$)/;
|
1075
|
+
$tags{Car} = $1 if $$dataPt =~ /\bCAR,(.*?)(;|$)/;
|
1063
1076
|
|
1064
1077
|
if (%tags) {
|
1065
1078
|
HandleTextTags($et, $tagTbl, \%tags);
|
@@ -1233,7 +1246,7 @@ sub ProcessSamples($)
|
|
1233
1246
|
$et->HandleTag($tagTbl, Text => $buff); # just store any other text
|
1234
1247
|
}
|
1235
1248
|
}
|
1236
|
-
Process_text($et, $tagTbl
|
1249
|
+
Process_text($et, \$buff, $tagTbl);
|
1237
1250
|
|
1238
1251
|
} elsif ($processByMetaFormat{$type}) {
|
1239
1252
|
|
@@ -1254,7 +1267,7 @@ sub ProcessSamples($)
|
|
1254
1267
|
# "X0000.0000Y0000.0000Z0000.0000G0000.0000$GPRMC,000125,V,,,,,000.0,,280908,002.1,N*71~, 794021 \x0a"
|
1255
1268
|
FoundSomething($et, $tagTbl, $time[$i], $dur[$i]);
|
1256
1269
|
$et->HandleTag($tagTbl, Accelerometer => "$1 $2 $3 $4") if $buff =~ /X(.*?)Y(.*?)Z(.*?)G(.*?)\$/;
|
1257
|
-
Process_text($et, $tagTbl
|
1270
|
+
Process_text($et, \$buff, $tagTbl);
|
1258
1271
|
}
|
1259
1272
|
} elsif ($verbose) {
|
1260
1273
|
$et->VPrint(0, "Unknown $type format ($metaFormat)");
|
@@ -387,8 +387,11 @@ numerical, and generated automatically otherwise.
|
|
387
387
|
'Flattened' - [reserved] used internally to mark Struct tags
|
388
388
|
which have been processed to generate flattened equivalents.
|
389
389
|
|
390
|
-
'
|
391
|
-
|
390
|
+
'NotFlat' - [XMP tags only] Flag indicates that this tag ID
|
391
|
+
does not represent a flattened tag. Used to avoid a conflict
|
392
|
+
if the tag ID would be the same as a generated ID for a
|
393
|
+
flattened tag. The result is that the flattened tag will not
|
394
|
+
be accessible.
|
392
395
|
|
393
396
|
'Hidden' - set to hide tag from the TagName documentation.
|
394
397
|
Also suppresses verbose output of a BinaryData tag.
|
@@ -15,7 +15,7 @@ use strict;
|
|
15
15
|
use vars qw($VERSION);
|
16
16
|
use Image::ExifTool qw(:DataAccess :Utils);
|
17
17
|
|
18
|
-
$VERSION = '1.
|
18
|
+
$VERSION = '1.02';
|
19
19
|
|
20
20
|
# Radiance tags
|
21
21
|
%Image::ExifTool::Radiance::Main = (
|
@@ -42,6 +42,7 @@ $VERSION = '1.01';
|
|
42
42
|
},
|
43
43
|
},
|
44
44
|
_command => 'Command',
|
45
|
+
_comment => 'Comment',
|
45
46
|
software => 'Software',
|
46
47
|
view => 'View',
|
47
48
|
'format' => 'Format', # <-- this is the one that caused the conflict when uppercase
|
@@ -74,8 +75,12 @@ sub ProcessHDR($$)
|
|
74
75
|
while ($raf->ReadLine($buff)) {
|
75
76
|
chomp $buff;
|
76
77
|
last unless length($buff) > 0 and length($buff) < 4096;
|
78
|
+
if ($buff =~ s/^#\s*//) {
|
79
|
+
$et->HandleTag($tagTablePtr, '_comment', $buff) if length $buff;
|
80
|
+
next;
|
81
|
+
}
|
77
82
|
unless ($buff =~ /^(.*)?\s*=\s*(.*)/) {
|
78
|
-
$et->HandleTag($tagTablePtr, '_command', $buff);
|
83
|
+
$et->HandleTag($tagTablePtr, '_command', $buff) if length $buff;
|
79
84
|
next;
|
80
85
|
}
|
81
86
|
# use lower-case tag names to avoid conflicts with reserved tag table entries
|