exiftool_vendored 12.06.0 → 12.12.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.
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
|
|