exiftool-vendored.exe 12.39.0 → 12.42.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 +66 -1
- package/bin/exiftool_files/README +2 -2
- package/bin/exiftool_files/arg_files/exif2xmp.args +5 -0
- package/bin/exiftool_files/arg_files/xmp2exif.args +6 -0
- package/bin/exiftool_files/config_files/acdsee.config +6 -6
- package/bin/exiftool_files/config_files/photoshop_paths.config +30 -7
- package/bin/exiftool_files/config_files/picasa_faces.config +1 -1
- package/bin/exiftool_files/config_files/pix4d.config +2 -2
- package/bin/exiftool_files/config_files/tiff_version.config +2 -2
- package/bin/exiftool_files/exiftool.pl +53 -20
- package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +89 -6
- package/bin/exiftool_files/lib/Image/ExifTool/DJI.pm +59 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DNG.pm +8 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +53 -20
- package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +3 -2
- package/bin/exiftool_files/lib/Image/ExifTool/ICC_Profile.pm +10 -8
- package/bin/exiftool_files/lib/Image/ExifTool/ID3.pm +5 -5
- package/bin/exiftool_files/lib/Image/ExifTool/MacOS.pm +9 -9
- package/bin/exiftool_files/lib/Image/ExifTool/MakerNotes.pm +17 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +44 -12
- package/bin/exiftool_files/lib/Image/ExifTool/NikonCustom.pm +4 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +27 -7
- package/bin/exiftool_files/lib/Image/ExifTool/PDF.pm +2 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +10 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Photoshop.pm +6 -5
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +9 -5
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Samsung.pm +237 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Shortcuts.pm +3 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +10 -4
- package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +6376 -6354
- package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +79 -28
- package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +7 -3
- package/bin/exiftool_files/lib/Image/ExifTool/WriteXMP.pl +2 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +9 -1
- package/bin/exiftool_files/lib/Image/ExifTool/XMPStruct.pl +21 -7
- package/bin/exiftool_files/lib/Image/ExifTool.pm +20 -12
- package/bin/exiftool_files/lib/Image/ExifTool.pod +7 -6
- package/package.json +14 -3
|
@@ -11,11 +11,14 @@ package Image::ExifTool::DJI;
|
|
|
11
11
|
|
|
12
12
|
use strict;
|
|
13
13
|
use vars qw($VERSION);
|
|
14
|
+
use Image::ExifTool qw(:DataAccess :Utils);
|
|
14
15
|
use Image::ExifTool::Exif;
|
|
15
16
|
use Image::ExifTool::XMP;
|
|
16
17
|
use Image::ExifTool::GPS;
|
|
17
18
|
|
|
18
|
-
$VERSION = '1.
|
|
19
|
+
$VERSION = '1.05';
|
|
20
|
+
|
|
21
|
+
sub ProcessDJIInfo($$$);
|
|
19
22
|
|
|
20
23
|
my %convFloat2 = (
|
|
21
24
|
PrintConv => 'sprintf("%+.2f", $val)',
|
|
@@ -44,6 +47,29 @@ my %convFloat2 = (
|
|
|
44
47
|
0x0b => { Name => 'CameraRoll', Writable => 'float', %convFloat2 },
|
|
45
48
|
);
|
|
46
49
|
|
|
50
|
+
# DJI debug maker notes
|
|
51
|
+
%Image::ExifTool::DJI::Info = (
|
|
52
|
+
PROCESS_PROC => \&ProcessDJIInfo,
|
|
53
|
+
GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
|
54
|
+
NOTES => 'Tags written by some DJI drones.',
|
|
55
|
+
VARS => { LONG_TAGS => 2 },
|
|
56
|
+
ae_dbg_info => { Name => 'AEDebugInfo' },
|
|
57
|
+
ae_histogram_info => { Name => 'AEHistogramInfo' },
|
|
58
|
+
ae_local_histogram => { Name => 'AELocalHistogram' },
|
|
59
|
+
ae_liveview_histogram_info => { Name => 'AELiveViewHistogramInfo' },
|
|
60
|
+
ae_liveview_local_histogram => { Name => 'AELiveViewLocalHistogram' },
|
|
61
|
+
awb_dbg_info => { Name => 'AWBDebugInfo' },
|
|
62
|
+
af_dbg_info => { Name => 'AFDebugInfo' },
|
|
63
|
+
hiso => { Name => 'Histogram' },
|
|
64
|
+
xidiri => { Name => 'Xidiri' },
|
|
65
|
+
'GimbalDegree(Y,P,R)'=> { Name => 'GimbalDegree' },
|
|
66
|
+
'FlightDegree(Y,P,R)'=> { Name => 'FlightDegree' },
|
|
67
|
+
adj_dbg_info => { Name => 'ADJDebugInfo' },
|
|
68
|
+
sensor_id => { Name => 'SensorID' },
|
|
69
|
+
'FlightSpeed(X,Y,Z)' => { Name => 'FlightSpeed' },
|
|
70
|
+
hyperlapse_dbg_info => { Name => 'HyperlapsDebugInfo' },
|
|
71
|
+
);
|
|
72
|
+
|
|
47
73
|
# thermal parameters in APP4 of DJI ZH20T images (ref forum11401)
|
|
48
74
|
%Image::ExifTool::DJI::ThermalParams = (
|
|
49
75
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
|
@@ -134,6 +160,38 @@ my %convFloat2 = (
|
|
|
134
160
|
},
|
|
135
161
|
);
|
|
136
162
|
|
|
163
|
+
#------------------------------------------------------------------------------
|
|
164
|
+
# Process DJI infor (ref PH)
|
|
165
|
+
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
|
166
|
+
# Returns: 1 on success
|
|
167
|
+
sub ProcessDJIInfo($$$)
|
|
168
|
+
{
|
|
169
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
|
170
|
+
my $dataPt = $$dirInfo{DataPt};
|
|
171
|
+
my $dirStart = $$dirInfo{DirStart} || 0;
|
|
172
|
+
my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart);
|
|
173
|
+
if ($dirStart) {
|
|
174
|
+
my $buff = substr($$dataPt, $dirStart, $dirLen);
|
|
175
|
+
$dataPt = \$buff;
|
|
176
|
+
}
|
|
177
|
+
while ($$dataPt =~ /\G\[(.*?)\](?=(\[|$))/sg) {
|
|
178
|
+
my ($tag, $val) = split /:/, $1, 2;
|
|
179
|
+
if ($val =~ /^([\x20-\x7f]+)\0*$/) {
|
|
180
|
+
$val = $1;
|
|
181
|
+
} else {
|
|
182
|
+
my $buff = $val;
|
|
183
|
+
$val = \$buff;
|
|
184
|
+
}
|
|
185
|
+
if (not $$tagTbl{$tag} and $tag=~ /^[-_a-zA-Z0-9]+$/) {
|
|
186
|
+
my $name = $tag;
|
|
187
|
+
$name =~ s/_([a-z])/_\U$1/g;
|
|
188
|
+
AddTagToTable($tagTbl, $tag, { Name => Image::ExifTool::MakeTagName($name) });
|
|
189
|
+
}
|
|
190
|
+
$et->HandleTag($tagTbl, $tag, $val);
|
|
191
|
+
}
|
|
192
|
+
return 1;
|
|
193
|
+
}
|
|
194
|
+
|
|
137
195
|
__END__
|
|
138
196
|
|
|
139
197
|
=head1 NAME
|
|
@@ -680,8 +680,14 @@ sub ProcessAdobeMakN($$$)
|
|
|
680
680
|
my $dataPos = $$dirInfo{DataPos};
|
|
681
681
|
my $hdrLen = 6;
|
|
682
682
|
|
|
683
|
-
# hack for extra 12 bytes in MakN header of JPEG converted to DNG
|
|
684
|
-
# (4 bytes "00 00 00 01" followed by 8 unknown bytes)
|
|
683
|
+
# 2018-09-27: hack for extra 12 bytes in MakN header of JPEG converted to DNG
|
|
684
|
+
# by Adobe Camera Raw (4 bytes "00 00 00 01" followed by 8 unknown bytes)
|
|
685
|
+
# - this is because CameraRaw copies the maker notes from the wrong location
|
|
686
|
+
# in a JPG image (off by 12 bytes presumably due to the JPEG headers)
|
|
687
|
+
# - this hack won't work in most cases because the extra bytes are not consistent
|
|
688
|
+
# since they are just the data that existed in the JPG before the maker notes
|
|
689
|
+
# - also, the last 12 bytes of the maker notes will be missing
|
|
690
|
+
# - 2022-04-26: this bug still exists in Camera Raw 14.3
|
|
685
691
|
$hdrLen += 12 if $len >= 18 and substr($$dataPt, $start+6, 4) eq "\0\0\0\x01";
|
|
686
692
|
|
|
687
693
|
my $dirStart = $start + $hdrLen; # pointer to maker note directory
|
|
@@ -56,7 +56,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
|
|
|
56
56
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
57
57
|
use Image::ExifTool::MakerNotes;
|
|
58
58
|
|
|
59
|
-
$VERSION = '4.
|
|
59
|
+
$VERSION = '4.40';
|
|
60
60
|
|
|
61
61
|
sub ProcessExif($$$);
|
|
62
62
|
sub WriteExif($$$);
|
|
@@ -415,7 +415,14 @@ my %opcodeInfo = (
|
|
|
415
415
|
WriteGroup => 'IFD0',
|
|
416
416
|
# set priority directory if this is the full resolution image
|
|
417
417
|
DataMember => 'SubfileType',
|
|
418
|
-
RawConv =>
|
|
418
|
+
RawConv => q{
|
|
419
|
+
if ($val == ($val & 0x02)) {
|
|
420
|
+
$self->SetPriorityDir() if $val == 0;
|
|
421
|
+
$$self{PageCount} = ($$self{PageCount} || 0) + 1;
|
|
422
|
+
$$self{MultiPage} = 1 if $val == 2 or $$self{PageCount} > 1;
|
|
423
|
+
}
|
|
424
|
+
$$self{SubfileType} = $val;
|
|
425
|
+
},
|
|
419
426
|
PrintConv => \%subfileType,
|
|
420
427
|
},
|
|
421
428
|
0xff => {
|
|
@@ -425,7 +432,14 @@ my %opcodeInfo = (
|
|
|
425
432
|
Writable => 'int16u',
|
|
426
433
|
WriteGroup => 'IFD0',
|
|
427
434
|
# set priority directory if this is the full resolution image
|
|
428
|
-
RawConv =>
|
|
435
|
+
RawConv => q{
|
|
436
|
+
if ($val == 1 or $val == 3) {
|
|
437
|
+
$self->SetPriorityDir() if $val == 1;
|
|
438
|
+
$$self{PageCount} = ($$self{PageCount} || 0) + 1;
|
|
439
|
+
$$self{MultiPage} = 1 if $val == 3 or $$self{PageCount} > 1;
|
|
440
|
+
}
|
|
441
|
+
$val;
|
|
442
|
+
},
|
|
429
443
|
PrintConv => {
|
|
430
444
|
1 => 'Full-resolution image',
|
|
431
445
|
2 => 'Reduced-resolution image',
|
|
@@ -2144,7 +2158,7 @@ my %opcodeInfo = (
|
|
|
2144
2158
|
Notes => 'displayed in seconds, but stored as an APEX value',
|
|
2145
2159
|
Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u)
|
|
2146
2160
|
Writable => 'rational64s',
|
|
2147
|
-
ValueConv => 'abs($val)<100 ? 2**(-$val) : 0',
|
|
2161
|
+
ValueConv => 'IsFloat($val) && abs($val)<100 ? 2**(-$val) : 0',
|
|
2148
2162
|
ValueConvInv => '$val>0 ? -log($val)/log(2) : -100',
|
|
2149
2163
|
PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
|
|
2150
2164
|
PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
|
|
@@ -3383,6 +3397,15 @@ my %opcodeInfo = (
|
|
|
3383
3397
|
},
|
|
3384
3398
|
# the DJI FC2103 writes some interesting stuff here (with sections labelled
|
|
3385
3399
|
# awb_dbg_info, ae_dbg_info, ae_histogram_info, af_dbg_info, hiso, xidiri) - PH
|
|
3400
|
+
{
|
|
3401
|
+
Name => 'MakerNoteDJIInfo',
|
|
3402
|
+
Condition => '$$valPt =~ /^\[ae_dbg_info:/',
|
|
3403
|
+
MakerNotes => 1,
|
|
3404
|
+
Binary => 1,
|
|
3405
|
+
WriteGroup => 'IFD0', # (for Validate)
|
|
3406
|
+
SubDirectory => { TagTable => 'Image::ExifTool::DJI::Info' },
|
|
3407
|
+
Format => 'undef',
|
|
3408
|
+
},
|
|
3386
3409
|
{
|
|
3387
3410
|
Name => 'DNGPrivateData',
|
|
3388
3411
|
Flags => [ 'Binary', 'Protected' ],
|
|
@@ -4827,6 +4850,7 @@ my %subSecConv = (
|
|
|
4827
4850
|
PrintConvInv => q{
|
|
4828
4851
|
return undef unless $val =~ /(.*? ?[NS]?), ?(.*? ?[EW]?)$/;
|
|
4829
4852
|
my ($lat, $lon) = ($1, $2);
|
|
4853
|
+
require Image::ExifTool::GPS;
|
|
4830
4854
|
$lat = Image::ExifTool::GPS::ToDegrees($lat, 1, "lat");
|
|
4831
4855
|
$lon = Image::ExifTool::GPS::ToDegrees($lon, 1, "lon");
|
|
4832
4856
|
return "$lat, $lon";
|
|
@@ -5248,6 +5272,7 @@ sub RedBlueBalance($@)
|
|
|
5248
5272
|
sub PrintExposureTime($)
|
|
5249
5273
|
{
|
|
5250
5274
|
my $secs = shift;
|
|
5275
|
+
return $secs unless Image::ExifTool::IsFloat($secs);
|
|
5251
5276
|
if ($secs < 0.25001 and $secs > 0) {
|
|
5252
5277
|
return sprintf("1/%d",int(0.5 + 1/$secs));
|
|
5253
5278
|
}
|
|
@@ -5853,7 +5878,7 @@ sub ProcessExif($$$)
|
|
|
5853
5878
|
unless ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) {
|
|
5854
5879
|
if ($Image::ExifTool::MWG::strict) {
|
|
5855
5880
|
$et->Warn("Ignored non-standard EXIF at $path");
|
|
5856
|
-
return
|
|
5881
|
+
return 0;
|
|
5857
5882
|
} else {
|
|
5858
5883
|
$et->Warn("Non-standard EXIF at $path", 1);
|
|
5859
5884
|
}
|
|
@@ -5896,10 +5921,6 @@ sub ProcessExif($$$)
|
|
|
5896
5921
|
# also read next IFD pointer if available
|
|
5897
5922
|
if ($raf->Read($buf2, $len+4) >= $len) {
|
|
5898
5923
|
$buff .= $buf2;
|
|
5899
|
-
# make copy of dirInfo since we're going to modify it
|
|
5900
|
-
my %newDirInfo = %$dirInfo;
|
|
5901
|
-
$dirInfo = \%newDirInfo;
|
|
5902
|
-
# update directory parameters for the newly loaded IFD
|
|
5903
5924
|
$dataPt = $$dirInfo{DataPt} = \$buff;
|
|
5904
5925
|
$dataPos = $$dirInfo{DataPos} = $offset;
|
|
5905
5926
|
$dataLen = $$dirInfo{DataLen} = length $buff;
|
|
@@ -6593,7 +6614,7 @@ sub ProcessExif($$$)
|
|
|
6593
6614
|
#### eval Validate ($val, $dirData, $subdirStart, $size)
|
|
6594
6615
|
my $ok = 0;
|
|
6595
6616
|
if (defined $$subdir{Validate} and not eval $$subdir{Validate}) {
|
|
6596
|
-
$et->Warn("Invalid $tagStr data");
|
|
6617
|
+
$et->Warn("Invalid $tagStr data", $inMakerNotes);
|
|
6597
6618
|
$invalid = 1;
|
|
6598
6619
|
} else {
|
|
6599
6620
|
if (not $subdirInfo{DirName} and $inMakerNotes) {
|
|
@@ -6706,28 +6727,40 @@ sub ProcessExif($$$)
|
|
|
6706
6727
|
|
|
6707
6728
|
# scan for subsequent IFD's if specified
|
|
6708
6729
|
if ($$dirInfo{Multi} and $bytesFromEnd >= 4) {
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6730
|
+
# use same directory information for trailing directory,
|
|
6731
|
+
# but change the start location (ProcessDirectory will
|
|
6732
|
+
# test to make sure we don't reprocess the same dir twice)
|
|
6733
|
+
my %newDirInfo = %$dirInfo;
|
|
6734
|
+
$newDirInfo{Multi} = 0; # prevent recursion
|
|
6735
|
+
$newDirInfo{OffsetName} = $nextOffName;
|
|
6736
|
+
$$et{INDENT} =~ s/..$//; # keep indent the same
|
|
6737
|
+
for (;;) {
|
|
6738
|
+
my $offset = Get32u($dataPt, $dirEnd) or last;
|
|
6739
|
+
$newDirInfo{DirStart} = $offset - $dataPos;
|
|
6717
6740
|
# increment IFD number
|
|
6718
6741
|
my $ifdNum = $newDirInfo{DirName} =~ s/(\d+)$// ? $1 : 0;
|
|
6719
6742
|
$newDirInfo{DirName} .= $ifdNum + 1;
|
|
6720
|
-
$newDirInfo{OffsetName} = $nextOffName;
|
|
6721
6743
|
# must validate SubIFD1 because the nextIFD pointer is invalid for some RAW formats
|
|
6722
6744
|
if ($newDirInfo{DirName} ne 'SubIFD1' or ValidateIFD(\%newDirInfo)) {
|
|
6723
|
-
$$et{INDENT} =~ s/..$//; # keep indent the same
|
|
6724
6745
|
my $cur = pop @{$$et{PATH}};
|
|
6725
6746
|
$et->ProcessDirectory(\%newDirInfo, $tagTablePtr) or $success = 0;
|
|
6726
6747
|
push @{$$et{PATH}}, $cur;
|
|
6748
|
+
if ($success and $newDirInfo{BytesFromEnd} >= 4) {
|
|
6749
|
+
$dataPt = $newDirInfo{DataPt};
|
|
6750
|
+
$dataPos = $newDirInfo{DataPos};
|
|
6751
|
+
$dirEnd = $newDirInfo{DirEnd};
|
|
6752
|
+
next;
|
|
6753
|
+
}
|
|
6727
6754
|
} elsif ($verbose or $$et{TIFF_TYPE} eq 'TIFF') {
|
|
6728
6755
|
$et->Warn('Ignored bad IFD linked from SubIFD');
|
|
6729
6756
|
}
|
|
6757
|
+
last;
|
|
6730
6758
|
}
|
|
6759
|
+
} elsif (defined $$dirInfo{Multi}) {
|
|
6760
|
+
# return necessary parameters for parsing next IFD
|
|
6761
|
+
$$dirInfo{DirEnd} = $dirEnd;
|
|
6762
|
+
$$dirInfo{OffsetName} = $nextOffName;
|
|
6763
|
+
$$dirInfo{BytesFromEnd} = $bytesFromEnd;
|
|
6731
6764
|
}
|
|
6732
6765
|
return $success;
|
|
6733
6766
|
}
|
|
@@ -28,7 +28,7 @@ use vars qw($VERSION);
|
|
|
28
28
|
use Image::ExifTool qw(:Public);
|
|
29
29
|
use Image::ExifTool::GPS;
|
|
30
30
|
|
|
31
|
-
$VERSION = '1.
|
|
31
|
+
$VERSION = '1.66';
|
|
32
32
|
|
|
33
33
|
sub JITTER() { return 2 } # maximum time jitter
|
|
34
34
|
|
|
@@ -210,13 +210,14 @@ sub LoadTrackLog($$;$)
|
|
|
210
210
|
$raf->ReadLine($_) or last;
|
|
211
211
|
# determine file format
|
|
212
212
|
if (not $format) {
|
|
213
|
+
s/^\xef\xbb\xbf//; # remove leading BOM if it exists
|
|
213
214
|
if (/^<(\?xml|gpx)[\s>]/) { # look for XML or GPX header
|
|
214
215
|
$format = 'XML';
|
|
215
216
|
# check for NMEA sentence
|
|
216
217
|
# (must ONLY start with ones that have timestamps! eg. not GSA or PTNTHPR!)
|
|
217
218
|
} elsif (/^.*\$([A-Z]{2}(RMC|GGA|GLL|ZDA)|PMGNTRK),/) {
|
|
218
219
|
$format = 'NMEA';
|
|
219
|
-
$nmeaStart = $2 || $1;
|
|
220
|
+
$nmeaStart = $2 || $1; # save type of first sentence
|
|
220
221
|
} elsif (/^A(FLA|XSY|FIL)/) {
|
|
221
222
|
# (don't set format yet because we want to read HFDTE first)
|
|
222
223
|
$nmeaStart = 'B' ;
|
|
@@ -25,7 +25,7 @@ use strict;
|
|
|
25
25
|
use vars qw($VERSION);
|
|
26
26
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
27
27
|
|
|
28
|
-
$VERSION = '1.
|
|
28
|
+
$VERSION = '1.39';
|
|
29
29
|
|
|
30
30
|
sub ProcessICC($$);
|
|
31
31
|
sub ProcessICC_Profile($$$);
|
|
@@ -522,11 +522,11 @@ my %manuSig = ( #6
|
|
|
522
522
|
prmg => 'Perceptual Reference Medium Gamut',
|
|
523
523
|
},
|
|
524
524
|
},
|
|
525
|
-
meta => { #5
|
|
525
|
+
meta => { #5
|
|
526
526
|
Name => 'Metadata',
|
|
527
527
|
SubDirectory => {
|
|
528
528
|
TagTable => 'Image::ExifTool::ICC_Profile::Metadata',
|
|
529
|
-
Validate => '$type eq "
|
|
529
|
+
Validate => '$type eq "dict"',
|
|
530
530
|
},
|
|
531
531
|
},
|
|
532
532
|
|
|
@@ -891,6 +891,7 @@ my %manuSig = ( #6
|
|
|
891
891
|
ManufacturerName => { },
|
|
892
892
|
MediaColor => { },
|
|
893
893
|
MediaWeight => { },
|
|
894
|
+
CreatorApp => { },
|
|
894
895
|
);
|
|
895
896
|
|
|
896
897
|
#------------------------------------------------------------------------------
|
|
@@ -1000,7 +1001,7 @@ sub FormatICCTag($$$)
|
|
|
1000
1001
|
}
|
|
1001
1002
|
|
|
1002
1003
|
#------------------------------------------------------------------------------
|
|
1003
|
-
# Process ICC metadata record (ref 5)
|
|
1004
|
+
# Process ICC metadata record (ref 5)
|
|
1004
1005
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
|
1005
1006
|
# Returns: 1 on success
|
|
1006
1007
|
sub ProcessMetadata($$$)
|
|
@@ -1032,7 +1033,7 @@ sub ProcessMetadata($$$)
|
|
|
1032
1033
|
my $namePtr = Get32u($dataPt, $entry);
|
|
1033
1034
|
my $nameLen = Get32u($dataPt, $entry + 4);
|
|
1034
1035
|
my $valuePtr = Get32u($dataPt, $entry + 8);
|
|
1035
|
-
my $valueLen = Get32u($dataPt, $entry +
|
|
1036
|
+
my $valueLen = Get32u($dataPt, $entry + 12);
|
|
1036
1037
|
next unless $namePtr and $valuePtr; # ignore if offsets are zero
|
|
1037
1038
|
if ($namePtr < $minPtr or $namePtr + $nameLen > $dirLen or
|
|
1038
1039
|
$valuePtr < $minPtr or $valuePtr + $valueLen > $dirLen)
|
|
@@ -1040,8 +1041,8 @@ sub ProcessMetadata($$$)
|
|
|
1040
1041
|
$et->Warn('Corrupted ICC meta dictionary');
|
|
1041
1042
|
last;
|
|
1042
1043
|
}
|
|
1043
|
-
my $tag = substr(
|
|
1044
|
-
my $val = substr(
|
|
1044
|
+
my $tag = substr($$dataPt, $dirStart + $namePtr, $nameLen);
|
|
1045
|
+
my $val = substr($$dataPt, $dirStart + $valuePtr, $valueLen);
|
|
1045
1046
|
$tag = $et->Decode($tag, 'UTF16', 'MM', 'UTF8');
|
|
1046
1047
|
$val = $et->Decode($val, 'UTF16', 'MM');
|
|
1047
1048
|
# generate tagInfo if it doesn't exist
|
|
@@ -1050,6 +1051,7 @@ sub ProcessMetadata($$$)
|
|
|
1050
1051
|
$name =~ s/\s+(.)/\u$1/g;
|
|
1051
1052
|
$name =~ tr/-_a-zA-Z0-9//dc;
|
|
1052
1053
|
next unless length $name;
|
|
1054
|
+
$et->VPrint(0, $$et{INDENT}, "[adding $tag]\n");
|
|
1053
1055
|
AddTagToTable($tagTablePtr, $tag, { Name => $name });
|
|
1054
1056
|
}
|
|
1055
1057
|
$et->HandleTag($tagTablePtr, $tag, $val);
|
|
@@ -1312,7 +1314,7 @@ sub ProcessICC_Profile($$$)
|
|
|
1312
1314
|
DirName => $name,
|
|
1313
1315
|
Parent => $$dirInfo{DirName},
|
|
1314
1316
|
);
|
|
1315
|
-
my $type =
|
|
1317
|
+
my $type = $fmt;
|
|
1316
1318
|
#### eval Validate ($type)
|
|
1317
1319
|
if (defined $$subdir{Validate} and not eval $$subdir{Validate}) {
|
|
1318
1320
|
$et->Warn("Invalid ICC $name data");
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Revisions: 09/12/2005 - P. Harvey Created
|
|
7
7
|
# 09/08/2020 - PH Added Lyrics3 support
|
|
8
8
|
#
|
|
9
|
-
# References: 1) http://www.id3.org/
|
|
9
|
+
# References: 1) http://www.id3.org/ (now https://id3.org)
|
|
10
10
|
# 2) http://www.mp3-tech.org/
|
|
11
11
|
# 3) http://www.fortunecity.com/underworld/sonic/3/id3tag.html
|
|
12
12
|
# 4) https://id3.org/Lyrics3
|
|
@@ -76,9 +76,9 @@ my %dateTimeConv = (
|
|
|
76
76
|
OGG, FLAC, APE, MPC and RealAudio files. ID3v2 tags which support multiple
|
|
77
77
|
languages (eg. Comment and Lyrics) are extracted by specifying the tag name,
|
|
78
78
|
followed by a dash ('-'), then a 3-character ISO 639-2 language code (eg.
|
|
79
|
-
"Comment-spa"). See L<
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
"Comment-spa"). See L<https://id3.org/> for the official ID3 specification
|
|
80
|
+
and L<http://www.loc.gov/standards/iso639-2/php/code_list.php> for a list of
|
|
81
|
+
ISO 639-2 language codes.
|
|
82
82
|
},
|
|
83
83
|
ID3v1 => {
|
|
84
84
|
Name => 'ID3v1',
|
|
@@ -1661,7 +1661,7 @@ under the same terms as Perl itself.
|
|
|
1661
1661
|
|
|
1662
1662
|
=over 4
|
|
1663
1663
|
|
|
1664
|
-
=item L<
|
|
1664
|
+
=item L<https://id3.org/>
|
|
1665
1665
|
|
|
1666
1666
|
=item L<http://www.mp3-tech.org/>
|
|
1667
1667
|
|
|
@@ -12,7 +12,7 @@ use strict;
|
|
|
12
12
|
use vars qw($VERSION);
|
|
13
13
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
14
14
|
|
|
15
|
-
$VERSION = '1.
|
|
15
|
+
$VERSION = '1.12';
|
|
16
16
|
|
|
17
17
|
sub MDItemLocalTime($);
|
|
18
18
|
sub ProcessATTR($$$);
|
|
@@ -381,7 +381,7 @@ sub SetMacOSTags($$$)
|
|
|
381
381
|
$val = Image::ExifTool::ConvertUnixTime($time, 1) if $time;
|
|
382
382
|
}
|
|
383
383
|
$val =~ s{(\d{4}):(\d{2}):(\d{2})}{$2/$3/$1}; # reformat for setfile
|
|
384
|
-
$cmd = "setfile -d '${val}' '${f}'";
|
|
384
|
+
$cmd = "/usr/bin/setfile -d '${val}' '${f}'";
|
|
385
385
|
} elsif ($tag eq 'MDItemUserTags') {
|
|
386
386
|
# (tested with "tag" version 0.9.0)
|
|
387
387
|
($f = $file) =~ s/'/'\\''/g;
|
|
@@ -391,7 +391,7 @@ sub SetMacOSTags($$$)
|
|
|
391
391
|
my @dels = @{$$nvHash{DelValue}};
|
|
392
392
|
s/'/'\\''/g foreach @dels;
|
|
393
393
|
my $del = join ',', @dels;
|
|
394
|
-
$err = system "tag -r '${del}' '${f}'>/dev/null 2>&1";
|
|
394
|
+
$err = system "/usr/local/bin/tag -r '${del}' '${f}'>/dev/null 2>&1";
|
|
395
395
|
unless ($err) {
|
|
396
396
|
$et->VerboseValue("- $tag", $del);
|
|
397
397
|
$result = 1;
|
|
@@ -403,13 +403,13 @@ sub SetMacOSTags($$$)
|
|
|
403
403
|
s/'/'\\''/g foreach @vals;
|
|
404
404
|
my $opt = $overwrite > 0 ? '-s' : '-a';
|
|
405
405
|
$val = @vals ? join(',', @vals) : '';
|
|
406
|
-
$cmd = "tag $opt '${val}' '${f}'";
|
|
406
|
+
$cmd = "/usr/local/bin/tag $opt '${val}' '${f}'";
|
|
407
407
|
$et->VPrint(1," - $tag = (all)\n") if $overwrite > 0;
|
|
408
408
|
undef $val if $val eq '';
|
|
409
409
|
}
|
|
410
410
|
} elsif ($tag eq 'XAttrQuarantine') {
|
|
411
411
|
($f = $file) =~ s/'/'\\''/g;
|
|
412
|
-
$cmd = "xattr -d com.apple.quarantine '${f}'";
|
|
412
|
+
$cmd = "/usr/bin/xattr -d com.apple.quarantine '${f}'";
|
|
413
413
|
$silentErr = 256; # (will get this error if attribute doesn't exist)
|
|
414
414
|
} else {
|
|
415
415
|
($f = $file) =~ s/(["\\])/\\$1/g; # escape necessary characters for script
|
|
@@ -426,7 +426,7 @@ sub SetMacOSTags($$$)
|
|
|
426
426
|
$v = $val ? 8 - $val : 0; # convert from label to label index (0 for no label)
|
|
427
427
|
$attr = 'label index';
|
|
428
428
|
}
|
|
429
|
-
$cmd = qq(osascript -e 'set fp to POSIX file "$f" as alias' -e \\
|
|
429
|
+
$cmd = qq(/usr/bin/osascript -e 'set fp to POSIX file "$f" as alias' -e \\
|
|
430
430
|
'tell application "Finder" to set $attr of file fp to "$v"');
|
|
431
431
|
}
|
|
432
432
|
if (defined $cmd) {
|
|
@@ -455,7 +455,7 @@ sub ExtractMDItemTags($$)
|
|
|
455
455
|
|
|
456
456
|
($fn = $file) =~ s/([`"\$\\])/\\$1/g; # escape necessary characters
|
|
457
457
|
$et->VPrint(0, '(running mdls)');
|
|
458
|
-
my @mdls =
|
|
458
|
+
my @mdls = `/usr/bin/mdls "$fn" 2> /dev/null`; # get MacOS metadata
|
|
459
459
|
if ($? or not @mdls) {
|
|
460
460
|
$et->Warn('Error running "mdls" to extract MDItem tags');
|
|
461
461
|
return;
|
|
@@ -565,7 +565,7 @@ sub ExtractXAttrTags($$)
|
|
|
565
565
|
|
|
566
566
|
($fn = $file) =~ s/([`"\$\\])/\\$1/g; # escape necessary characters
|
|
567
567
|
$et->VPrint(0, '(running xattr)');
|
|
568
|
-
my @xattr =
|
|
568
|
+
my @xattr = `/usr/bin/xattr -lx "$fn" 2> /dev/null`; # get MacOS extended attributes
|
|
569
569
|
if ($? or not @xattr) {
|
|
570
570
|
$? and $et->Warn('Error running "xattr" to extract XAttr tags');
|
|
571
571
|
return;
|
|
@@ -611,7 +611,7 @@ sub GetFileCreateDate($$)
|
|
|
611
611
|
|
|
612
612
|
($fn = $file) =~ s/([`"\$\\])/\\$1/g; # escape necessary characters
|
|
613
613
|
$et->VPrint(0, '(running stat)');
|
|
614
|
-
my $time =
|
|
614
|
+
my $time = `/usr/bin/stat -f '%SB' -t '%Y:%m:%d %H:%M:%S%z' "$fn" 2> /dev/null`;
|
|
615
615
|
if ($? or not $time or $time !~ s/([-+]\d{2})(\d{2})\s*$/$1:$2/) {
|
|
616
616
|
$et->Warn('Error running "stat" to extract FileCreateDate');
|
|
617
617
|
return;
|
|
@@ -21,7 +21,7 @@ sub ProcessKodakPatch($$$);
|
|
|
21
21
|
sub WriteUnknownOrPreview($$$);
|
|
22
22
|
sub FixLeicaBase($$;$);
|
|
23
23
|
|
|
24
|
-
$VERSION = '2.
|
|
24
|
+
$VERSION = '2.11';
|
|
25
25
|
|
|
26
26
|
my $debug; # set to 1 to enable debugging code
|
|
27
27
|
|
|
@@ -89,6 +89,11 @@ my $debug; # set to 1 to enable debugging code
|
|
|
89
89
|
FixBase => 1, # necessary for AVI and MOV videos
|
|
90
90
|
},
|
|
91
91
|
},
|
|
92
|
+
{
|
|
93
|
+
Name => 'MakerNoteDJIInfo',
|
|
94
|
+
Condition => '$$valPt =~ /^\[ae_dbg_info:/',
|
|
95
|
+
SubDirectory => { TagTable => 'Image::ExifTool::DJI::Info' },
|
|
96
|
+
},
|
|
92
97
|
{
|
|
93
98
|
Name => 'MakerNoteDJI',
|
|
94
99
|
Condition => '$$self{Make} eq "DJI" and $$valPt !~ /^...\@AMBA/s',
|
|
@@ -570,6 +575,17 @@ my $debug; # set to 1 to enable debugging code
|
|
|
570
575
|
ByteOrder => 'Unknown',
|
|
571
576
|
},
|
|
572
577
|
},
|
|
578
|
+
{
|
|
579
|
+
Name => 'MakerNoteOlympus3',
|
|
580
|
+
# new Olympus maker notes start with "OLYMPUS\0"
|
|
581
|
+
Condition => '$$valPt =~ /^OM SYSTEM\0/',
|
|
582
|
+
SubDirectory => {
|
|
583
|
+
TagTable => 'Image::ExifTool::Olympus::Main',
|
|
584
|
+
Start => '$valuePtr + 16',
|
|
585
|
+
Base => '$start - 16',
|
|
586
|
+
ByteOrder => 'Unknown',
|
|
587
|
+
},
|
|
588
|
+
},
|
|
573
589
|
{
|
|
574
590
|
Name => 'MakerNoteLeica',
|
|
575
591
|
# (starts with "LEICA\0\0\0")
|
|
@@ -63,7 +63,7 @@ use Image::ExifTool::Exif;
|
|
|
63
63
|
use Image::ExifTool::GPS;
|
|
64
64
|
use Image::ExifTool::XMP;
|
|
65
65
|
|
|
66
|
-
$VERSION = '4.
|
|
66
|
+
$VERSION = '4.06';
|
|
67
67
|
|
|
68
68
|
sub LensIDConv($$$);
|
|
69
69
|
sub ProcessNikonAVI($$$);
|
|
@@ -437,6 +437,7 @@ sub GetAFPointGrid($$;$);
|
|
|
437
437
|
'A5 40 2D 88 2C 40 4B 0E' => 'Sigma 18-250mm F3.5-6.3 DC OS HSM',
|
|
438
438
|
# LensFStops varies with FocalLength for this lens (ref 2):
|
|
439
439
|
'92 2C 2D 88 2C 40 4B 0E' => 'Sigma 18-250mm F3.5-6.3 DC Macro OS HSM', #2
|
|
440
|
+
'87 2C 2D 8E 2C 40 4B 0E' => 'Sigma 18-300mm F3.5-6.3 DC Macro HSM', #30
|
|
440
441
|
# '92 2C 2D 88 2C 40 4B 0E' (250mm)
|
|
441
442
|
# '92 2B 2D 88 2C 40 4B 0E' (210mm)
|
|
442
443
|
# '92 2C 2D 88 2C 40 4B 0E' (185mm)
|
|
@@ -495,6 +496,7 @@ sub GetAFPointGrid($$;$);
|
|
|
495
496
|
'7A 48 5C 80 24 24 4B 06' => 'Sigma 70-200mm F2.8 EX APO DG Macro HSM II',
|
|
496
497
|
'EE 48 5C 80 24 24 4B 06' => 'Sigma 70-200mm F2.8 EX APO DG Macro HSM II', #JD
|
|
497
498
|
'9C 48 5C 80 24 24 4B 0E' => 'Sigma 70-200mm F2.8 EX DG OS HSM', #Rolando Ruzic
|
|
499
|
+
'BB 48 5C 80 24 24 4B 4E' => 'Sigma 70-200mm F2.8 DG OS HSM | S', #forum13207
|
|
498
500
|
'02 46 5C 82 25 25 02 00' => 'Sigma 70-210mm F2.8 APO', #JD
|
|
499
501
|
'02 40 5C 82 2C 35 02 00' => 'Sigma APO 70-210mm F3.5-4.5',
|
|
500
502
|
'26 3C 5C 82 30 3C 1C 02' => 'Sigma 70-210mm F4-5.6 UC-II',
|
|
@@ -665,6 +667,7 @@ sub GetAFPointGrid($$;$);
|
|
|
665
667
|
'00 54 55 55 0C 0C 00 00' => 'Voigtlander Nokton 58mm F1.4 SLII',
|
|
666
668
|
'00 40 64 64 2C 2C 00 00' => 'Voigtlander APO-Lanthar 90mm F3.5 SLII Close Focus',
|
|
667
669
|
'07 40 30 45 2D 35 03 02.2' => 'Voigtlander Ultragon 19-35mm F3.5-4.5 VMV', #NJ
|
|
670
|
+
'71 48 64 64 24 24 00 00' => 'Voigtlander APO-Skopar 90mm F2.8 SL IIs', #30
|
|
668
671
|
#
|
|
669
672
|
'00 40 2D 2D 2C 2C 00 00' => 'Carl Zeiss Distagon T* 3.5/18 ZF.2',
|
|
670
673
|
'00 48 27 27 24 24 00 00' => 'Carl Zeiss Distagon T* 2.8/15 ZF.2', #MykytaKozlov
|
|
@@ -1220,6 +1223,16 @@ my %binaryDataAttrs = (
|
|
|
1220
1223
|
my %base64bin = ( ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)' );
|
|
1221
1224
|
my %base64int32u = ( ValueConv => 'my $val=Image::ExifTool::XMP::DecodeBase64($val); unpack("V",$$val)' );
|
|
1222
1225
|
my %base64bytes = ( ValueConv => 'my $val=Image::ExifTool::XMP::DecodeBase64($val); join(".",unpack("C*",$$val))' );
|
|
1226
|
+
my %base64double = (
|
|
1227
|
+
ValueConv => q{
|
|
1228
|
+
my $val=Image::ExifTool::XMP::DecodeBase64($val);
|
|
1229
|
+
my $saveOrder = GetByteOrder();
|
|
1230
|
+
SetByteOrder('II');
|
|
1231
|
+
$val = GetDouble($val,0);
|
|
1232
|
+
SetByteOrder($saveOrder);
|
|
1233
|
+
return $val;
|
|
1234
|
+
},
|
|
1235
|
+
);
|
|
1223
1236
|
my %base64coord = (
|
|
1224
1237
|
ValueConv => q{
|
|
1225
1238
|
my $val=Image::ExifTool::XMP::DecodeBase64($val);
|
|
@@ -4180,7 +4193,7 @@ my %base64coord = (
|
|
|
4180
4193
|
Format => 'int16u',
|
|
4181
4194
|
},
|
|
4182
4195
|
0x43 => {
|
|
4183
|
-
Name => '
|
|
4196
|
+
Name => 'FocusPositionHorizontal',
|
|
4184
4197
|
PrintConv => sub { my ($val) = @_; PrintAFPointsLeftRight($val, 29 ); }, #493 focus points for Z9 fall in a 30x18 grid (some coordinates are not accessible)
|
|
4185
4198
|
},
|
|
4186
4199
|
0x45 => {
|
|
@@ -8565,7 +8578,19 @@ my %nikonFocalConversions = (
|
|
|
8565
8578
|
444 => { Name => 'FlashRemoteControl', PrintConv => \%flashRemoteControlZ7, Unknown => 1},
|
|
8566
8579
|
456 => { Name => 'FlashWirelessOption', PrintConv => \%flashWirelessOptionZ7, Unknown => 1},
|
|
8567
8580
|
#526 FocusMode
|
|
8568
|
-
|
|
8581
|
+
528 => {
|
|
8582
|
+
Name => 'AFAreaMode',
|
|
8583
|
+
PrintConv => {
|
|
8584
|
+
1 => 'Single',
|
|
8585
|
+
2 => 'Dynamic',
|
|
8586
|
+
3 => 'Wide (S)',
|
|
8587
|
+
4 => 'Wide (L)',
|
|
8588
|
+
5 => '3D',
|
|
8589
|
+
6 => 'Auto',
|
|
8590
|
+
12 => 'Wide (C1)',
|
|
8591
|
+
13 => 'Wide (C2)',
|
|
8592
|
+
},
|
|
8593
|
+
},
|
|
8569
8594
|
530 => { Name => 'VRMode', PrintConv => \%vRModeZ9},
|
|
8570
8595
|
534 => {
|
|
8571
8596
|
Name => 'BracketSet',
|
|
@@ -8634,6 +8659,8 @@ my %nikonFocalConversions = (
|
|
|
8634
8659
|
2 => 'H.265 8-bit (MOV)',
|
|
8635
8660
|
3 => 'H.265 10-bit (MOV)',
|
|
8636
8661
|
4 => 'ProRes 422 HQ 10-bit (MOV)',
|
|
8662
|
+
5 => 'ProRes RAW HQ 12-bit (MOV)',
|
|
8663
|
+
6 => 'NRAW 12-bit (NEV)'
|
|
8637
8664
|
},
|
|
8638
8665
|
},
|
|
8639
8666
|
616 => {
|
|
@@ -11055,17 +11082,22 @@ my %nikonFocalConversions = (
|
|
|
11055
11082
|
},
|
|
11056
11083
|
GPSAltitude => {
|
|
11057
11084
|
Groups => { 2 => 'Location' },
|
|
11058
|
-
|
|
11059
|
-
my $val=Image::ExifTool::XMP::DecodeBase64($val);
|
|
11060
|
-
my $saveOrder = GetByteOrder();
|
|
11061
|
-
SetByteOrder('II');
|
|
11062
|
-
$val = GetDouble($val,0);
|
|
11063
|
-
SetByteOrder($saveOrder);
|
|
11064
|
-
return $val;
|
|
11065
|
-
},
|
|
11085
|
+
%base64double,
|
|
11066
11086
|
PrintConv => '"$val m"',
|
|
11067
11087
|
},
|
|
11068
|
-
GPSMapDatum => { },
|
|
11088
|
+
GPSMapDatum => { Groups => { 2 => 'Location' } },
|
|
11089
|
+
GPSImgDirection => {
|
|
11090
|
+
Groups => { 2 => 'Location' },
|
|
11091
|
+
%base64double,
|
|
11092
|
+
PrintConv => 'sprintf("%.2f", $val)',
|
|
11093
|
+
},
|
|
11094
|
+
GPSImgDirectionRef => {
|
|
11095
|
+
Groups => { 2 => 'Location' },
|
|
11096
|
+
PrintConv => {
|
|
11097
|
+
M => 'Magnetic North',
|
|
11098
|
+
T => 'True North',
|
|
11099
|
+
},
|
|
11100
|
+
},
|
|
11069
11101
|
);
|
|
11070
11102
|
%Image::ExifTool::Nikon::sdc = (
|
|
11071
11103
|
GROUPS => { 0 => 'XMP', 1 => 'XMP-sdc', 2 => 'Image' },
|
|
@@ -15,7 +15,7 @@ package Image::ExifTool::NikonCustom;
|
|
|
15
15
|
use strict;
|
|
16
16
|
use vars qw($VERSION);
|
|
17
17
|
|
|
18
|
-
$VERSION = '1.
|
|
18
|
+
$VERSION = '1.20';
|
|
19
19
|
|
|
20
20
|
my %buttonsZ9= (
|
|
21
21
|
0 => 'None',
|
|
@@ -74,6 +74,9 @@ my %buttonsZ9= (
|
|
|
74
74
|
82 => 'Select To Send (PC)',
|
|
75
75
|
83 => 'Select To Send (FTP)',
|
|
76
76
|
85 => 'Control Lock',
|
|
77
|
+
86 => 'Save Focus Position',
|
|
78
|
+
87 => 'Recall Focus Position',
|
|
79
|
+
88 => 'Recall Shooting Functions (Hold)',
|
|
77
80
|
);
|
|
78
81
|
my %dialsZ9 = (
|
|
79
82
|
0 => '1 Frame',
|