exiftool_vendored 12.99.0 → 13.02.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/Changes +56 -3
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/arg_files/exif2xmp.args +4 -0
- data/bin/arg_files/xmp2exif.args +4 -0
- data/bin/exiftool +82 -40
- data/bin/lib/Image/ExifTool/CBOR.pm +4 -1
- data/bin/lib/Image/ExifTool/Canon.pm +35 -26
- data/bin/lib/Image/ExifTool/Exif.pm +8 -9
- data/bin/lib/Image/ExifTool/FlashPix.pm +5 -9
- data/bin/lib/Image/ExifTool/Geolocation.dat +0 -0
- data/bin/lib/Image/ExifTool/Geotag.pm +6 -5
- data/bin/lib/Image/ExifTool/GoPro.pm +2 -2
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +2 -2
- data/bin/lib/Image/ExifTool/LNK.pm +1 -1
- data/bin/lib/Image/ExifTool/M2TS.pm +2 -2
- data/bin/lib/Image/ExifTool/MIE.pm +9 -3
- data/bin/lib/Image/ExifTool/MacOS.pm +2 -1
- data/bin/lib/Image/ExifTool/Nikon.pm +5 -2
- data/bin/lib/Image/ExifTool/PDF.pm +7 -3
- data/bin/lib/Image/ExifTool/PhaseOne.pm +2 -1
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +69 -7
- data/bin/lib/Image/ExifTool/TagLookup.pm +11 -8
- data/bin/lib/Image/ExifTool/TagNames.pod +33 -18
- data/bin/lib/Image/ExifTool/Text.pm +3 -2
- data/bin/lib/Image/ExifTool/Validate.pm +2 -2
- data/bin/lib/Image/ExifTool/Writer.pl +26 -55
- data/bin/lib/Image/ExifTool/XMP.pm +13 -3
- data/bin/lib/Image/ExifTool/XMPStruct.pl +1 -2
- data/bin/lib/Image/ExifTool.pm +167 -76
- data/bin/lib/Image/ExifTool.pod +42 -28
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +2 -2
data/bin/lib/Image/ExifTool.pm
CHANGED
@@ -29,7 +29,7 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes
|
|
29
29
|
%jpegMarker %specialTags %fileTypeLookup $testLen $exeDir
|
30
30
|
%static_vars $advFmtSelf);
|
31
31
|
|
32
|
-
$VERSION = '
|
32
|
+
$VERSION = '13.02';
|
33
33
|
$RELEASE = '';
|
34
34
|
@ISA = qw(Exporter);
|
35
35
|
%EXPORT_TAGS = (
|
@@ -126,6 +126,7 @@ sub MakeTiffHeader($$$$;$$);
|
|
126
126
|
# other subroutine definitions
|
127
127
|
sub SplitFileName($);
|
128
128
|
sub EncodeFileName($$;$);
|
129
|
+
sub WindowsLongPath($$);
|
129
130
|
sub Open($*$;$);
|
130
131
|
sub Exists($$;$);
|
131
132
|
sub IsDirectory($$);
|
@@ -740,7 +741,7 @@ my %fileDescription = (
|
|
740
741
|
OGV => 'video/ogg',
|
741
742
|
ONP => 'application/on1',
|
742
743
|
ORF => 'image/x-olympus-orf',
|
743
|
-
OTF => 'application/
|
744
|
+
OTF => 'application/font-otf',
|
744
745
|
PAGES=> 'application/x-iwork-pages-sffpages',
|
745
746
|
PBM => 'image/x-portable-bitmap',
|
746
747
|
PCD => 'image/x-photo-cd',
|
@@ -798,8 +799,8 @@ my %fileDescription = (
|
|
798
799
|
THMX => 'application/vnd.ms-officetheme',
|
799
800
|
TIFF => 'image/tiff',
|
800
801
|
Torrent => 'application/x-bittorrent',
|
801
|
-
TTC => 'application/
|
802
|
-
TTF => 'application/
|
802
|
+
TTC => 'application/font-ttf',
|
803
|
+
TTF => 'application/font-ttf',
|
803
804
|
TXT => 'text/plain',
|
804
805
|
VCard=> 'text/vcard',
|
805
806
|
VRD => 'application/octet-stream', #PH (NC)
|
@@ -1081,6 +1082,7 @@ my %xmpShorthandOpt = ( 0 => 'None', 1 => 'Shorthand', 2 => ['Shorthand','OneDes
|
|
1081
1082
|
# +-----------------------------------------------------+
|
1082
1083
|
# (Note: All options must exist in this lookup, even if undefined,
|
1083
1084
|
# to facilitate case-insensitive options. 'Group#' is handled specially)
|
1085
|
+
# (item 3 is a flag indicating the option is undocumented)
|
1084
1086
|
my @availableOptions = (
|
1085
1087
|
[ 'Binary', undef, 'flag to extract binary values even if tag not specified' ],
|
1086
1088
|
[ 'ByteOrder', undef, 'default byte order when creating EXIF information' ],
|
@@ -1098,7 +1100,12 @@ my @availableOptions = (
|
|
1098
1100
|
[ 'Compress', undef, 'flag to write new values as compressed if possible' ],
|
1099
1101
|
[ 'CoordFormat', undef, 'GPS lat/long coordinate format' ],
|
1100
1102
|
[ 'DateFormat', undef, 'format for date/time' ],
|
1103
|
+
[ 'Debug', undef, 'enable debugging output', 1 ], # (undocumented)
|
1101
1104
|
[ 'Duplicates', 1, 'flag to save duplicate tag values' ],
|
1105
|
+
# ("require Encode" hangs on my Windows 10 virtual machine running under MacOS if
|
1106
|
+
# the current working directory has a long path name. This problem hasn't been
|
1107
|
+
# seen on other Windows systems, so I'm leaving this option undocumented for now)
|
1108
|
+
[ 'EncodeHangs', undef, 'flag set to avoid using Encode if it hangs on your system', 1 ], # (undocumented)
|
1102
1109
|
[ 'Escape', undef, 'escape special characters' ],
|
1103
1110
|
[ 'Exclude', undef, 'tags to exclude' ],
|
1104
1111
|
[ 'ExtendedXMP', 1, 'strategy for reading extended XMP' ],
|
@@ -1130,10 +1137,10 @@ my @availableOptions = (
|
|
1130
1137
|
[ 'Lang', $defaultLang, 'localized language for descriptions etc' ],
|
1131
1138
|
[ 'LargeFileSupport', 1, 'flag indicating support of 64-bit file offsets' ],
|
1132
1139
|
[ 'LimitLongValues', 60, 'length limit for long values' ],
|
1133
|
-
[ 'List', undef, '[deprecated, use ListSplit and ListJoin instead]' ],
|
1140
|
+
[ 'List', undef, '[deprecated, use ListSplit and ListJoin instead]', 1 ],
|
1134
1141
|
[ 'ListItem', undef, 'used to return a specific item from lists' ],
|
1135
1142
|
[ 'ListJoin', ', ', 'join lists together with this separator' ],
|
1136
|
-
[ 'ListSep', ', ', '[deprecated, use ListSplit and ListJoin instead]' ],
|
1143
|
+
[ 'ListSep', ', ', '[deprecated, use ListSplit and ListJoin instead]', 1 ],
|
1137
1144
|
[ 'ListSplit', undef, 'regex for splitting list-type tag values when writing' ],
|
1138
1145
|
[ 'MakerNotes', undef, 'extract maker notes as a block' ],
|
1139
1146
|
[ 'MDItemTags', undef, 'extract MacOS metadata item tags' ],
|
@@ -1150,6 +1157,7 @@ my @availableOptions = (
|
|
1150
1157
|
[ 'QuickTimeUTC', undef, 'assume that QuickTime date/time tags are stored as UTC' ],
|
1151
1158
|
[ 'RequestAll', undef, 'extract all tags that must be specifically requested' ],
|
1152
1159
|
[ 'RequestTags', undef, 'extra tags to request (on top of those in the tag list)' ],
|
1160
|
+
[ 'SaveBin', undef, 'save binary values of tags' ],
|
1153
1161
|
[ 'SaveFormat', undef, 'save family 6 tag TIFF format' ],
|
1154
1162
|
[ 'SavePath', undef, 'save family 5 location path' ],
|
1155
1163
|
[ 'ScanForXMP', undef, 'flag to scan for XMP information in all files' ],
|
@@ -1165,11 +1173,12 @@ my @availableOptions = (
|
|
1165
1173
|
[ 'UserParam', { }, 'user parameters for additional user-defined tag values' ],
|
1166
1174
|
[ 'Validate', undef, 'perform additional validation' ],
|
1167
1175
|
[ 'Verbose', 0, 'print verbose messages (0-5, higher # = more verbose)' ],
|
1176
|
+
[ 'WindowsLongPath', undef, 'enable support for long pathnames (enables WindowsWideFile)' ],
|
1168
1177
|
[ 'WindowsWideFile', undef, 'force the use of Windows wide-character file routines' ], # (see forum15208)
|
1169
1178
|
[ 'WriteMode', 'wcg', 'enable all write modes by default' ],
|
1170
1179
|
[ 'XAttrTags', undef, 'extract MacOS extended attribute tags' ],
|
1171
1180
|
[ 'XMPAutoConv', 1, 'automatic conversion of unknown XMP tag values' ],
|
1172
|
-
[ 'XMPShorthand', 0, '[deprecated, use Compact=Shorthand instead]' ],
|
1181
|
+
[ 'XMPShorthand', 0, '[deprecated, use Compact=Shorthand instead]', 1 ],
|
1173
1182
|
);
|
1174
1183
|
|
1175
1184
|
# default family 0 group priority for writing
|
@@ -3328,8 +3337,8 @@ sub GetRequestedTags($)
|
|
3328
3337
|
# Inputs: 0) ExifTool object reference
|
3329
3338
|
# 1) tag key or tag name with optional group names (case sensitive)
|
3330
3339
|
# (or flattened tagInfo for getting field values, not part of public API)
|
3331
|
-
# 2) [optional] Value type: PrintConv, ValueConv, Both, Raw or Rational, the
|
3332
|
-
# is PrintConv or ValueConv, depending on the PrintConv option setting
|
3340
|
+
# 2) [optional] Value type: PrintConv, ValueConv, Both, Raw, Bin or Rational, the
|
3341
|
+
# default is PrintConv or ValueConv, depending on the PrintConv option setting
|
3333
3342
|
# 3) raw field value (not part of public API)
|
3334
3343
|
# Returns: Scalar context: tag value or undefined
|
3335
3344
|
# List context: list of values or empty list
|
@@ -3358,7 +3367,8 @@ sub GetValue($$;$)
|
|
3358
3367
|
}
|
3359
3368
|
# figure out what conversions to do
|
3360
3369
|
if ($type) {
|
3361
|
-
return $$self{
|
3370
|
+
return $$self{TAG_EXTRA}{$tag}{Rational} if $type eq 'Rational';
|
3371
|
+
return $$self{TAG_EXTRA}{$tag}{BinVal} if $type eq 'Bin';
|
3362
3372
|
} else {
|
3363
3373
|
$type = $$self{OPTIONS}{PrintConv} ? 'PrintConv' : 'ValueConv';
|
3364
3374
|
}
|
@@ -3702,9 +3712,10 @@ sub GetGroup($$;$)
|
|
3702
3712
|
$tag = $$tagInfo{Name};
|
3703
3713
|
# set flag so we don't get extra information for an extracted tag
|
3704
3714
|
$byTagInfo = 1;
|
3715
|
+
$ex = { };
|
3705
3716
|
} else {
|
3706
3717
|
$tagInfo = $$self{TAG_INFO}{$tag} || { };
|
3707
|
-
$ex = $$self{TAG_EXTRA}{$tag};
|
3718
|
+
$ex = $$self{TAG_EXTRA}{$tag} || { };
|
3708
3719
|
}
|
3709
3720
|
my $groups = $$tagInfo{Groups};
|
3710
3721
|
# fill in default groups unless already done
|
@@ -3723,32 +3734,30 @@ sub GetGroup($$;$)
|
|
3723
3734
|
if (defined $family and $family ne '-1') {
|
3724
3735
|
if ($family =~ /[^\d]/) {
|
3725
3736
|
@families = ($family =~ /\d+/g);
|
3726
|
-
return(
|
3737
|
+
return($$ex{G0} || $$groups{0}) unless @families;
|
3727
3738
|
$simplify = 1 unless $family =~ /^:/;
|
3728
3739
|
undef $family;
|
3729
3740
|
foreach (0..2) { $groups[$_] = $$groups{$_}; }
|
3730
3741
|
$noID = 1 if @families == 1 and $families[0] != 7;
|
3731
3742
|
} else {
|
3732
|
-
return(
|
3743
|
+
return($$ex{"G$family"} || $$groups{$family}) if $family == 0 or $family == 2;
|
3733
3744
|
$groups[1] = $$groups{1};
|
3734
3745
|
}
|
3735
3746
|
} else {
|
3736
|
-
return(
|
3747
|
+
return($$ex{G0} || $$groups{0}) unless wantarray;
|
3737
3748
|
foreach (0..2) { $groups[$_] = $$groups{$_}; }
|
3738
3749
|
}
|
3739
3750
|
$groups[3] = 'Main';
|
3740
|
-
$groups[4] = ($tag =~ /\((\d+)\)$/) ? "Copy$1" : '';
|
3751
|
+
$groups[4] = ($tag =~ /\((\d+)\)$/ and $1 ne '0') ? "Copy$1" : '';
|
3741
3752
|
# handle dynamic group names if necessary
|
3742
3753
|
unless ($byTagInfo) {
|
3743
|
-
if
|
3744
|
-
|
3745
|
-
|
3746
|
-
|
3747
|
-
|
3748
|
-
|
3749
|
-
|
3750
|
-
$groups[6] = $$ex{G6};
|
3751
|
-
}
|
3754
|
+
$groups[0] = $$ex{G0} if $$ex{G0};
|
3755
|
+
$groups[1] = $$ex{G1} =~ /^\+(.*)/ ? "$groups[1]$1" : $$ex{G1} if $$ex{G1};
|
3756
|
+
$groups[3] = 'Doc' . $$ex{G3} if $$ex{G3};
|
3757
|
+
$groups[5] = $$ex{G5} || $groups[1] if defined $$ex{G5};
|
3758
|
+
if (defined $$ex{G6}) {
|
3759
|
+
$groups[5] = '' unless defined $groups[5]; # (can't leave a hole in the array)
|
3760
|
+
$groups[6] = $$ex{G6};
|
3752
3761
|
}
|
3753
3762
|
if ($$ex{G8}) {
|
3754
3763
|
$groups[7] = '';
|
@@ -3921,12 +3930,9 @@ COMPOSITE_TAG:
|
|
3921
3930
|
$key = "$reqTag ($i)";
|
3922
3931
|
}
|
3923
3932
|
@keys = $self->GroupMatches($reqGroup, \@keys) if defined $reqGroup;
|
3924
|
-
|
3925
|
-
|
3926
|
-
|
3927
|
-
# priority tag will win in the case of duplicates within a doc
|
3928
|
-
$$cacheTag[$$ex{$_} ? $$ex{$_}{G3} || 0 : 0] = $_ foreach reverse @keys;
|
3929
|
-
}
|
3933
|
+
# loop through tags in reverse order of precedence so the higher
|
3934
|
+
# priority tag will win in the case of duplicates within a doc
|
3935
|
+
$$cacheTag[$$self{TAG_EXTRA}{$_}{G3} || 0] = $_ foreach reverse @keys;
|
3930
3936
|
}
|
3931
3937
|
# (set $reqTag to a bogus key if not found)
|
3932
3938
|
$reqTag = $$cacheTag[$doc] || "$reqTag (0)";
|
@@ -4218,9 +4224,7 @@ sub Init($)
|
|
4218
4224
|
local $_;
|
4219
4225
|
my $self = shift;
|
4220
4226
|
# delete all DataMember variables (lower-case names)
|
4221
|
-
foreach
|
4222
|
-
/[a-z]/ and delete $$self{$_};
|
4223
|
-
}
|
4227
|
+
delete $$self{$_} foreach grep /[a-z]/, keys %$self;
|
4224
4228
|
undef %static_vars; # clear all static variables
|
4225
4229
|
delete $$self{FOUND_TAGS}; # list of found tags
|
4226
4230
|
delete $$self{EXIF_DATA}; # the EXIF data block
|
@@ -4235,7 +4239,6 @@ sub Init($)
|
|
4235
4239
|
$$self{FILE_ORDER} = { }; # * hash of tag order in file ('*' = based on tag key)
|
4236
4240
|
$$self{VALUE} = { }; # * hash of raw tag values
|
4237
4241
|
$$self{BOTH} = { }; # * hash for Value/PrintConv values of Require'd tags
|
4238
|
-
$$self{RATIONAL} = { }; # * hash of original rational components
|
4239
4242
|
$$self{TAG_INFO} = { }; # * hash of tag information
|
4240
4243
|
$$self{TAG_EXTRA} = { }; # * hash of extra tag information (dynamic group names)
|
4241
4244
|
$$self{PRIORITY} = { }; # * priority of current tags
|
@@ -4468,11 +4471,7 @@ sub DoneExtract($)
|
|
4468
4471
|
my $err = $$altExifTool{VALUE}{Error};
|
4469
4472
|
$err and $self->Warn(qq{$err "$fileName"});
|
4470
4473
|
# set family 8 group name for all tags
|
4471
|
-
foreach
|
4472
|
-
my $ex = $$altExifTool{TAG_EXTRA}{$_};
|
4473
|
-
$ex or $ex = $$altExifTool{TAG_EXTRA}{$_} = { };
|
4474
|
-
$$ex{G8} = $g8;
|
4475
|
-
}
|
4474
|
+
$$altExifTool{TAG_EXTRA}{$_}{G8} = $g8 foreach keys %{$$altExifTool{VALUE}};
|
4476
4475
|
# prepare our sorted list of found tags
|
4477
4476
|
$$altExifTool{FoundTags} = [ reverse sort keys %{$$altExifTool{VALUE}} ];
|
4478
4477
|
$$altExifTool{DID_EXTRACT} = 1;
|
@@ -4614,36 +4613,125 @@ sub SplitFileName($)
|
|
4614
4613
|
|
4615
4614
|
#------------------------------------------------------------------------------
|
4616
4615
|
# Encode file name for calls to system i/o routines
|
4617
|
-
# Inputs: 0) ExifTool ref, 1) file name in
|
4616
|
+
# Inputs: 0) ExifTool ref, 1) file name in CharsetFileName encoding, 2) flag to force conversion
|
4618
4617
|
# Returns: true if Windows Unicode routines should be used (in which case
|
4619
4618
|
# the file name will be encoded as a null-terminated UTF-16LE string)
|
4620
4619
|
sub EncodeFileName($$;$)
|
4621
4620
|
{
|
4622
4621
|
my ($self, $file, $force) = @_;
|
4623
4622
|
my $enc = $$self{OPTIONS}{CharsetFileName};
|
4624
|
-
$
|
4625
|
-
if ($
|
4626
|
-
|
4627
|
-
|
4628
|
-
if (
|
4629
|
-
|
4630
|
-
|
4631
|
-
# recode as UTF-16LE and add null terminator
|
4632
|
-
$_[1] = $self->Decode($file, $enc, undef, 'UTF16', 'II') . "\0\0";
|
4633
|
-
return 1;
|
4634
|
-
}
|
4635
|
-
$self->WarnOnce('Install Win32API::File for Windows Unicode file support');
|
4623
|
+
my $hasSpecialChars;
|
4624
|
+
if ($file =~ /[\x80-\xff]/) {
|
4625
|
+
$hasSpecialChars = 1;
|
4626
|
+
if (not $enc and $^O eq 'MSWin32') {
|
4627
|
+
if (IsUTF8(\$file) < 0) {
|
4628
|
+
$self->WarnOnce('FileName encoding must be specified') if not defined $enc;
|
4629
|
+
return 0;
|
4636
4630
|
} else {
|
4637
|
-
|
4638
|
-
|
4631
|
+
$enc = 'UTF8'; # assume UTF8
|
4632
|
+
}
|
4633
|
+
}
|
4634
|
+
}
|
4635
|
+
$force = 1 if $$self{OPTIONS}{WindowsWideFile} or $$self{OPTIONS}{WindowsLongPath};
|
4636
|
+
if ($hasSpecialChars or $force) {
|
4637
|
+
$enc or $enc = 'UTF8';
|
4638
|
+
if ($^O eq 'MSWin32') {
|
4639
|
+
local $SIG{'__WARN__'} = \&SetWarning;
|
4640
|
+
if (eval { require Win32API::File }) {
|
4641
|
+
$file = $self->WindowsLongPath($file) if $$self{OPTIONS}{WindowsLongPath};
|
4642
|
+
# recode as UTF-16LE and add null terminator
|
4643
|
+
$_[1] = $self->Decode($file, $enc, undef, 'UTF16', 'II') . "\0\0";
|
4644
|
+
return 1;
|
4639
4645
|
}
|
4646
|
+
$self->WarnOnce('Install Win32API::File for Windows wide/long file name support');
|
4647
|
+
} elsif ($enc ne 'UTF8') {
|
4648
|
+
# recode as UTF-8 for other platforms if necessary
|
4649
|
+
$_[1] = $self->Decode($file, $enc, undef, 'UTF8');
|
4640
4650
|
}
|
4641
|
-
} elsif ($^O eq 'MSWin32' and $file =~ /[\x80-\xff]/ and not defined $enc) {
|
4642
|
-
$self->WarnOnce('FileName encoding not specified') if IsUTF8(\$file) < 0;
|
4643
4651
|
}
|
4644
4652
|
return 0;
|
4645
4653
|
}
|
4646
4654
|
|
4655
|
+
#------------------------------------------------------------------------------
|
4656
|
+
# Rebuild a path as an absolute long path to be usable in Windows system calls
|
4657
|
+
# Inputs: 0) ExifTool ref, 1) path string
|
4658
|
+
# Returns: normalized long path
|
4659
|
+
# Note: this should only be called for Windows systems
|
4660
|
+
# References:
|
4661
|
+
# - https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats
|
4662
|
+
# - https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
|
4663
|
+
sub WindowsLongPath($$)
|
4664
|
+
{
|
4665
|
+
my ($self, $path) = @_;
|
4666
|
+
my $debug = $$self{OPTIONS}{Debug};
|
4667
|
+
my $out = $$self{OPTIONS}{TextOut};
|
4668
|
+
my @fullParts;
|
4669
|
+
my $prefixLen = 0;
|
4670
|
+
|
4671
|
+
$debug and print $out "WindowsLongPath input : $path\n";
|
4672
|
+
$path =~ tr(/)(\\); # convert slashes to backslashes
|
4673
|
+
my @pathParts = split /\\/, $path;
|
4674
|
+
|
4675
|
+
if ($path =~ /^\\\\\?\\/ or # already a device path in the format we want
|
4676
|
+
$path =~ s/^\\\\\.\\/\\\\?\\/) # convert //./ to //?/
|
4677
|
+
{
|
4678
|
+
# path is already long-path compatible
|
4679
|
+
$prefixLen = 3; # path already contains prefix of 3 parts ('', '' and '?')
|
4680
|
+
} elsif ($path =~ /[*?]/) {
|
4681
|
+
return $path; # do nothing because we don't support wildcards
|
4682
|
+
} elsif ($path =~ /^\\\\/) {
|
4683
|
+
# UNC path starts with two slashes change to "\\?\UNC\"
|
4684
|
+
splice @pathParts, 2, 0, '?', 'UNC';
|
4685
|
+
$prefixLen = (@pathParts > 6 ? 6 : @pathParts); # ('', '', '?', 'UNC', <server>, <share>)
|
4686
|
+
} elsif ($path =~ /^[a-z]:\\/i) {
|
4687
|
+
# path is already absolute but we need to add the device path prefix
|
4688
|
+
unshift @pathParts, '', '', '?';
|
4689
|
+
$prefixLen = 4;
|
4690
|
+
} elsif ({ eval { require Cwd } }) {
|
4691
|
+
my $drive;
|
4692
|
+
$drive = $1 if $pathParts[0] =~ s/^([a-z]:)//;
|
4693
|
+
my $cwd = Cwd::getdcwd($drive); # ($drive is undef for current working drive)
|
4694
|
+
$debug and print $out "WindowsLongPath getcwd: $cwd\n";
|
4695
|
+
@fullParts = split /[\\\/]/, $cwd;
|
4696
|
+
# UNC path starts with "\\", so first 2 elements are empty
|
4697
|
+
# --> shift and put UNC in first element.
|
4698
|
+
if (@fullParts > 1 and $fullParts[0] eq '' and $fullParts[1] eq '') {
|
4699
|
+
shift @fullParts;
|
4700
|
+
$fullParts[0] = 'UNC';
|
4701
|
+
unshift @fullParts, '', '', '?';
|
4702
|
+
$prefixLen = (@fullParts > 6 ? 6 : @fullParts);
|
4703
|
+
} else {
|
4704
|
+
$prefixLen = 1; # drive designator only
|
4705
|
+
}
|
4706
|
+
# if absolute path on current drive starts with "\"
|
4707
|
+
# just keep prefix and drop the rest of the cwd
|
4708
|
+
$#fullParts = $prefixLen - 1 if $pathParts[0] eq '';
|
4709
|
+
} else {
|
4710
|
+
$prefixLen = @pathParts; # (nothing more we can do)
|
4711
|
+
}
|
4712
|
+
# remove "." and ".." from path (not handled for device paths)
|
4713
|
+
my $part;
|
4714
|
+
foreach $part (@pathParts) {
|
4715
|
+
if ($part eq '.') {
|
4716
|
+
next;
|
4717
|
+
} elsif ($part eq '') {
|
4718
|
+
# only allow double slashes at start of path name (max 2)
|
4719
|
+
push @fullParts, $part if not @fullParts or (@fullParts == 1 and $fullParts[0] eq '');
|
4720
|
+
} elsif ($part eq '..') {
|
4721
|
+
# step up one directory, but not into the prefix
|
4722
|
+
pop @fullParts if @fullParts > $prefixLen;
|
4723
|
+
} else {
|
4724
|
+
push @fullParts, $part;
|
4725
|
+
}
|
4726
|
+
}
|
4727
|
+
$path = join '\\', @fullParts;
|
4728
|
+
# add device path prefix ("\\?\") if path length near the limit (the most
|
4729
|
+
# conservative limit I can find is 247, which is the limit on the directory name)
|
4730
|
+
$path = '\\\\?\\' . $path unless $prefixLen > 1 or length($path) <= 247;
|
4731
|
+
$debug and print $out "WindowsLongPath return: $path\n";
|
4732
|
+
return $path;
|
4733
|
+
}
|
4734
|
+
|
4647
4735
|
#------------------------------------------------------------------------------
|
4648
4736
|
# Modified perl open() routine to properly handle special characters in file names
|
4649
4737
|
# Inputs: 0) ExifTool ref, 1) filehandle, 2) filename,
|
@@ -4910,11 +4998,13 @@ sub ParseArguments($;@)
|
|
4910
4998
|
next if defined $$self{RAF};
|
4911
4999
|
# convert image data from UTF-8 to character stream if necessary
|
4912
5000
|
# (patches RHEL 3 UTF8 LANG problem)
|
4913
|
-
if (ref $arg eq 'SCALAR' and $] >= 5.006 and
|
4914
|
-
|
5001
|
+
if (ref $arg eq 'SCALAR' and $] >= 5.006 and ($$self{OPTIONS}{EncodeHangs} or
|
5002
|
+
eval { require Encode; Encode::is_utf8($$arg) } or $@))
|
4915
5003
|
{
|
5004
|
+
local $SIG{'__WARN__'} = \&SetWarning;
|
4916
5005
|
# repack by hand if Encode isn't available
|
4917
|
-
my $buff = $@ ? pack('C*',unpack($] < 5.010000 ?
|
5006
|
+
my $buff = ($$self{OPTIONS}{EncodeHangs} or $@) ? pack('C*',unpack($] < 5.010000 ?
|
5007
|
+
'U0C*' : 'C0C*', $$arg)) : Encode::encode('utf8', $$arg);
|
4918
5008
|
$arg = \$buff;
|
4919
5009
|
}
|
4920
5010
|
$$self{RAF} = File::RandomAccess->new($arg);
|
@@ -6322,10 +6412,12 @@ sub Filter($$$)
|
|
6322
6412
|
# Return printable value
|
6323
6413
|
# Inputs: 0) ExifTool object reference
|
6324
6414
|
# 1) value to print, 2) line length limit (undef defaults to 60, 0=unlimited)
|
6415
|
+
# Returns: Printable string
|
6325
6416
|
sub Printable($;$)
|
6326
6417
|
{
|
6327
6418
|
my ($self, $outStr, $maxLen) = @_;
|
6328
6419
|
return '(undef)' unless defined $outStr;
|
6420
|
+
ref $outStr eq 'SCALAR' and return '(Binary data '.length($$outStr).' bytes)';
|
6329
6421
|
$outStr =~ tr/\x01-\x1f\x7f-\xff/./;
|
6330
6422
|
$outStr =~ s/\x00//g;
|
6331
6423
|
my $verbose = $$self{OPTIONS}{Verbose};
|
@@ -8924,7 +9016,7 @@ sub HandleTag($$$$;%)
|
|
8924
9016
|
my $pfmt = $parms{Format};
|
8925
9017
|
my $tagInfo = $parms{TagInfo} || $self->GetTagInfo($tagTablePtr, $tag, \$val, $pfmt, $parms{Count});
|
8926
9018
|
my $dataPt = $parms{DataPt};
|
8927
|
-
my ($subdir, $format, $noTagInfo, $rational);
|
9019
|
+
my ($subdir, $format, $noTagInfo, $rational, $binVal);
|
8928
9020
|
|
8929
9021
|
if ($tagInfo) {
|
8930
9022
|
$subdir = $$tagInfo{SubDirectory};
|
@@ -8948,6 +9040,7 @@ sub HandleTag($$$$;%)
|
|
8948
9040
|
} else {
|
8949
9041
|
$val = substr($$dataPt, $start, $size);
|
8950
9042
|
}
|
9043
|
+
$binVal = substr($$dataPt, $start, $size) if $$self{OPTIONS}{SaveBin};
|
8951
9044
|
} else {
|
8952
9045
|
$self->Warn("Error extracting value for $$tagInfo{Name}");
|
8953
9046
|
return undef;
|
@@ -9030,8 +9123,11 @@ sub HandleTag($$$$;%)
|
|
9030
9123
|
return undef unless $$tagInfo{Writable};
|
9031
9124
|
}
|
9032
9125
|
my $key = $self->FoundTag($tagInfo, $val);
|
9033
|
-
|
9034
|
-
|
9126
|
+
if (defined $key) {
|
9127
|
+
# save original components of rational numbers and original binary value
|
9128
|
+
$$self{TAG_EXTRA}{$key}{Rational} = $rational if defined $rational;
|
9129
|
+
$$self{TAG_EXTRA}{$key}{BinVal} = $binVal if defined $binVal;
|
9130
|
+
}
|
9035
9131
|
return $key;
|
9036
9132
|
}
|
9037
9133
|
return undef;
|
@@ -9142,9 +9238,7 @@ sub FoundTag($$$;@)
|
|
9142
9238
|
# a Warning tag because they may be added by ValueConv, which could be confusing)
|
9143
9239
|
my $oldPriority = $$self{PRIORITY}{$tag};
|
9144
9240
|
unless ($oldPriority) {
|
9145
|
-
if ($$self{DOC_NUM} or not $$self{TAG_EXTRA}{$tag}
|
9146
|
-
not $$self{TAG_EXTRA}{$tag}{G3})
|
9147
|
-
{
|
9241
|
+
if ($$self{DOC_NUM} or $tag eq 'Warning' or not $$self{TAG_EXTRA}{$tag}{G3}) {
|
9148
9242
|
$oldPriority = 1;
|
9149
9243
|
} else {
|
9150
9244
|
$oldPriority = 0; # don't promote sub-document tag over main document
|
@@ -9162,8 +9256,7 @@ sub FoundTag($$$;@)
|
|
9162
9256
|
} else {
|
9163
9257
|
$priority = 1; # the normal default
|
9164
9258
|
}
|
9165
|
-
if ($priority >= $oldPriority and (not $$self{DOC_NUM} or
|
9166
|
-
($$self{TAG_EXTRA}{$tag} and $$self{TAG_EXTRA}{$tag}{G3} and
|
9259
|
+
if ($priority >= $oldPriority and (not $$self{DOC_NUM} or ($$self{TAG_EXTRA}{$tag}{G3} and
|
9167
9260
|
$$self{DOC_NUM} eq $$self{TAG_EXTRA}{$tag}{G3})) and not $noListDel)
|
9168
9261
|
{
|
9169
9262
|
# move existing tag out of the way since this tag is higher priority
|
@@ -9172,12 +9265,8 @@ sub FoundTag($$$;@)
|
|
9172
9265
|
$$valueHash{$nextTag} = $$valueHash{$tag};
|
9173
9266
|
$$self{FILE_ORDER}{$nextTag} = $$self{FILE_ORDER}{$tag};
|
9174
9267
|
my $oldInfo = $$self{TAG_INFO}{$nextTag} = $$self{TAG_INFO}{$tag};
|
9175
|
-
|
9176
|
-
|
9177
|
-
$$self{$_}{$nextTag} = $$self{$_}{$tag};
|
9178
|
-
delete $$self{$_}{$tag};
|
9179
|
-
}
|
9180
|
-
}
|
9268
|
+
$$self{TAG_EXTRA}{$nextTag} = $$self{TAG_EXTRA}{$tag};
|
9269
|
+
$$self{TAG_EXTRA}{$tag} = { };
|
9181
9270
|
delete $$self{BOTH}{$tag};
|
9182
9271
|
# update tag key for list if necessary
|
9183
9272
|
$$self{LIST_TAGS}{$oldInfo} = $nextTag if $$self{LIST_TAGS}{$oldInfo};
|
@@ -9202,6 +9291,7 @@ sub FoundTag($$$;@)
|
|
9202
9291
|
$$valueHash{$tag} = $value;
|
9203
9292
|
$$self{FILE_ORDER}{$tag} = ++$$self{NUM_FOUND};
|
9204
9293
|
$$self{TAG_INFO}{$tag} = $tagInfo;
|
9294
|
+
$$self{TAG_EXTRA}{$tag} = { } unless $$self{TAG_EXTRA}{$tag};
|
9205
9295
|
# set dynamic groups 0, 1 and 3 if necessary
|
9206
9296
|
$$self{TAG_EXTRA}{$tag}{G0} = $grps[0] if $grps[0];
|
9207
9297
|
$$self{TAG_EXTRA}{$tag}{G1} = $grps[1] if $grps[1];
|
@@ -9260,7 +9350,6 @@ sub DeleteTag($$)
|
|
9260
9350
|
delete $$self{TAG_INFO}{$tag};
|
9261
9351
|
delete $$self{TAG_EXTRA}{$tag};
|
9262
9352
|
delete $$self{PRIORITY}{$tag};
|
9263
|
-
delete $$self{RATIONAL}{$tag};
|
9264
9353
|
delete $$self{BOTH}{$tag};
|
9265
9354
|
}
|
9266
9355
|
|
@@ -9496,7 +9585,7 @@ sub ProcessBinaryData($$$)
|
|
9496
9585
|
$increment = $formatSize{$defaultFormat};
|
9497
9586
|
}
|
9498
9587
|
# prepare list of tag numbers to extract
|
9499
|
-
my (@tags, $topIndex);
|
9588
|
+
my (@tags, $topIndex, $binVal);
|
9500
9589
|
if ($unknown > 1 and defined $$tagTablePtr{FIRST_ENTRY}) {
|
9501
9590
|
# don't create a stupid number of tags if data is huge
|
9502
9591
|
my $sizeLimit = $size < 65536 ? $size : 65536;
|
@@ -9636,6 +9725,7 @@ sub ProcessBinaryData($$$)
|
|
9636
9725
|
$val = $self->Decode($val, 'UCS2') if $format eq 'ustring' or $format eq 'ustr32';
|
9637
9726
|
$val =~ s/\0.*//s unless $format eq 'undef'; # truncate at null
|
9638
9727
|
}
|
9728
|
+
$binVal = substr($$dataPt, $entry+$dirStart, $count) if $$self{OPTIONS}{SaveBin};
|
9639
9729
|
$wasVar = 1;
|
9640
9730
|
# save variable size data if required for writing
|
9641
9731
|
if ($$dirInfo{VarFormatData}) {
|
@@ -9757,7 +9847,8 @@ sub ProcessBinaryData($$$)
|
|
9757
9847
|
my $key = $self->FoundTag($tagInfo,$val);
|
9758
9848
|
$$self{BASE} = $oldBase if defined $oldBase;
|
9759
9849
|
if ($key) {
|
9760
|
-
$$self{
|
9850
|
+
$$self{TAG_EXTRA}{$key}{Rational} = $rational if defined $rational;
|
9851
|
+
$$self{TAG_EXTRA}{$key}{BinVal} = $binVal if defined $binVal;
|
9761
9852
|
} else {
|
9762
9853
|
# don't increment nextIndex if we didn't extract a tag
|
9763
9854
|
$nextIndex = $saveNextIndex if defined $saveNextIndex;
|
data/bin/lib/Image/ExifTool.pod
CHANGED
@@ -520,9 +520,9 @@ set to undef to pass through EXIF "ASCII" values without recoding. Set to
|
|
520
520
|
=item CharsetFileName
|
521
521
|
|
522
522
|
External character set used for file names passed to ExifTool functions.
|
523
|
-
|
524
|
-
|
525
|
-
|
523
|
+
Default is undef but "UTF8" is assumed in Windows if the file name contains
|
524
|
+
special characters and is valid UTF8. May also be set to an empty string to
|
525
|
+
avoid "encoding must be specified" warnings on Windows.
|
526
526
|
|
527
527
|
=item CharsetID3
|
528
528
|
|
@@ -981,7 +981,7 @@ normally. Currently this feature applies only to GM PDR data (see
|
|
981
981
|
L<Image::ExifTool::TagNames/GM Tags>). Setting this option automatically
|
982
982
|
sets L</IgnoreTags> to "all", and L</ExtractEmbedded> to 1. Default is
|
983
983
|
undef.
|
984
|
-
|
984
|
+
|
985
985
|
=item QuickTimeHandler
|
986
986
|
|
987
987
|
Flag set to add an 'mdir' Handler to a newly created Meta box when adding
|
@@ -1028,6 +1028,11 @@ current RequestTags list. Groups are requested by adding a colon after the
|
|
1028
1028
|
name (eg. "MacOS:"). Names are converted to lower case as they are added to
|
1029
1029
|
the list. Default is undef.
|
1030
1030
|
|
1031
|
+
=item SaveBin
|
1032
|
+
|
1033
|
+
Flag to save binary values of tags, accessible through calls to L</GetValue>
|
1034
|
+
with a value type of "Bin".
|
1035
|
+
|
1031
1036
|
=item SaveFormat
|
1032
1037
|
|
1033
1038
|
Flag to save EXIF/TIFF format type as the family 6 group name when
|
@@ -1176,13 +1181,17 @@ details about the tags. Level 3 adds a hex dump of the tag data, but with
|
|
1176
1181
|
limits on the number of bytes dumped. Levels 4 and 5 remove the dump limit
|
1177
1182
|
on tag values and JPEG segment data respectively.
|
1178
1183
|
|
1184
|
+
=item WindowsLongPath
|
1185
|
+
|
1186
|
+
Support long path names in Windows. Enabling this option automatically
|
1187
|
+
enables the WindowsWideFile feature.
|
1188
|
+
|
1179
1189
|
=item WindowsWideFile
|
1180
1190
|
|
1181
|
-
Force the use of wide-character Windows I/O functions
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
path contains Unicode characters.
|
1191
|
+
Force the use of wide-character Windows I/O functions. This may be
|
1192
|
+
necessary when files are on a network drive and the current directory name
|
1193
|
+
contains Unicode characters. By default, the wide-character functions are
|
1194
|
+
used only if the specified file path contains Unicode characters.
|
1186
1195
|
|
1187
1196
|
=item WriteMode
|
1188
1197
|
|
@@ -1257,8 +1266,9 @@ CharsetPhotoshop, CharsetQuickTime, CharsetRIFF, Composite, ExtendedXMP,
|
|
1257
1266
|
ExtractEmbedded, FastScan, FixBase, HtmlDump, HtmlDumpBase, IgnoreGroups,
|
1258
1267
|
IgnoreMinorErrors, IgnoreTags, Lang, LargeFileSupport, MakerNotes,
|
1259
1268
|
MDItemTags, NoPDFList, Password, QuickTimeUTC (enforced 1904 time zero),
|
1260
|
-
RequestAll, RequestTags, SaveFormat, SavePath, ScanForXMP, Struct,
|
1261
|
-
Unknown, Verbose, WindowsWideFile, XAttrTags and
|
1269
|
+
RequestAll, RequestTags, SaveBin, SaveFormat, SavePath, ScanForXMP, Struct,
|
1270
|
+
TextOut, Unknown, Verbose, WindowsLongPath, WindowsWideFile, XAttrTags and
|
1271
|
+
XMPAutoConv.
|
1262
1272
|
|
1263
1273
|
=item Return Value:
|
1264
1274
|
|
@@ -1397,7 +1407,8 @@ The following ExifTool options are effective in the call to L</WriteInfo>:
|
|
1397
1407
|
|
1398
1408
|
ByteOrder, Charset, CharsetEXIF, CharsetFileName, CharsetIPTC, Compact,
|
1399
1409
|
Compress, FixBase, IgnoreMinorErrors, NoMultiExif, NoPDFList, Password,
|
1400
|
-
QuickTimeHandler, QuickTimePad, Verbose, WindowsWideFile
|
1410
|
+
QuickTimeHandler, QuickTimePad, Verbose, WindowsLongPath, WindowsWideFile
|
1411
|
+
and WriteMode.
|
1401
1412
|
|
1402
1413
|
=head2 GetTagList
|
1403
1414
|
|
@@ -1535,14 +1546,15 @@ StrictDate and TimeZone.
|
|
1535
1546
|
|
1536
1547
|
1) Tag key, or case-sensitive tag name with optional group prefix(es)
|
1537
1548
|
|
1538
|
-
2) [optional] Value type: 'PrintConv', 'ValueConv', 'Both', 'Raw' or
|
1549
|
+
2) [optional] Value type: 'PrintConv', 'ValueConv', 'Both', 'Raw', 'Bin' or
|
1539
1550
|
'Rational'
|
1540
1551
|
|
1541
1552
|
The default value type is 'PrintConv' if the PrintConv option is set,
|
1542
1553
|
otherwise the default is 'ValueConv'. A value type of 'Both' returns both
|
1543
|
-
ValueConv and PrintConv values as a list. '
|
1544
|
-
|
1545
|
-
|
1554
|
+
ValueConv and PrintConv values as a list. 'Raw' returns the raw decoded tag
|
1555
|
+
value. 'Bin' returns the original binary data for EXIF tags if the
|
1556
|
+
L</SaveBin> option was set. 'Rational' returns the raw rational value as a
|
1557
|
+
string fraction for rational types, or undef for other types.
|
1546
1558
|
|
1547
1559
|
=item Return Values:
|
1548
1560
|
|
@@ -2394,7 +2406,8 @@ Get a list of available API options. (See L</Options> for option details.)
|
|
2394
2406
|
=item Return Values:
|
2395
2407
|
|
2396
2408
|
Reference to list of available options. Each entry in the list is a list
|
2397
|
-
reference with
|
2409
|
+
reference with 4 items: 0=Option name, 1=Default value, 2=Description,
|
2410
|
+
3=flag set if option is undocumented.
|
2398
2411
|
|
2399
2412
|
my $opts = Image::ExifTool::<b>AvailableOptions</b>();
|
2400
2413
|
foreach (@$opts) {
|
@@ -2553,17 +2566,18 @@ Real-PROP, Real-RA3, Real-RA4, Real-RA5, Real-RJMD, Reconyx, Red, Ricoh,
|
|
2553
2566
|
SPIFF, SR2, SR2DataIFD, SR2SubIFD, SRF#, SVG, Samsung, Sanyo, Scalado,
|
2554
2567
|
Sigma, SigmaRaw, Sony, SonyIDC, Stim, SubIFD, System, Theora, Torrent,
|
2555
2568
|
Track#, UserData, VCalendar, VCard, VNote, Version0, Vorbis, WTV, XML, XMP,
|
2556
|
-
XMP-DICOM, XMP-Device, XMP-GAudio, XMP-GCamera, XMP-
|
2557
|
-
XMP-
|
2558
|
-
XMP-
|
2559
|
-
XMP-
|
2560
|
-
XMP-
|
2561
|
-
XMP-
|
2562
|
-
XMP-
|
2563
|
-
XMP-
|
2564
|
-
XMP-
|
2565
|
-
XMP-
|
2566
|
-
XMP-
|
2569
|
+
XMP-DICOM, XMP-Device, XMP-GAudio, XMP-GCamera, XMP-GContainer,
|
2570
|
+
XMP-GCreations, XMP-GDepth, XMP-GFocus, XMP-GImage, XMP-GPano,
|
2571
|
+
XMP-GSpherical, XMP-LImage, XMP-MP, XMP-MP1, XMP-PixelLive, XMP-aas,
|
2572
|
+
XMP-acdsee, XMP-acdsee-rs, XMP-album, XMP-apple-fi, XMP-ast, XMP-aux,
|
2573
|
+
XMP-cc, XMP-cell, XMP-crd, XMP-creatorAtom, XMP-crs, XMP-dc, XMP-dex,
|
2574
|
+
XMP-digiKam, XMP-drone-dji, XMP-dwc, XMP-et, XMP-exif, XMP-exifEX,
|
2575
|
+
XMP-expressionmedia, XMP-extensis, XMP-fpv, XMP-getty, XMP-hdr, XMP-hdrgm,
|
2576
|
+
XMP-ics, XMP-iptcCore, XMP-iptcExt, XMP-lr, XMP-mediapro, XMP-microsoft,
|
2577
|
+
XMP-mwg-coll, XMP-mwg-kw, XMP-mwg-rs, XMP-nine, XMP-panorama, XMP-pdf,
|
2578
|
+
XMP-pdfx, XMP-photomech, XMP-photoshop, XMP-plus, XMP-pmi, XMP-prism,
|
2579
|
+
XMP-prl, XMP-prm, XMP-pur, XMP-rdf, XMP-sdc, XMP-swf, XMP-tiff, XMP-x,
|
2580
|
+
XMP-xmp, XMP-xmpBJ, XMP-xmpDM, XMP-xmpDSA, XMP-xmpMM, XMP-xmpNote,
|
2567
2581
|
XMP-xmpPLUS, XMP-xmpRights, XMP-xmpTPg, ZIP, iTunes
|
2568
2582
|
|
2569
2583
|
=item Family 2 (Category):
|