exiftool_vendored 13.47.0 → 13.50.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.
- checksums.yaml +4 -4
- data/bin/Changes +31 -1
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/exiftool +2 -2
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +12 -6
- data/bin/lib/Image/ExifTool/Canon.pm +6 -1
- data/bin/lib/Image/ExifTool/CanonRaw.pm +4 -2
- data/bin/lib/Image/ExifTool/CaptureOne.pm +2 -2
- data/bin/lib/Image/ExifTool/DICOM.pm +5 -2
- data/bin/lib/Image/ExifTool/Exif.pm +10 -2
- data/bin/lib/Image/ExifTool/FlashPix.pm +6 -6
- data/bin/lib/Image/ExifTool/GM.pm +3 -3
- data/bin/lib/Image/ExifTool/Geolocation.dat +0 -0
- data/bin/lib/Image/ExifTool/Geotag.pm +33 -7
- data/bin/lib/Image/ExifTool/MacOS.pm +32 -21
- data/bin/lib/Image/ExifTool/Nikon.pm +30 -28
- data/bin/lib/Image/ExifTool/NikonCustom.pm +5 -5
- data/bin/lib/Image/ExifTool/QuickTime.pm +6 -5
- data/bin/lib/Image/ExifTool/README +23 -17
- data/bin/lib/Image/ExifTool/Samsung.pm +19 -2
- data/bin/lib/Image/ExifTool/Sony.pm +63 -36
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +4 -1
- data/bin/lib/Image/ExifTool/TagLookup.pm +15 -3
- data/bin/lib/Image/ExifTool/TagNames.pod +42 -6
- data/bin/lib/Image/ExifTool/Validate.pm +2 -1
- data/bin/lib/Image/ExifTool/XMP.pm +7 -5
- data/bin/lib/Image/ExifTool.pm +27 -11
- data/bin/lib/Image/ExifTool.pod +5 -5
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 119da28d5499012533651a09438cf1c0b551bb65e4b97815bc86190c7b439beb
|
|
4
|
+
data.tar.gz: 11292b43f6d89879e7eef760270799f803ec5bc15cdcaf8eb9c57fdeb7d9f9cc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 36b76bee5489e79558b03b5eabf21f0e59d9d60c4702818468f82dd50141f652caa8395a791d117d502d3e7aff95d6ceb139e741fa5351c0cf5925936331d45b
|
|
7
|
+
data.tar.gz: 39b786e84e02df42bc8021b97084fa899810a4b8207e5bb91fc92dc990e4768efb1600bfc83497f7ae0d1db2cab02677633e054cc23fe693e30490778dd09f23
|
data/bin/Changes
CHANGED
|
@@ -4,14 +4,44 @@ ExifTool Version History
|
|
|
4
4
|
|
|
5
5
|
RSS feed: https://exiftool.org/rss.xml
|
|
6
6
|
|
|
7
|
-
Note: The most recent production release is Version 13.
|
|
7
|
+
Note: The most recent production release is Version 13.50. (Other versions are
|
|
8
8
|
considered development releases, and are not uploaded to MetaCPAN.)
|
|
9
9
|
|
|
10
|
+
Feb. 7, 2026 - Version 13.50 (production release)
|
|
11
|
+
|
|
12
|
+
- Added a few new Sony lenses (thanks Jos Roost)
|
|
13
|
+
- Added a couple of new Canon lenses (thanks Norbert Wasser)
|
|
14
|
+
- Decode another Samsung trailer tag
|
|
15
|
+
- Decode BlackLevels from some Canon CRW files (github #387)
|
|
16
|
+
- Updated Sony maker note decoding for the ILCE-7M5 (thanks Jos Roost)
|
|
17
|
+
- Patched potential MacOS security issue (thanks Tay Kiat Loong)
|
|
18
|
+
- Fixed -list options so reading image files beforehand doesn't add tags to
|
|
19
|
+
the output when running multiple commands using the -execute feature
|
|
20
|
+
|
|
21
|
+
Feb. 3, 2026 - Version 13.49
|
|
22
|
+
|
|
23
|
+
- Decode a couple of new Samsung trailer tags
|
|
24
|
+
- Disabled decoding of MenuSettings for the Nikon Z6III firmware 2.0 until the
|
|
25
|
+
changes can be worked through in detail
|
|
26
|
+
- Fixed problem where Google Photos had problems displaying ExifTool-edited
|
|
27
|
+
HEIC MotionPhoto images. Files written by older versions of ExifTool may be
|
|
28
|
+
repaired by re-writing with 13.49 or later
|
|
29
|
+
|
|
30
|
+
Jan. 31, 2026 - Version 13.48
|
|
31
|
+
|
|
32
|
+
- Added a new Nikon LensID (github #385)
|
|
33
|
+
- Added support for quoted entries in input -geotag CSV files
|
|
34
|
+
- Fixed decoding of Nikon Z6III menu settings for firmware 2.0 update
|
|
35
|
+
- Fixed -fast2 to avoid processing maker notes in some QuickTime-based files
|
|
36
|
+
- Fixed bug introduced in version 13.46 where some tags may be associated with
|
|
37
|
+
the next fix when geotagging from GPX files
|
|
38
|
+
|
|
10
39
|
Jan. 27, 2026 - Version 13.47
|
|
11
40
|
|
|
12
41
|
- Enhanced -fast option to avoid scanning QuickTime MediaData for metadata
|
|
13
42
|
(improves performance when reading CR3 files from slow media, github #384)
|
|
14
43
|
and -fast2 to avoid reading HDRP maker notes
|
|
44
|
+
- Fixed hang problem when reading HDRPMakerNotes from some Google phones
|
|
15
45
|
- API Changes:
|
|
16
46
|
- Added CSV support to GeoUserTag option
|
|
17
47
|
|
data/bin/META.json
CHANGED
data/bin/META.yml
CHANGED
data/bin/README
CHANGED
|
@@ -111,8 +111,8 @@ your home directory, then you would type the following commands in a
|
|
|
111
111
|
terminal window to extract and run ExifTool:
|
|
112
112
|
|
|
113
113
|
cd ~/Desktop
|
|
114
|
-
gzip -dc Image-ExifTool-13.
|
|
115
|
-
cd Image-ExifTool-13.
|
|
114
|
+
gzip -dc Image-ExifTool-13.50.tar.gz | tar -xf -
|
|
115
|
+
cd Image-ExifTool-13.50
|
|
116
116
|
./exiftool t/images/ExifTool.jpg
|
|
117
117
|
|
|
118
118
|
Note: These commands extract meta information from one of the test images.
|
data/bin/exiftool
CHANGED
|
@@ -11,7 +11,7 @@ use strict;
|
|
|
11
11
|
use warnings;
|
|
12
12
|
require 5.004;
|
|
13
13
|
|
|
14
|
-
my $version = '13.
|
|
14
|
+
my $version = '13.50';
|
|
15
15
|
|
|
16
16
|
$^W = 1; # enable global warnings
|
|
17
17
|
|
|
@@ -6136,7 +6136,7 @@ with this command:
|
|
|
6136
6136
|
|
|
6137
6137
|
produces output like this:
|
|
6138
6138
|
|
|
6139
|
-
-- Generated by ExifTool 13.
|
|
6139
|
+
-- Generated by ExifTool 13.50 --
|
|
6140
6140
|
File: a.jpg - 2003:10:31 15:44:19
|
|
6141
6141
|
(f/5.6, 1/60s, ISO 100)
|
|
6142
6142
|
File: b.jpg - 2006:05:23 11:57:38
|
|
@@ -35,7 +35,7 @@ use Image::ExifTool::Sony;
|
|
|
35
35
|
use Image::ExifTool::Validate;
|
|
36
36
|
use Image::ExifTool::MacOS;
|
|
37
37
|
|
|
38
|
-
$VERSION = '3.
|
|
38
|
+
$VERSION = '3.65';
|
|
39
39
|
@ISA = qw(Exporter);
|
|
40
40
|
|
|
41
41
|
sub NumbersFirst($$);
|
|
@@ -71,6 +71,7 @@ my %tweakOrder = (
|
|
|
71
71
|
CBOR => 'JSON',
|
|
72
72
|
GeoTiff => 'GPS',
|
|
73
73
|
CanonVRD=> 'CanonCustom',
|
|
74
|
+
CaptureOne => 'CanonVRD',
|
|
74
75
|
DJI => 'Casio',
|
|
75
76
|
FLIR => 'DJI',
|
|
76
77
|
FujiFilm => 'FLIR',
|
|
@@ -977,7 +978,7 @@ TagID: foreach $tagID (@keys) {
|
|
|
977
978
|
if ($format and $format =~ /^var_/) {
|
|
978
979
|
$datamember{$tagID} = $name;
|
|
979
980
|
unless (defined $$tagInfo{Writable} and not $$tagInfo{Writable}) {
|
|
980
|
-
warn "Warning: Var-format tag is writable - $short $name\n"
|
|
981
|
+
warn "Warning: Var-format tag is writable - $short $name\n";
|
|
981
982
|
}
|
|
982
983
|
# also need DATAMEMBER for tags used in length of var-sized value
|
|
983
984
|
while ($format =~ /\$val\{(.*?)\}/g) {
|
|
@@ -996,10 +997,15 @@ TagID: foreach $tagID (@keys) {
|
|
|
996
997
|
if ($format and $format =~ /\$val\{/ and
|
|
997
998
|
($$tagInfo{Writable} or not defined $$tagInfo{Writable}))
|
|
998
999
|
{
|
|
999
|
-
warn "Warning: \$val{} used in Format of writable tag - $short $name\n"
|
|
1000
|
+
warn "Warning: \$val{} used in Format of writable tag - $short $name\n";
|
|
1000
1001
|
}
|
|
1001
1002
|
}
|
|
1002
1003
|
if ($$tagInfo{Hidden}) {
|
|
1004
|
+
if ($$tagInfo{Hidden} ne '2' and not $$tagInfo{Unknown} and
|
|
1005
|
+
(not $$tagInfo{RawConv} or $$tagInfo{RawConv} !~ /Unknown|undef/))
|
|
1006
|
+
{
|
|
1007
|
+
warn "Warning: $short $name is Hidden contrary to guidelines\n";
|
|
1008
|
+
}
|
|
1003
1009
|
if ($tagInfo == $infoArray[0]) {
|
|
1004
1010
|
next TagID; # hide all tags with this ID if first tag in list is hidden
|
|
1005
1011
|
} else {
|
|
@@ -1011,7 +1017,7 @@ TagID: foreach $tagID (@keys) {
|
|
|
1011
1017
|
$writable = $$tagInfo{Writable};
|
|
1012
1018
|
# validate Writable
|
|
1013
1019
|
unless ($formatOK{$writable} or ($writable =~ /(.*)\[/ and $formatOK{$1})) {
|
|
1014
|
-
warn "Warning: Unknown Writable ($writable) - $short $name\n"
|
|
1020
|
+
warn "Warning: Unknown Writable ($writable) - $short $name\n";
|
|
1015
1021
|
}
|
|
1016
1022
|
} elsif (not $$tagInfo{SubDirectory}) {
|
|
1017
1023
|
$writable = $$table{WRITABLE};
|
|
@@ -1021,7 +1027,7 @@ TagID: foreach $tagID (@keys) {
|
|
|
1021
1027
|
undef $writable;
|
|
1022
1028
|
}
|
|
1023
1029
|
#if ($writable and $$tagInfo{Unknown} and $$table{GROUPS}{0} ne 'MakerNotes') {
|
|
1024
|
-
# warn "Warning: Writable Unknown tag - $short $name\n"
|
|
1030
|
+
# warn "Warning: Writable Unknown tag - $short $name\n";
|
|
1025
1031
|
#}
|
|
1026
1032
|
# validate some characteristics of obvious date/time tags
|
|
1027
1033
|
my @g = $et->GetGroup($tagInfo);
|
|
@@ -2096,7 +2102,7 @@ sub CloseHtmlFiles($)
|
|
|
2096
2102
|
if ($htmlFile =~ /index\.html$/) {
|
|
2097
2103
|
print HTMLFILE "'../index.html'><-- Back to ExifTool home page</a></p>\n";
|
|
2098
2104
|
} else {
|
|
2099
|
-
print HTMLFILE "'index.html'><-- ExifTool Tag Names</a></p>\n"
|
|
2105
|
+
print HTMLFILE "'index.html'><-- ExifTool Tag Names</a></p>\n";
|
|
2100
2106
|
}
|
|
2101
2107
|
print HTMLFILE "</body>\n</html>\n" or $success = 0;
|
|
2102
2108
|
close HTMLFILE or $success = 0;
|
|
@@ -88,7 +88,7 @@ sub ProcessCTMD($$$);
|
|
|
88
88
|
sub ProcessExifInfo($$$);
|
|
89
89
|
sub SwapWords($);
|
|
90
90
|
|
|
91
|
-
$VERSION = '5.
|
|
91
|
+
$VERSION = '5.03';
|
|
92
92
|
|
|
93
93
|
# Note: Removed 'USM' from 'L' lenses since it is redundant - PH
|
|
94
94
|
# (or is it? Ref 32 shows 5 non-USM L-type lenses)
|
|
@@ -645,6 +645,8 @@ $VERSION = '5.02';
|
|
|
645
645
|
'61182.64' => 'Canon RF 20mm F1.4 L VCM', #42
|
|
646
646
|
'61182.65' => 'Canon RF 85mm F1.4 L VCM', #github350
|
|
647
647
|
'61182.66' => 'Canon RF 45mm F1.2 STM', #42
|
|
648
|
+
'61182.67' => 'Canon RF 7-14mm F2.8-3.5 L FISHEYE STM', #42
|
|
649
|
+
'61182.68' => 'Canon RF 14mm F1.4 L VCM', #42
|
|
648
650
|
65535 => 'n/a',
|
|
649
651
|
);
|
|
650
652
|
|
|
@@ -7081,6 +7083,8 @@ my %ciMaxFocal = (
|
|
|
7081
7083
|
327 => 'Canon RF 20mm F1.4 L VCM', #42
|
|
7082
7084
|
328 => 'Canon RF 85mm F1.4 L VCM', #42/github350
|
|
7083
7085
|
330 => 'Canon RF 45mm F1.2 STM', #42
|
|
7086
|
+
331 => 'Canon RF 7-14mm F2.8-3.5 L FISHEYE STM', #42
|
|
7087
|
+
332 => 'Canon RF 14mm F1.4 L VCM', #42
|
|
7084
7088
|
# Note: add new RF lenses to %canonLensTypes with ID 61182
|
|
7085
7089
|
},
|
|
7086
7090
|
},
|
|
@@ -9728,6 +9732,7 @@ my %filterConv = (
|
|
|
9728
9732
|
},
|
|
9729
9733
|
0x927c => {
|
|
9730
9734
|
Name => 'MakerNoteCanon',
|
|
9735
|
+
MakerNotes => 1,
|
|
9731
9736
|
SubDirectory => {
|
|
9732
9737
|
TagTable => 'Image::ExifTool::Canon::Main',
|
|
9733
9738
|
ProcessProc => \&Image::ExifTool::ProcessTIFF,
|
|
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
21
21
|
use Image::ExifTool::Exif;
|
|
22
22
|
use Image::ExifTool::Canon;
|
|
23
23
|
|
|
24
|
-
$VERSION = '1.
|
|
24
|
+
$VERSION = '1.62';
|
|
25
25
|
|
|
26
26
|
sub WriteCRW($$);
|
|
27
27
|
sub ProcessCanonRaw($$$);
|
|
@@ -595,7 +595,9 @@ sub BuildMakerNotes($$$$$$);
|
|
|
595
595
|
3 => 'WhiteSampleLeftBorder',
|
|
596
596
|
4 => 'WhiteSampleTopBorder',
|
|
597
597
|
5 => 'WhiteSampleBits',
|
|
598
|
-
#
|
|
598
|
+
# (followed by the encrypted white sample values, ref 1)
|
|
599
|
+
# BlackLevels seem valid for D30 and D60, but not sure about PowerShot models
|
|
600
|
+
0x37 => { Name => 'BlackLevels', Format => 'int16u[4]' }, #github387
|
|
599
601
|
);
|
|
600
602
|
|
|
601
603
|
#------------------------------------------------------------------------------
|
|
@@ -17,7 +17,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
17
17
|
use Image::ExifTool::XMP;
|
|
18
18
|
use Image::ExifTool::ZIP;
|
|
19
19
|
|
|
20
|
-
$VERSION = '1.
|
|
20
|
+
$VERSION = '1.05';
|
|
21
21
|
|
|
22
22
|
# CaptureOne COS XML tags
|
|
23
23
|
# - tags are added dynamically when encountered
|
|
@@ -26,7 +26,7 @@ $VERSION = '1.04';
|
|
|
26
26
|
GROUPS => { 0 => 'XML', 1 => 'XML', 2 => 'Image' },
|
|
27
27
|
PROCESS_PROC => \&Image::ExifTool::XMP::ProcessXMP,
|
|
28
28
|
VARS => { ID_FMT => 'none' },
|
|
29
|
-
ColorCorrections => { ValueConv => '\$val' }, # (long list of floating point numbers)
|
|
29
|
+
ColorCorrections => { ValueConv => '\$val', Hidden => 1 }, # (long list of floating point numbers)
|
|
30
30
|
);
|
|
31
31
|
|
|
32
32
|
#------------------------------------------------------------------------------
|
|
@@ -20,7 +20,7 @@ use strict;
|
|
|
20
20
|
use vars qw($VERSION %uid);
|
|
21
21
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
22
22
|
|
|
23
|
-
$VERSION = '1.
|
|
23
|
+
$VERSION = '1.24';
|
|
24
24
|
|
|
25
25
|
# DICOM VR (Value Representation) format conversions
|
|
26
26
|
my %dicomFormat = (
|
|
@@ -3794,7 +3794,10 @@ sub ProcessDICOM($$)
|
|
|
3794
3794
|
} elsif ($vr eq 'UI') {
|
|
3795
3795
|
# add PrintConv to translate registered UID's
|
|
3796
3796
|
$val =~ s/\0.*//s; # truncate at null
|
|
3797
|
-
|
|
3797
|
+
if ($tagInfo) {
|
|
3798
|
+
$$tagInfo{PrintConv} = \%uid if $uid{$val};
|
|
3799
|
+
$$tagInfo{Hidden} = '' unless defined $$tagInfo{Hidden}; # (don't add PrintConv to -listx output)
|
|
3800
|
+
}
|
|
3798
3801
|
} elsif ($vr =~ /^(AE|CS|DS|IS|LO|PN|SH)$/) {
|
|
3799
3802
|
$val =~ s/ +$//; # leading/trailing spaces not significant
|
|
3800
3803
|
$val =~ s/^ +//;
|
|
@@ -2118,8 +2118,16 @@ my %opcodeInfo = (
|
|
|
2118
2118
|
0x8827 => {
|
|
2119
2119
|
Name => 'ISO',
|
|
2120
2120
|
Notes => q{
|
|
2121
|
-
called ISOSpeedRatings by EXIF 2.2, then PhotographicSensitivity by
|
|
2122
|
-
2.3
|
|
2121
|
+
called ISOSpeedRatings by EXIF 2.2, then PhotographicSensitivity by EXIF
|
|
2122
|
+
2.3. This tag has a maximum value of 65535 because the brain-dead EXIF
|
|
2123
|
+
specification limits it to a short integer, and while they can change the
|
|
2124
|
+
name of the tag in an updated EXIF specification, they can't allow a larger
|
|
2125
|
+
storage format for some reason. For higher ISO settings, see the other
|
|
2126
|
+
ISO-related tags StandardOutputSensitivity, RecommendedExposureIndex,
|
|
2127
|
+
ISOSpeed, ISOSpeedLatitudeyyy and ISOSpeedLatitudezzz. But the meanings of
|
|
2128
|
+
these new tags are anyone's guess since the defining specification, ISO
|
|
2129
|
+
12232, is imprisoned by the ISO organization who extort a ransom for the
|
|
2130
|
+
release of this information
|
|
2123
2131
|
},
|
|
2124
2132
|
Writable => 'int16u',
|
|
2125
2133
|
Count => -1,
|
|
@@ -23,7 +23,7 @@ use Image::ExifTool::Exif;
|
|
|
23
23
|
use Image::ExifTool::ASF; # for GetGUID()
|
|
24
24
|
use Image::ExifTool::Microsoft; # for %codePage
|
|
25
25
|
|
|
26
|
-
$VERSION = '1.
|
|
26
|
+
$VERSION = '1.51';
|
|
27
27
|
|
|
28
28
|
sub ProcessFPX($$);
|
|
29
29
|
sub ProcessFPXR($$$);
|
|
@@ -290,12 +290,12 @@ my %fpxFileType = (
|
|
|
290
290
|
# save these tables until after the WordDocument was processed
|
|
291
291
|
'0Table' => {
|
|
292
292
|
Name => 'Table0',
|
|
293
|
-
Hidden =>
|
|
293
|
+
Hidden => 2, # (used only as temporary storage until table is processed)
|
|
294
294
|
Binary => 1,
|
|
295
295
|
},
|
|
296
296
|
'1Table' => {
|
|
297
297
|
Name => 'Table1',
|
|
298
|
-
Hidden =>
|
|
298
|
+
Hidden => 2, # (used only as temporary storage until table is processed)
|
|
299
299
|
Binary => 1,
|
|
300
300
|
},
|
|
301
301
|
Preview => {
|
|
@@ -1117,20 +1117,20 @@ my %fpxFileType = (
|
|
|
1117
1117
|
#
|
|
1118
1118
|
# tags below are used internally in intermediate steps to extract the tags above
|
|
1119
1119
|
#
|
|
1120
|
-
TableOffsets => { Hidden =>
|
|
1120
|
+
TableOffsets => { Hidden => 2 }, # stores offsets to extract data from document table
|
|
1121
1121
|
CommentByBlock => { # entire block of CommentBy entries
|
|
1122
1122
|
SubDirectory => {
|
|
1123
1123
|
TagTable => 'Image::ExifTool::FlashPix::DocTable',
|
|
1124
1124
|
ProcessProc => \&ProcessCommentBy,
|
|
1125
1125
|
},
|
|
1126
|
-
Hidden =>
|
|
1126
|
+
Hidden => 2,
|
|
1127
1127
|
},
|
|
1128
1128
|
LastSavedByBlock => { # entire block of LastSavedBy entries
|
|
1129
1129
|
SubDirectory => {
|
|
1130
1130
|
TagTable => 'Image::ExifTool::FlashPix::DocTable',
|
|
1131
1131
|
ProcessProc => \&ProcessLastSavedBy,
|
|
1132
1132
|
},
|
|
1133
|
-
Hidden =>
|
|
1133
|
+
Hidden => 2,
|
|
1134
1134
|
},
|
|
1135
1135
|
);
|
|
1136
1136
|
|
|
@@ -15,7 +15,7 @@ use vars qw($VERSION);
|
|
|
15
15
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
16
16
|
use Image::ExifTool::GPS;
|
|
17
17
|
|
|
18
|
-
$VERSION = '1.
|
|
18
|
+
$VERSION = '1.02';
|
|
19
19
|
|
|
20
20
|
sub Process_marl($$$);
|
|
21
21
|
sub Process_mrld($$$);
|
|
@@ -344,7 +344,7 @@ sub Process_mrld($$$)
|
|
|
344
344
|
|
|
345
345
|
$et->VerboseDir('mrld', undef, $dirLen);
|
|
346
346
|
require 'Image/ExifTool/XMPStruct.pl';
|
|
347
|
-
Image::ExifTool::XMP::AddFlattenedTags($tagTablePtr);
|
|
347
|
+
Image::ExifTool::XMP::AddFlattenedTags($tagTablePtr, undef, undef, 1);
|
|
348
348
|
$csv = [ ] if $et->Options('PrintCSV');
|
|
349
349
|
|
|
350
350
|
for ($pos=0; $pos+448<=$dirLen; $pos+=448) {
|
|
@@ -375,7 +375,7 @@ sub Process_mrld($$$)
|
|
|
375
375
|
my $hash = { map { $channel[$_] => $a[$_] } 1..$#a };
|
|
376
376
|
unless ($tagInfo) {
|
|
377
377
|
$tagInfo = AddTagToTable($tagTablePtr, $tag, { Name => $tag, Struct => \%channelStruct });
|
|
378
|
-
Image::ExifTool::XMP::AddFlattenedTags($tagTablePtr, $tag);
|
|
378
|
+
Image::ExifTool::XMP::AddFlattenedTags($tagTablePtr, $tag, undef, 1);
|
|
379
379
|
}
|
|
380
380
|
# extract channel structure if specified
|
|
381
381
|
if ($struct) {
|
|
Binary file
|
|
@@ -36,7 +36,7 @@ use vars qw($VERSION);
|
|
|
36
36
|
use Image::ExifTool qw(:Public);
|
|
37
37
|
use Image::ExifTool::GPS;
|
|
38
38
|
|
|
39
|
-
$VERSION = '1.
|
|
39
|
+
$VERSION = '1.87';
|
|
40
40
|
|
|
41
41
|
sub JITTER() { return 2 } # maximum time jitter
|
|
42
42
|
|
|
@@ -137,6 +137,31 @@ my %otherConv = (
|
|
|
137
137
|
|
|
138
138
|
my $secPerDay = 24 * 3600; # a useful constant
|
|
139
139
|
|
|
140
|
+
#------------------------------------------------------------------------------
|
|
141
|
+
# Split a line of CSV
|
|
142
|
+
# Inputs: 0) line to split, 1) delimiter
|
|
143
|
+
# Returns: list of items
|
|
144
|
+
sub SplitCSV($$)
|
|
145
|
+
{
|
|
146
|
+
my ($line, $delim) = @_;
|
|
147
|
+
my @toks = split /\Q$delim/, $line;
|
|
148
|
+
my (@vals, $v);
|
|
149
|
+
while (@toks) {
|
|
150
|
+
($v = shift @toks) =~ s/^ +//; # remove leading spaces
|
|
151
|
+
if ($v =~ s/^"//) {
|
|
152
|
+
# quoted value must end in an odd number of quotes
|
|
153
|
+
while ($v !~ /("+)\s*$/ or not length($1) & 1) {
|
|
154
|
+
last unless @toks;
|
|
155
|
+
$v .= $delim . shift @toks;
|
|
156
|
+
}
|
|
157
|
+
$v =~ s/"\s*$//; # remove trailing quote and whitespace
|
|
158
|
+
$v =~ s/""/"/g; # un-escape quotes
|
|
159
|
+
}
|
|
160
|
+
push @vals, $v;
|
|
161
|
+
}
|
|
162
|
+
return @vals;
|
|
163
|
+
}
|
|
164
|
+
|
|
140
165
|
#------------------------------------------------------------------------------
|
|
141
166
|
# Load GPS track log file
|
|
142
167
|
# Inputs: 0) ExifTool ref, 1) track log data or file name
|
|
@@ -281,7 +306,7 @@ sub LoadTrackLog($$;$)
|
|
|
281
306
|
$format = 'Bramor';
|
|
282
307
|
} elsif (((/\b(GPS)?Date/i and /\b(GPS)?(Date)?Time/i) or /\bTime\(seconds\)/i) and /\Q$csvDelim/) {
|
|
283
308
|
chomp;
|
|
284
|
-
@csvHeadings =
|
|
309
|
+
@csvHeadings = SplitCSV($_, $csvDelim);
|
|
285
310
|
my $isColumbus = ($csvHeadings[0] and $csvHeadings[0] eq 'INDEX'); # (Columbus GPS logger)
|
|
286
311
|
$format = 'CSV';
|
|
287
312
|
# convert recognized headings to our parameter names
|
|
@@ -382,7 +407,8 @@ sub LoadTrackLog($$;$)
|
|
|
382
407
|
# parse attributes (eg. GPX 'lat' and 'lon')
|
|
383
408
|
# (note: ignore namespace prefixes if they exist)
|
|
384
409
|
if ($arg =~ /^(\w+:)?(\w+)=(['"])(.*?)\3/g) {
|
|
385
|
-
my $tag = $xmlTag{lc $2}
|
|
410
|
+
my $tag = $xmlTag{lc $2};
|
|
411
|
+
$tag = $userTag{lc $2} unless defined $tag;
|
|
386
412
|
if ($tag) {
|
|
387
413
|
$$fix{$tag} = $4;
|
|
388
414
|
if ($keyCategory{$tag}) {
|
|
@@ -399,7 +425,8 @@ sub LoadTrackLog($$;$)
|
|
|
399
425
|
# loop through XML elements
|
|
400
426
|
while ($arg =~ m{([^<>]*)<(/)?(\w+:)?(\w+)(>|$)}g) {
|
|
401
427
|
$tok = lc $4;
|
|
402
|
-
my $tag = $xmlTag{$tok}
|
|
428
|
+
my $tag = $xmlTag{$tok};
|
|
429
|
+
$tag = $userTag{$tok} unless defined $tag;
|
|
403
430
|
# parse as a simple property if this element has a value
|
|
404
431
|
if (defined $tag and not $tag) {
|
|
405
432
|
# a containing property was opened or closed
|
|
@@ -530,7 +557,7 @@ DoneFix: $isDate = 1;
|
|
|
530
557
|
goto DoneFix; # save this fix
|
|
531
558
|
} elsif ($format eq 'CSV') {
|
|
532
559
|
chomp;
|
|
533
|
-
my @vals =
|
|
560
|
+
my @vals = SplitCSV($_, $csvDelim);
|
|
534
561
|
#
|
|
535
562
|
# CSV format output of GPS/IMU POS system
|
|
536
563
|
# Date* - date in DD/MM/YYYY format
|
|
@@ -1557,8 +1584,7 @@ sub ConvertGeosync($$)
|
|
|
1557
1584
|
# Returns: UTC time string with fractional seconds
|
|
1558
1585
|
sub PrintFixTime($)
|
|
1559
1586
|
{
|
|
1560
|
-
my $time =
|
|
1561
|
-
my $fsec = int(($time - int($time)) * 1000);
|
|
1587
|
+
my $time = shift;
|
|
1562
1588
|
return Image::ExifTool::ConvertUnixTime($time, undef, 3) . ' UTC';
|
|
1563
1589
|
}
|
|
1564
1590
|
|
|
@@ -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.15';
|
|
16
16
|
|
|
17
17
|
sub MDItemLocalTime($);
|
|
18
18
|
sub ProcessATTR($$$);
|
|
@@ -364,6 +364,23 @@ sub MDItemLocalTime($)
|
|
|
364
364
|
return $val;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
+
#------------------------------------------------------------------------------
|
|
368
|
+
# Call system command, redirecting all I/O to /dev/null
|
|
369
|
+
# Inputs: system arguments
|
|
370
|
+
# Returns: system return code
|
|
371
|
+
sub System
|
|
372
|
+
{
|
|
373
|
+
my ($oldout, $olderr);
|
|
374
|
+
open($oldout, ">&STDOUT");
|
|
375
|
+
open($olderr, ">&STDERR");
|
|
376
|
+
open(STDOUT, '>', '/dev/null');
|
|
377
|
+
open(STDERR, '>', '/dev/null');
|
|
378
|
+
my $result = system(@_);
|
|
379
|
+
open(STDOUT, ">&", $oldout);
|
|
380
|
+
open(STDERR, ">&", $olderr);
|
|
381
|
+
return $result;
|
|
382
|
+
}
|
|
383
|
+
|
|
367
384
|
#------------------------------------------------------------------------------
|
|
368
385
|
# Set MacOS MDItem and XAttr tags from new tag values
|
|
369
386
|
# Inputs: 0) ExifTool ref, 1) file name, 2) list of tags to set
|
|
@@ -376,7 +393,7 @@ sub SetMacOSTags($$$)
|
|
|
376
393
|
my $tag;
|
|
377
394
|
|
|
378
395
|
foreach $tag (@$setTags) {
|
|
379
|
-
my ($nvHash, $
|
|
396
|
+
my ($nvHash, $attr, @cmd, $err, $silentErr);
|
|
380
397
|
my $val = $et->GetNewValue($tag, \$nvHash);
|
|
381
398
|
next unless $nvHash;
|
|
382
399
|
my $overwrite = $et->IsOverwriting($nvHash);
|
|
@@ -389,7 +406,6 @@ sub SetMacOSTags($$$)
|
|
|
389
406
|
}
|
|
390
407
|
}
|
|
391
408
|
if ($tag eq 'MDItemFSCreationDate' or $tag eq 'FileCreateDate') {
|
|
392
|
-
($f = $file) =~ s/'/'\\''/g;
|
|
393
409
|
# convert to local time if value has a time zone
|
|
394
410
|
if ($val =~ /[-+Z]/) {
|
|
395
411
|
my $time = Image::ExifTool::GetUnixTime($val, 1);
|
|
@@ -397,17 +413,15 @@ sub SetMacOSTags($$$)
|
|
|
397
413
|
$val =~ s/[-+].*//; # remove time zone
|
|
398
414
|
}
|
|
399
415
|
$val =~ s{(\d{4}):(\d{2}):(\d{2})}{$2/$3/$1}; # reformat for setfile
|
|
400
|
-
|
|
416
|
+
push @cmd, '/usr/bin/setfile', '-d', $val, $file;
|
|
401
417
|
} elsif ($tag eq 'MDItemUserTags') {
|
|
402
418
|
# (tested with "tag" version 0.9.0)
|
|
403
|
-
($f = $file) =~ s/'/'\\''/g;
|
|
404
419
|
my @vals = $et->GetNewValue($nvHash);
|
|
405
420
|
if ($overwrite < 0 and @{$$nvHash{DelValue}}) {
|
|
406
421
|
# delete specified tags
|
|
407
422
|
my @dels = @{$$nvHash{DelValue}};
|
|
408
|
-
s/'/'\\''/g foreach @dels;
|
|
409
423
|
my $del = join ',', @dels;
|
|
410
|
-
$err =
|
|
424
|
+
$err = System('/usr/local/bin/tag', '-r', $del, $file);
|
|
411
425
|
unless ($err) {
|
|
412
426
|
$et->VerboseValue("- $tag", $del);
|
|
413
427
|
$result = 1;
|
|
@@ -416,43 +430,39 @@ sub SetMacOSTags($$$)
|
|
|
416
430
|
}
|
|
417
431
|
unless (defined $err) {
|
|
418
432
|
# add new tags, or overwrite or delete existing tags
|
|
419
|
-
s/'/'\\''/g foreach @vals;
|
|
420
433
|
my $opt = $overwrite > 0 ? '-s' : '-a';
|
|
421
434
|
$val = @vals ? join(',', @vals) : '';
|
|
422
|
-
|
|
435
|
+
push @cmd, '/usr/local/bin/tag', $opt, $val, $file;
|
|
423
436
|
$et->VPrint(1," - $tag = (all)\n") if $overwrite > 0;
|
|
424
437
|
undef $val if $val eq '';
|
|
425
438
|
}
|
|
426
439
|
} elsif ($delXAttr{$tag}) {
|
|
427
|
-
|
|
428
|
-
$cmd = "/usr/bin/xattr -d $delXAttr{$tag} '${f}'";
|
|
440
|
+
push @cmd, '/usr/bin/xattr', '-d', $delXAttr{$tag}, $file;
|
|
429
441
|
$silentErr = 256; # (will get this error if attribute doesn't exist)
|
|
430
442
|
} else {
|
|
431
|
-
($f
|
|
432
|
-
$f =~ s/
|
|
443
|
+
my ($f, $v);
|
|
444
|
+
($f = $file) =~ s/([\\"])/\\$1/g; # escape backslashes and quotes for AppleScript
|
|
433
445
|
if ($tag eq 'MDItemFinderComment') {
|
|
434
446
|
# (write finder comment using osascript instead of xattr
|
|
435
447
|
# because it is more work to construct the necessary bplist)
|
|
436
448
|
$val = '' unless defined $val; # set to empty string instead of deleting
|
|
437
449
|
$v = $et->Encode($val, 'UTF8');
|
|
438
|
-
$v =~ s/(["
|
|
439
|
-
$v =~ s/'/'"'"'/g;
|
|
450
|
+
$v =~ s/([\\"])/\\$1/g;
|
|
440
451
|
$attr = 'comment';
|
|
441
452
|
} else { # $tag eq 'MDItemFSLabel'
|
|
442
453
|
$v = $val ? 8 - $val : 0; # convert from label to label index (0 for no label)
|
|
443
454
|
$attr = 'label index';
|
|
444
455
|
}
|
|
445
|
-
|
|
446
|
-
'tell application "Finder" to set $attr of file fp to "$v"
|
|
447
|
-
}
|
|
448
|
-
if (defined $cmd) {
|
|
449
|
-
$err = system $cmd . '>/dev/null 2>&1'; # (pipe all output to /dev/null)
|
|
456
|
+
push @cmd, '/usr/bin/osascript', '-e', qq(set fp to POSIX file "$f" as alias),
|
|
457
|
+
'-e', qq(tell application "Finder" to set $attr of file fp to "$v");
|
|
450
458
|
}
|
|
459
|
+
$err = System(@cmd) if @cmd;
|
|
451
460
|
if (not $err) {
|
|
452
461
|
$et->VerboseValue("+ $tag", $val) if defined $val;
|
|
453
462
|
$result = 1;
|
|
454
463
|
} elsif (not $silentErr or $err != $silentErr) {
|
|
455
|
-
$cmd
|
|
464
|
+
my $cmd = $cmd[0] || 'tag';
|
|
465
|
+
$cmd =~ s(.*/)();
|
|
456
466
|
$et->Warn(qq{Error $err running "$cmd" to set $tag});
|
|
457
467
|
$result = -1 unless $result;
|
|
458
468
|
}
|
|
@@ -498,6 +508,7 @@ sub ExtractMDItemTags($$)
|
|
|
498
508
|
$_ = '' if $_ eq '(null)';
|
|
499
509
|
s/^"// and s/"$//; # remove quotes if they exist
|
|
500
510
|
s/\\"/"/g; # un-escape quotes
|
|
511
|
+
s/\\\\/\\/g; # un-escape backslashes
|
|
501
512
|
$_ = $et->Decode($_, 'UTF8');
|
|
502
513
|
push @$val, $_;
|
|
503
514
|
next;
|