exiftool_vendored 12.06.0 → 12.12.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 +96 -2
- data/bin/MANIFEST +5 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +43 -42
- data/bin/exiftool +156 -82
- data/bin/lib/Image/ExifTool.pm +22 -13
- data/bin/lib/Image/ExifTool.pod +59 -50
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +11 -5
- data/bin/lib/Image/ExifTool/Canon.pm +202 -13
- data/bin/lib/Image/ExifTool/DarwinCore.pm +9 -3
- data/bin/lib/Image/ExifTool/EXE.pm +8 -5
- data/bin/lib/Image/ExifTool/GIF.pm +2 -2
- data/bin/lib/Image/ExifTool/Geotag.pm +30 -11
- data/bin/lib/Image/ExifTool/GoPro.pm +47 -30
- data/bin/lib/Image/ExifTool/IPTC.pm +1 -0
- 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 +153 -37
- data/bin/lib/Image/ExifTool/Matroska.pm +3 -1
- data/bin/lib/Image/ExifTool/Minolta.pm +5 -1
- data/bin/lib/Image/ExifTool/Nikon.pm +11 -3
- data/bin/lib/Image/ExifTool/Olympus.pm +8 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +12 -12
- 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 +51 -16
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +68 -45
- data/bin/lib/Image/ExifTool/README +5 -2
- data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
- data/bin/lib/Image/ExifTool/Radiance.pm +7 -2
- data/bin/lib/Image/ExifTool/Sony.pm +56 -35
- 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 +248 -49
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +7 -6
- data/bin/lib/Image/ExifTool/Writer.pl +5 -3
- data/bin/lib/Image/ExifTool/XMP.pm +63 -18
- data/bin/lib/Image/ExifTool/XMP2.pl +1 -0
- data/bin/perl-Image-ExifTool.spec +42 -41
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +7 -7
@@ -15,7 +15,7 @@ use strict;
|
|
15
15
|
use vars qw($VERSION);
|
16
16
|
use Image::ExifTool::XMP;
|
17
17
|
|
18
|
-
$VERSION = '1.
|
18
|
+
$VERSION = '1.05';
|
19
19
|
|
20
20
|
my %dateTimeInfo = (
|
21
21
|
# NOTE: Do NOT put "Groups" here because Groups hash must not be common!
|
@@ -44,14 +44,20 @@ my %event = (
|
|
44
44
|
Groups => { 2 => 'Time' },
|
45
45
|
Writable => 'string', # (so we can format this ourself)
|
46
46
|
Shift => 'Time',
|
47
|
-
# (
|
47
|
+
# (allow date/time or just time value)
|
48
48
|
ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)',
|
49
49
|
PrintConv => '$self->ConvertDateTime($val)',
|
50
50
|
ValueConvInv => 'Image::ExifTool::XMP::FormatXMPDate($val) or $val',
|
51
51
|
PrintConvInv => q{
|
52
52
|
my $v = $self->InverseDateTime($val,undef,1);
|
53
53
|
undef $Image::ExifTool::evalWarning;
|
54
|
-
return $v
|
54
|
+
return $v if $v;
|
55
|
+
# allow time-only values by adding dummy date (thanks Herb)
|
56
|
+
my $v = $self->InverseDateTime("2000:01:01 $val",undef,1);
|
57
|
+
undef $Image::ExifTool::evalWarning;
|
58
|
+
return $v if $v and $v =~ s/.* //; # strip off dummy date
|
59
|
+
$Image::ExifTool::evalWarning = 'Invalid date/time or time-only value (use HH:MM:SS[.ss][+/-HH:MM|Z])';
|
60
|
+
return undef;
|
55
61
|
},
|
56
62
|
},
|
57
63
|
fieldNotes => { },
|
@@ -21,7 +21,7 @@ use strict;
|
|
21
21
|
use vars qw($VERSION);
|
22
22
|
use Image::ExifTool qw(:DataAccess :Utils);
|
23
23
|
|
24
|
-
$VERSION = '1.
|
24
|
+
$VERSION = '1.17';
|
25
25
|
|
26
26
|
sub ProcessPEResources($$);
|
27
27
|
sub ProcessPEVersion($$);
|
@@ -1009,7 +1009,7 @@ sub ProcessPEDict($$)
|
|
1009
1009
|
my $raf = $$dirInfo{RAF};
|
1010
1010
|
my $dataPt = $$dirInfo{DataPt};
|
1011
1011
|
my $dirLen = length($$dataPt);
|
1012
|
-
my ($pos, @sections, %dirInfo);
|
1012
|
+
my ($pos, @sections, %dirInfo, $rsrcFound);
|
1013
1013
|
|
1014
1014
|
# loop through all sections
|
1015
1015
|
for ($pos=0; $pos+40<=$dirLen; $pos+=40) {
|
@@ -1019,14 +1019,16 @@ sub ProcessPEDict($$)
|
|
1019
1019
|
my $offset = Get32u($dataPt, $pos + 20);
|
1020
1020
|
# remember the section offsets for the VirtualAddress lookup later
|
1021
1021
|
push @sections, { Base => $offset, Size => $size, VirtualAddress => $va };
|
1022
|
-
# save details of the first resource section
|
1022
|
+
# save details of the first resource section (or .text if .rsrc not found, ref forum11465)
|
1023
|
+
next unless ($name eq ".rsrc\0\0\0" and not $rsrcFound and defined($rsrcFound = 1)) or
|
1024
|
+
($name eq ".text\0\0\0" and not %dirInfo);
|
1023
1025
|
%dirInfo = (
|
1024
1026
|
RAF => $raf,
|
1025
1027
|
Base => $offset,
|
1026
1028
|
DirStart => 0, # (relative to Base)
|
1027
1029
|
DirLen => $size,
|
1028
1030
|
Sections => \@sections,
|
1029
|
-
)
|
1031
|
+
);
|
1030
1032
|
}
|
1031
1033
|
# process the first resource section
|
1032
1034
|
ProcessPEResources($et, \%dirInfo) or return 0 if %dirInfo;
|
@@ -1144,7 +1146,8 @@ sub ProcessEXE($$)
|
|
1144
1146
|
my $fileSize = ($cp - ($cblp ? 1 : 0)) * 512 + $cblp;
|
1145
1147
|
#(patch to accommodate observed 64-bit files)
|
1146
1148
|
#return 0 if $fileSize < 0x40 or $fileSize < $lfarlc;
|
1147
|
-
return 0 if $fileSize < 0x40;
|
1149
|
+
#return 0 if $fileSize < 0x40; (changed to warning in ExifTool 12.08)
|
1150
|
+
$et->Warn('Invalid file size in DOS header') if $fileSize < 0x40;
|
1148
1151
|
# read the Windows NE, PE or LE (virtual device driver) header
|
1149
1152
|
#if ($lfarlc == 0x40 and $fileSize > $lfanew + 2 and ...
|
1150
1153
|
if ($raf->Seek($lfanew, 0) and $raf->Read($buff, 0x40) and $buff =~ /^(NE|PE|LE)/) {
|
@@ -20,7 +20,7 @@ use strict;
|
|
20
20
|
use vars qw($VERSION);
|
21
21
|
use Image::ExifTool qw(:DataAccess :Utils);
|
22
22
|
|
23
|
-
$VERSION = '1.
|
23
|
+
$VERSION = '1.18';
|
24
24
|
|
25
25
|
# road map of directory locations in GIF images
|
26
26
|
my %gifMap = (
|
@@ -116,7 +116,7 @@ my %gifMap = (
|
|
116
116
|
},
|
117
117
|
5 => 'BackgroundColor',
|
118
118
|
6 => {
|
119
|
-
Name => '
|
119
|
+
Name => 'PixelAspectRatio',
|
120
120
|
RawConv => '$val ? $val : undef',
|
121
121
|
ValueConv => '($val + 15) / 64',
|
122
122
|
},
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# 2016/07/13 - PH Added ability to geotag date/time only
|
14
14
|
# 2019/07/02 - PH Added ability to read IMU CSV files
|
15
15
|
# 2019/11/10 - PH Also write pitch to CameraElevationAngle
|
16
|
+
# 2020/12/01 - PH Added ability to read DJI CSV log files
|
16
17
|
#
|
17
18
|
# References: 1) http://www.topografix.com/GPX/1/1/
|
18
19
|
# 2) http://www.gpsinformation.org/dale/nmea.htm#GSA
|
@@ -27,7 +28,7 @@ use vars qw($VERSION);
|
|
27
28
|
use Image::ExifTool qw(:Public);
|
28
29
|
use Image::ExifTool::GPS;
|
29
30
|
|
30
|
-
$VERSION = '1.
|
31
|
+
$VERSION = '1.64';
|
31
32
|
|
32
33
|
sub JITTER() { return 2 } # maximum time jitter
|
33
34
|
|
@@ -133,7 +134,7 @@ sub LoadTrackLog($$;$)
|
|
133
134
|
my ($et, $val) = @_;
|
134
135
|
my ($raf, $from, $time, $isDate, $noDate, $noDateChanged, $lastDate, $dateFlarm);
|
135
136
|
my ($nmeaStart, $fixSecs, @fixTimes, $lastFix, %nmea, @csvHeadings);
|
136
|
-
my ($canCut, $cutPDOP, $cutHDOP, $cutSats, $e0, $e1, @tmp);
|
137
|
+
my ($canCut, $cutPDOP, $cutHDOP, $cutSats, $e0, $e1, @tmp, $trackFile, $trackTime);
|
137
138
|
|
138
139
|
unless (eval { require Time::Local }) {
|
139
140
|
return 'Geotag feature requires Time::Local installed';
|
@@ -159,6 +160,7 @@ sub LoadTrackLog($$;$)
|
|
159
160
|
} else {
|
160
161
|
# $val is track file name
|
161
162
|
if ($et->Open(\*EXIFTOOL_TRKFILE, $val)) {
|
163
|
+
$trackFile = $val;
|
162
164
|
$raf = new File::RandomAccess(\*EXIFTOOL_TRKFILE);
|
163
165
|
unless ($raf->Read($_, 256)) {
|
164
166
|
close EXIFTOOL_TRKFILE;
|
@@ -201,6 +203,8 @@ sub LoadTrackLog($$;$)
|
|
201
203
|
my $skipped = 0;
|
202
204
|
my $lastSecs = 0;
|
203
205
|
my $fix = { };
|
206
|
+
my $csvDelim = $et->Options('CSVDelim');
|
207
|
+
$csvDelim = ',' unless defined $csvDelim;
|
204
208
|
my (@saveFix, $timeSpan);
|
205
209
|
for (;;) {
|
206
210
|
$raf->ReadLine($_) or last;
|
@@ -217,7 +221,7 @@ sub LoadTrackLog($$;$)
|
|
217
221
|
# (don't set format yet because we want to read HFDTE first)
|
218
222
|
$nmeaStart = 'B' ;
|
219
223
|
next;
|
220
|
-
} elsif (/^HFDTE(\d{2})(\d{2})(\d{2})/) {
|
224
|
+
} elsif (/^HFDTE(?:DATE:)?(\d{2})(\d{2})(\d{2})/) {
|
221
225
|
my $year = $3 + ($3 >= 70 ? 1900 : 2000);
|
222
226
|
$dateFlarm = Time::Local::timegm(0,0,0,$1,$2-1,$year);
|
223
227
|
$nmeaStart = 'B' ;
|
@@ -230,19 +234,31 @@ sub LoadTrackLog($$;$)
|
|
230
234
|
$format = 'Winplus';
|
231
235
|
} elsif (/^\s*\d+\s+.*\sypr\s*$/ and (@tmp=split) == 12) {
|
232
236
|
$format = 'Bramor';
|
233
|
-
} elsif (/\b(GPS)?Date/i and /\b(GPS)?(Date)?Time/i and
|
237
|
+
} elsif (((/\b(GPS)?Date/i and /\b(GPS)?(Date)?Time/i) or /\bTime\(seconds\)/i) and /\Q$csvDelim/) {
|
234
238
|
chomp;
|
235
|
-
@csvHeadings = split
|
239
|
+
@csvHeadings = split /\Q$csvDelim/;
|
236
240
|
$format = 'CSV';
|
237
241
|
# convert recognized headings to our parameter names
|
238
242
|
foreach (@csvHeadings) {
|
239
243
|
my $param;
|
240
244
|
s/^GPS ?//; # remove leading "GPS" to simplify regex patterns
|
241
|
-
if (/^
|
245
|
+
if (/^Time ?\(seconds\)$/i) { # DJI
|
246
|
+
# DJI CSV log files have a column "Time(seconds)" which is seconds since
|
247
|
+
# the start of the flight. The date/time is obtained from the file name.
|
248
|
+
$param = 'runtime';
|
249
|
+
if ($trackFile and $trackFile =~ /(\d{4})-(\d{2})-(\d{2})[^\/]+(\d{2})-(\d{2})-(\d{2})[^\/]*$/) {
|
250
|
+
$trackTime = Image::ExifTool::TimeLocal($6,$5,$4,$3,$2-1,$1);
|
251
|
+
my $utc = PrintFixTime($trackTime);
|
252
|
+
my $tzs = Image::ExifTool::TimeZoneString([$6,$5,$4,$3,$2-1,$1-1900],$trackTime);
|
253
|
+
$et->VPrint(2, " DJI start time: $utc (local timezone is $tzs)\n");
|
254
|
+
} else {
|
255
|
+
return 'Error getting start time from file name for DJI CSV track file';
|
256
|
+
}
|
257
|
+
} elsif (/^Date ?Time/i) { # ExifTool addition
|
242
258
|
$param = 'datetime';
|
243
259
|
} elsif (/^Date/i) {
|
244
260
|
$param = 'date';
|
245
|
-
} elsif (/^Time/i) {
|
261
|
+
} elsif (/^Time(?! ?\(text\))/i) { # (ignore DJI "Time(text)" column)
|
246
262
|
$param = 'time';
|
247
263
|
} elsif (/^(Pos)?Lat/i) {
|
248
264
|
$param = 'lat';
|
@@ -423,7 +439,7 @@ DoneFix: $isDate = 1;
|
|
423
439
|
goto DoneFix; # save this fix
|
424
440
|
} elsif ($format eq 'CSV') {
|
425
441
|
chomp;
|
426
|
-
my @vals = split
|
442
|
+
my @vals = split /\Q$csvDelim/;
|
427
443
|
#
|
428
444
|
# CSV format output of GPS/IMU POS system
|
429
445
|
# Date* - date in DD/MM/YYYY format
|
@@ -435,7 +451,7 @@ DoneFix: $isDate = 1;
|
|
435
451
|
# [Angle]Pitch* - pitch angle in degrees
|
436
452
|
# [Angle]Roll* - roll angle in degrees
|
437
453
|
# (ExifTool enhancements allow for standard tag names or descriptions as the column headings,
|
438
|
-
# add support for time zones and flexible coordinates, and allow
|
454
|
+
# add support for time zones and flexible coordinates, and allow new DateTime and Shift columns)
|
439
455
|
#
|
440
456
|
my ($param, $date, $secs);
|
441
457
|
foreach $param (@csvHeadings) {
|
@@ -463,6 +479,9 @@ DoneFix: $isDate = 1;
|
|
463
479
|
}
|
464
480
|
} elsif ($param eq 'lat' or $param eq 'lon') {
|
465
481
|
$$fix{$param} = Image::ExifTool::GPS::ToDegrees($val, 1);
|
482
|
+
} elsif ($param eq 'runtime') {
|
483
|
+
$date = $trackTime;
|
484
|
+
$secs = $val;
|
466
485
|
} else {
|
467
486
|
$$fix{$param} = $val;
|
468
487
|
}
|
@@ -1378,8 +1397,8 @@ This module is used by Image::ExifTool
|
|
1378
1397
|
This module loads GPS track logs, interpolates to determine position based
|
1379
1398
|
on time, and sets new GPS values for geotagging images. Currently supported
|
1380
1399
|
formats are GPX, NMEA RMC/GGA/GLL, KML, IGC, Garmin XML and TCX, Magellan
|
1381
|
-
PMGNTRK, Honeywell PTNTHPR, Winplus Beacon text, IMU CSV,
|
1382
|
-
files.
|
1400
|
+
PMGNTRK, Honeywell PTNTHPR, Winplus Beacon text, IMU CSV, DJI CSV, and
|
1401
|
+
Bramor gEO log files.
|
1383
1402
|
|
1384
1403
|
Methods in this module should not be called directly. Instead, the Geotag
|
1385
1404
|
feature is accessed by writing the values of the ExifTool Geotag, Geosync
|
@@ -16,7 +16,7 @@ use vars qw($VERSION);
|
|
16
16
|
use Image::ExifTool qw(:DataAccess :Utils);
|
17
17
|
use Image::ExifTool::QuickTime;
|
18
18
|
|
19
|
-
$VERSION = '1.
|
19
|
+
$VERSION = '1.06';
|
20
20
|
|
21
21
|
sub ProcessGoPro($$$);
|
22
22
|
sub ProcessString($$$);
|
@@ -77,6 +77,9 @@ my %addUnits = (
|
|
77
77
|
Notes => 'accelerator readings in m/s2',
|
78
78
|
Binary => 1,
|
79
79
|
},
|
80
|
+
# ANGX (GPMF-GEOC) - seen -0.05 (fmt d, Max)
|
81
|
+
# ANGY (GPMF-GEOC) - seen 179.9 (fmt d, Max)
|
82
|
+
# ANGZ (GPMF-GEOC) - seen 0.152 (fmt d, Max)
|
80
83
|
ALLD => 'AutoLowLightDuration', #1 (gpmd) (untested)
|
81
84
|
# APTO (GPMF) - seen: 'RAW', 'DYNM' (fmt c)
|
82
85
|
ATTD => { #PH (Karma)
|
@@ -105,16 +108,14 @@ my %addUnits = (
|
|
105
108
|
},
|
106
109
|
# BRID (GPMF) - seen: 0 (fmt B)
|
107
110
|
# BROD (GPMF) - seen: 'ASK','' (fmt c)
|
111
|
+
# CALH (GPMF-GEOC) - seen 3040 (fmt L, Max)
|
112
|
+
# CALW (GPMF-GEOC) - seen 4056 (fmt L, Max)
|
108
113
|
CASN => 'CameraSerialNumber', #PH (GPMF - seen: 'C3221324545448', fmt c)
|
109
|
-
# CINF (GPMF) - seen: 0x67376be7709bc8876a8baf3940908618, 0xe230988539b30cf5f016627ae8fc5395
|
110
|
-
#
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
# TYPE=LLLLLfffBB
|
115
|
-
# SCAL=1000 1 1 1 1 1 1 1 1 1
|
116
|
-
Binary => 1,
|
117
|
-
},
|
114
|
+
# CINF (GPMF) - seen: 0x67376be7709bc8876a8baf3940908618, 0xe230988539b30cf5f016627ae8fc5395,
|
115
|
+
# 0x8bcbe424acc5b37d7d77001635198b3b (fmt B) (Camera INFormation?)
|
116
|
+
# CMOD (GPMF) - seen: 12,13,17 [12 360 video, 13 time-laps video, 17 JPEG] (fmt B)
|
117
|
+
# CRTX (GPMF-BACK/FRNT) - double[1]
|
118
|
+
# CRTY (GPMF-BACK/FRNT) - double[1]
|
118
119
|
CSEN => { #PH (Karma)
|
119
120
|
Name => 'CoyoteSense',
|
120
121
|
# UNIT=s,rad/s,rad/s,rad/s,g,g,g,,,,
|
@@ -122,13 +123,27 @@ my %addUnits = (
|
|
122
123
|
# SCAL=1000 1 1 1 1 1 1 1 1 1 1
|
123
124
|
Binary => 1,
|
124
125
|
},
|
126
|
+
CYTS => { #PH (Karma)
|
127
|
+
Name => 'CoyoteStatus',
|
128
|
+
# UNIT=s,,,,,rad,rad,rad,,
|
129
|
+
# TYPE=LLLLLfffBB
|
130
|
+
# SCAL=1000 1 1 1 1 1 1 1 1 1
|
131
|
+
Binary => 1,
|
132
|
+
},
|
125
133
|
DEVC => { #PH (gpmd,GPMF, fmt \0)
|
126
134
|
Name => 'DeviceContainer',
|
127
135
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
|
128
|
-
|
129
|
-
|
136
|
+
# (Max) DVID=1,DVNM='Global Settings',VERS,FMWR,LINF,CINF,CASN,MINF,MUID,CMOD,MTYP,OREN,
|
137
|
+
# DZOM,DZST,SMTR,PRTN,PTWB,PTSH,PTCL,EXPT,PIMX,PIMN,PTEV,RATE,SROT,ZFOV,VLTE,VLTA,
|
138
|
+
# EISE,EISA,AUPT,AUDO,BROD,BRID,PVUL,PRJT,SOFF
|
139
|
+
# (Max) DVID='GEOC',DVNM='Geometry Calibrations',SHFX,SHFY,SHFZ,ANGX,ANGY,ANGZ,CALW,CALH
|
140
|
+
# (Max) DVID='BACK',DVNM='Back Lens',KLNS,CTRX,CTRY,MFOV,SFTR
|
141
|
+
# (Max) DVID='FRNT',DVNM='Front Lens',KLNS,CTRX,CTRY,MFOV,SFTR
|
142
|
+
# (Max) DVID='HLMT',DVNM='Highlights'
|
143
|
+
},
|
144
|
+
# DVID (GPMF) - DeviceID; seen: 1 (fmt L), HLMT (fmt F), GEOC (fmt F), 'BACK' (fmt F, Max)
|
130
145
|
DVID => { Name => 'DeviceID', Unknown => 1 }, #2 (gpmd)
|
131
|
-
# DVNM (GPMF) seen: 'Video Global Settings' (fmt c), 'Highlights' (fmt c)
|
146
|
+
# DVNM (GPMF) seen: 'Video Global Settings' (fmt c), 'Highlights' (fmt c), 'Geometry Calibrations' (Max)
|
132
147
|
# DVNM (gpmd) seen: 'Camera' (Hero5), 'Hero6 Black' (Hero6), 'GoPro Karma v1.0' (Karma)
|
133
148
|
DVNM => 'DeviceName', #PH (n/c)
|
134
149
|
DZOM => { #PH (GPMF - seen: 'Y', fmt c)
|
@@ -136,10 +151,10 @@ my %addUnits = (
|
|
136
151
|
PrintConv => { N => 'No', Y => 'Yes' },
|
137
152
|
},
|
138
153
|
# DZST (GPMF) - seen: 0 (fmt L) (something to do with digital zoom maybe?)
|
139
|
-
EISA => { #PH (GPMF) - seen: 'Y','N',
|
154
|
+
EISA => { #PH (GPMF) - seen: 'Y','N','HS EIS','N/A' (fmt c) [N was for a time-lapse video]
|
140
155
|
Name => 'ElectronicImageStabilization',
|
141
156
|
},
|
142
|
-
# EISE (GPMF) - seen: 'Y' (fmt c)
|
157
|
+
# EISE (GPMF) - seen: 'Y','N' (fmt c)
|
143
158
|
EMPT => { Name => 'Empty', Unknown => 1 }, #2 (gpmd)
|
144
159
|
ESCS => { #PH (Karma)
|
145
160
|
Name => 'EscapeStatus',
|
@@ -215,7 +230,8 @@ my %addUnits = (
|
|
215
230
|
RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data
|
216
231
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::KBAT' },
|
217
232
|
},
|
218
|
-
#
|
233
|
+
# KLNS (GPMF-BACK/FRNT) - double[5] (fmt d, Max)
|
234
|
+
# LINF (GPMF) - seen: LAJ7061916601668,C3341326002180,C33632245450981 (fmt c) (Lens INFormation?)
|
219
235
|
LNED => { #PH (Karma)
|
220
236
|
Name => 'LocalPositionNED',
|
221
237
|
# UNIT=s,m,m,m,m/s,m/s,m/s
|
@@ -224,12 +240,13 @@ my %addUnits = (
|
|
224
240
|
Binary => 1,
|
225
241
|
},
|
226
242
|
MAGN => 'Magnetometer', #1 (gpmd) (units of uT)
|
243
|
+
# MFOV (GPMF-BACK/FRNT) - seen: 100 (fmt d, Max)
|
227
244
|
MINF => { #PH (GPMF - seen: HERO6 Black, fmt c)
|
228
245
|
Name => 'Model',
|
229
246
|
Groups => { 2 => 'Camera' },
|
230
247
|
Description => 'Camera Model Name',
|
231
248
|
},
|
232
|
-
# MTYP (GPMF) - seen: 0,1,11 [1 for time-lapse video, 11 for JPEG] (fmt B)
|
249
|
+
# MTYP (GPMF) - seen: 0,1,5,11 [1 for time-lapse video, 5 for 360 video, 11 for JPEG] (fmt B)
|
233
250
|
# MUID (GPMF) - seen: 3882563431 2278071152 967805802 411471936 0 0 0 0 (fmt L)
|
234
251
|
OREN => { #PH (GPMF - seen: 'U', fmt c)
|
235
252
|
Name => 'AutoRotation',
|
@@ -245,7 +262,7 @@ my %addUnits = (
|
|
245
262
|
PIMX => 'AutoISOMax', #PH (GPMF - seen: 1600, fmt L)
|
246
263
|
# PRAW (APP6) - seen: 0, 'N', 'Y' (fmt c)
|
247
264
|
PRES => 'PhotoResolution', #PH (APP6 - seen: '12MP_W')
|
248
|
-
# PRJT (APP6) - seen: 'GPRO' (fmt F, Hero8)
|
265
|
+
# PRJT (APP6) - seen: 'GPRO','EACO' (fmt F, Hero8, Max)
|
249
266
|
PRTN => { #PH (GPMF - seen: 'N', fmt c)
|
250
267
|
Name => 'ProTune',
|
251
268
|
PrintConv => {
|
@@ -257,7 +274,7 @@ my %addUnits = (
|
|
257
274
|
PTEV => 'ExposureCompensation', #PH (GPMF - seen: '0.0', fmt c)
|
258
275
|
PTSH => 'Sharpness', #PH (GPMF - seen: 'HIGH', fmt c)
|
259
276
|
PTWB => 'WhiteBalance', #PH (GPMF - seen: 'AUTO', fmt c)
|
260
|
-
# PVUL (APP6) - seen: 'F' (fmt c, Hero8)
|
277
|
+
# PVUL (APP6) - seen: 'F' (fmt c, Hero8, Max)
|
261
278
|
RATE => 'Rate', #PH (GPMF - seen: '0_5SEC', fmt c; APP6 - seen: '4_1SEC')
|
262
279
|
RMRK => { #2 (gpmd)
|
263
280
|
Name => 'Comments',
|
@@ -274,6 +291,10 @@ my %addUnits = (
|
|
274
291
|
# SCAL=1000 0.00999999977648258 0.00999999977648258 100
|
275
292
|
%addUnits,
|
276
293
|
},
|
294
|
+
# SFTR (GPMF-BACK/FRNT) - seen 0.999,1.00004 (fmt d, Max)
|
295
|
+
# SHFX (GPMF-GEOC) - seen 22.92 (fmt d, Max)
|
296
|
+
# SHFY (GPMF-GEOC) - seen 0.123 (fmt d, Max)
|
297
|
+
# SHFZ (GPMF-GEOC) - seen 36.06 (fmt d, Max)
|
277
298
|
SHUT => { #2 (gpmd)
|
278
299
|
Name => 'ExposureTimes',
|
279
300
|
PrintConv => q{
|
@@ -295,7 +316,8 @@ my %addUnits = (
|
|
295
316
|
ValueConv => '$self->Decode($val, "Latin")',
|
296
317
|
},
|
297
318
|
# SMTR (GPMF) - seen: 'N' (fmt c)
|
298
|
-
# SOFF (APP6) - seen: 0 (fmt L, Hero8)
|
319
|
+
# SOFF (APP6) - seen: 0 (fmt L, Hero8, Max)
|
320
|
+
# SROT (GPMF) - seen 20.60 (fmt f, Max)
|
299
321
|
STMP => { #1 (gpmd)
|
300
322
|
Name => 'TimeStamp',
|
301
323
|
ValueConv => '$val / 1e6',
|
@@ -338,7 +360,10 @@ my %addUnits = (
|
|
338
360
|
Unknown => 1,
|
339
361
|
ValueConv => '$self->Decode($val, "Latin")',
|
340
362
|
},
|
341
|
-
|
363
|
+
VERS => {
|
364
|
+
Name => 'MetadataVersion',
|
365
|
+
PrintConv => '$val =~ tr/ /./; $val',
|
366
|
+
},
|
342
367
|
VFOV => { #PH (GPMF - seen: 'W', fmt c)
|
343
368
|
Name => 'FieldOfView',
|
344
369
|
PrintConv => {
|
@@ -360,7 +385,7 @@ my %addUnits = (
|
|
360
385
|
Name => 'WhiteBalanceRGB',
|
361
386
|
Binary => 1,
|
362
387
|
},
|
363
|
-
# ZFOV (APP6) - seen: 148.34 (fmt f, Hero8)
|
388
|
+
# ZFOV (APP6,GPMF) - seen: 148.34, 0 (fmt f, Hero8, Max)
|
364
389
|
);
|
365
390
|
|
366
391
|
# GoPro GPS5 tags (ref 2) (Hero5,Hero6)
|
@@ -602,14 +627,6 @@ sub ProcessGoPro($$$)
|
|
602
627
|
my $unknown = $verbose || $et->Options('Unknown');
|
603
628
|
my ($size, $type, $unit, $scal, $setGroup0);
|
604
629
|
|
605
|
-
# the Rove Stealth 4K writes encrypted text here, so check for this first
|
606
|
-
# (really should check for this before loading GoPro module, but I was lazy) PHIL
|
607
|
-
if ($$dataPt =~ /^\0\0\xf2\xe1\xf0\xeeTT/) {
|
608
|
-
$et->VerboseDir('gpmd encrypted text', undef, length($$dataPt));
|
609
|
-
my $strmTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
610
|
-
Image::ExifTool::QuickTime::Process_text($et, $strmTbl, $dataPt);
|
611
|
-
return 1;
|
612
|
-
}
|
613
630
|
$et->VerboseDir($$dirInfo{DirName} || 'GPMF', undef, $dirEnd-$pos) if $verbose;
|
614
631
|
if ($pos) {
|
615
632
|
my $parent = $$dirInfo{Parent};
|
@@ -12,25 +12,26 @@ require Exporter;
|
|
12
12
|
|
13
13
|
use vars qw($VERSION @ISA @EXPORT_OK);
|
14
14
|
|
15
|
-
$VERSION = '1.
|
15
|
+
$VERSION = '1.10';
|
16
16
|
@ISA = qw(Exporter);
|
17
17
|
@EXPORT_OK = qw(ReadCSV ReadJSON);
|
18
18
|
|
19
19
|
sub ReadJSONObject($;$);
|
20
20
|
|
21
|
-
my %unescapeJSON = ( 't'=>"\t", 'n'=>"\n", 'r'=>"\r" );
|
21
|
+
my %unescapeJSON = ( 't'=>"\t", 'n'=>"\n", 'r'=>"\r", 'b' => "\b", 'f' => "\f" );
|
22
22
|
my $charset;
|
23
23
|
|
24
24
|
#------------------------------------------------------------------------------
|
25
25
|
# Read CSV file
|
26
|
-
# Inputs: 0) CSV file name, file ref or RAF ref, 1) database hash ref,
|
26
|
+
# Inputs: 0) CSV file name, file ref or RAF ref, 1) database hash ref,
|
27
|
+
# 2) missing tag value, 3) delimiter if other than ','
|
27
28
|
# Returns: undef on success, or error string
|
28
29
|
# Notes: There are various flavours of CSV, but here we assume that only
|
29
30
|
# double quotes are escaped, and they are escaped by doubling them
|
30
|
-
sub ReadCSV(
|
31
|
+
sub ReadCSV($$;$$)
|
31
32
|
{
|
32
33
|
local ($_, $/);
|
33
|
-
my ($file, $database, $missingValue) = @_;
|
34
|
+
my ($file, $database, $missingValue, $delim) = @_;
|
34
35
|
my ($buff, @tags, $found, $err, $raf, $openedFile);
|
35
36
|
|
36
37
|
if (UNIVERSAL::isa($file, 'File::RandomAccess')) {
|
@@ -45,6 +46,7 @@ sub ReadCSV($$;$)
|
|
45
46
|
$openedFile = 1;
|
46
47
|
$raf = new File::RandomAccess(\*CSVFILE);
|
47
48
|
}
|
49
|
+
$delim = ',' unless defined $delim;
|
48
50
|
# set input record separator by first newline found in the file
|
49
51
|
# (safe because first line should contain only tag names)
|
50
52
|
while ($raf->Read($buff, 65536)) {
|
@@ -53,18 +55,18 @@ sub ReadCSV($$;$)
|
|
53
55
|
$raf->Seek(0,0);
|
54
56
|
while ($raf->ReadLine($buff)) {
|
55
57
|
my (@vals, $v, $i, %fileInfo);
|
56
|
-
my @toks = split
|
58
|
+
my @toks = split /\Q$delim/, $buff;
|
57
59
|
while (@toks) {
|
58
60
|
($v = shift @toks) =~ s/^ +//; # remove leading spaces
|
59
61
|
if ($v =~ s/^"//) {
|
60
62
|
# quoted value must end in an odd number of quotes
|
61
63
|
while ($v !~ /("+)\s*$/ or not length($1) & 1) {
|
62
64
|
if (@toks) {
|
63
|
-
$v .=
|
65
|
+
$v .= $delim . shift @toks;
|
64
66
|
} else {
|
65
67
|
# read another line from the file
|
66
68
|
$raf->ReadLine($buff) or last;
|
67
|
-
@toks = split
|
69
|
+
@toks = split /\Q$delim/, $buff;
|
68
70
|
last unless @toks;
|
69
71
|
$v .= shift @toks;
|
70
72
|
}
|
@@ -330,9 +332,10 @@ Read CSV or JSON file into a database hash.
|
|
330
332
|
2) Optional string used to represent an undefined (missing) tag value.
|
331
333
|
(Used for deleting tags.)
|
332
334
|
|
333
|
-
3)
|
334
|
-
|
335
|
-
|
335
|
+
3) For ReadCSV this gives the delimiter for CSV entries, with a default of
|
336
|
+
",". For ReadJSON this is the character set for converting Unicode escape
|
337
|
+
sequences in strings, with a default of "UTF8". See the ExifTool Charset
|
338
|
+
option for a list of valid character sets.
|
336
339
|
|
337
340
|
=item Return Value:
|
338
341
|
|