exiftool_vendored 12.25.0 → 12.35.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 +174 -7
- data/bin/MANIFEST +11 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +44 -43
- data/bin/arg_files/xmp2exif.args +2 -1
- data/bin/config_files/convert_regions.config +25 -14
- data/bin/config_files/example.config +1 -1
- data/bin/exiftool +118 -92
- data/bin/fmt_files/gpx.fmt +1 -1
- data/bin/fmt_files/gpx_wpt.fmt +1 -1
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +16 -3
- data/bin/lib/Image/ExifTool/CBOR.pm +331 -0
- data/bin/lib/Image/ExifTool/Canon.pm +52 -20
- data/bin/lib/Image/ExifTool/Charset.pm +2 -0
- data/bin/lib/Image/ExifTool/DPX.pm +13 -2
- data/bin/lib/Image/ExifTool/Exif.pm +107 -8
- data/bin/lib/Image/ExifTool/FLIR.pm +33 -8
- data/bin/lib/Image/ExifTool/FlashPix.pm +35 -10
- data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -0
- data/bin/lib/Image/ExifTool/Geotag.pm +13 -2
- data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +96 -4
- data/bin/lib/Image/ExifTool/ID3.pm +15 -3
- data/bin/lib/Image/ExifTool/JPEG.pm +68 -2
- data/bin/lib/Image/ExifTool/JSON.pm +7 -3
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +164 -36
- data/bin/lib/Image/ExifTool/LIF.pm +153 -0
- data/bin/lib/Image/ExifTool/Lang/nl.pm +60 -59
- data/bin/lib/Image/ExifTool/M2TS.pm +103 -7
- data/bin/lib/Image/ExifTool/MIE.pm +2 -1
- data/bin/lib/Image/ExifTool/MRC.pm +1 -1
- data/bin/lib/Image/ExifTool/MacOS.pm +2 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +50 -6
- data/bin/lib/Image/ExifTool/NikonSettings.pm +10 -2
- data/bin/lib/Image/ExifTool/Olympus.pm +9 -2
- data/bin/lib/Image/ExifTool/Other.pm +93 -0
- data/bin/lib/Image/ExifTool/PDF.pm +11 -12
- data/bin/lib/Image/ExifTool/PNG.pm +7 -6
- data/bin/lib/Image/ExifTool/Panasonic.pm +14 -2
- data/bin/lib/Image/ExifTool/Pentax.pm +28 -5
- data/bin/lib/Image/ExifTool/Photoshop.pm +6 -0
- data/bin/lib/Image/ExifTool/QuickTime.pm +123 -25
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +203 -121
- data/bin/lib/Image/ExifTool/README +9 -2
- data/bin/lib/Image/ExifTool/RIFF.pm +7 -2
- data/bin/lib/Image/ExifTool/Samsung.pm +47 -10
- data/bin/lib/Image/ExifTool/Sony.pm +113 -42
- data/bin/lib/Image/ExifTool/TagLookup.pm +4599 -4451
- data/bin/lib/Image/ExifTool/TagNames.pod +276 -41
- data/bin/lib/Image/ExifTool/Torrent.pm +18 -11
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
- data/bin/lib/Image/ExifTool/WritePNG.pl +2 -0
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +21 -4
- data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
- data/bin/lib/Image/ExifTool/Writer.pl +47 -2
- data/bin/lib/Image/ExifTool/XMP.pm +32 -12
- data/bin/lib/Image/ExifTool/XMP2.pl +5 -2
- data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
- data/bin/lib/Image/ExifTool/ZISRAW.pm +121 -2
- data/bin/lib/Image/ExifTool.pm +153 -52
- data/bin/lib/Image/ExifTool.pod +70 -60
- data/bin/perl-Image-ExifTool.spec +43 -42
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +6 -3
@@ -13,10 +13,11 @@ package Image::ExifTool::Torrent;
|
|
13
13
|
use strict;
|
14
14
|
use vars qw($VERSION);
|
15
15
|
use Image::ExifTool qw(:DataAccess :Utils);
|
16
|
+
use Image::ExifTool::XMP;
|
16
17
|
|
17
|
-
$VERSION = '1.
|
18
|
+
$VERSION = '1.05';
|
18
19
|
|
19
|
-
sub ReadBencode(
|
20
|
+
sub ReadBencode($$$);
|
20
21
|
sub ExtractTags($$$;$$@);
|
21
22
|
|
22
23
|
# tags extracted from BitTorrent files
|
@@ -99,12 +100,12 @@ sub ReadMore($$)
|
|
99
100
|
|
100
101
|
#------------------------------------------------------------------------------
|
101
102
|
# Read bencoded value
|
102
|
-
# Inputs: 0) input file,
|
103
|
+
# Inputs: 0) ExifTool ref, 1) input file, 2) buffer (pos must be set to current position)
|
103
104
|
# Returns: HASH ref, ARRAY ref, SCALAR ref, SCALAR, or undef on error or end of data
|
104
105
|
# Notes: Sets BencodeError element of RAF on any error
|
105
|
-
sub ReadBencode(
|
106
|
+
sub ReadBencode($$$)
|
106
107
|
{
|
107
|
-
my ($raf, $dataPt) = @_;
|
108
|
+
my ($et, $raf, $dataPt) = @_;
|
108
109
|
|
109
110
|
# read more if necessary (keep a minimum of 64 bytes in the buffer)
|
110
111
|
my $pos = pos($$dataPt);
|
@@ -123,21 +124,21 @@ sub ReadBencode($$)
|
|
123
124
|
} elsif ($tok eq 'd') { # dictionary
|
124
125
|
$val = { };
|
125
126
|
for (;;) {
|
126
|
-
my $k = ReadBencode($raf, $dataPt);
|
127
|
+
my $k = ReadBencode($et, $raf, $dataPt);
|
127
128
|
last unless defined $k;
|
128
129
|
# the key must be a byte string
|
129
130
|
if (ref $k) {
|
130
131
|
ref $k ne 'SCALAR' and $$raf{BencodeError} = 'Bad dictionary key', last;
|
131
132
|
$k = $$k;
|
132
133
|
}
|
133
|
-
my $v = ReadBencode($raf, $dataPt);
|
134
|
+
my $v = ReadBencode($et, $raf, $dataPt);
|
134
135
|
last unless defined $v;
|
135
136
|
$$val{$k} = $v;
|
136
137
|
}
|
137
138
|
} elsif ($tok eq 'l') { # list
|
138
139
|
$val = [ ];
|
139
140
|
for (;;) {
|
140
|
-
my $v = ReadBencode($raf, $dataPt);
|
141
|
+
my $v = ReadBencode($et, $raf, $dataPt);
|
141
142
|
last unless defined $v;
|
142
143
|
push @$val, $v;
|
143
144
|
}
|
@@ -165,8 +166,14 @@ sub ReadBencode($$)
|
|
165
166
|
}
|
166
167
|
if (defined $value) {
|
167
168
|
# return as binary data unless it is a reasonable-length ASCII string
|
168
|
-
if (length($value) > 256
|
169
|
+
if (length($value) > 256) {
|
169
170
|
$val = \$value;
|
171
|
+
} elsif ($value =~ /[^\t\x20-\x7e]/) {
|
172
|
+
if (Image::ExifTool::XMP::IsUTF8(\$value) >= 0) {
|
173
|
+
$val = $et->Decode($value, 'UTF8');
|
174
|
+
} else {
|
175
|
+
$val = \$value;
|
176
|
+
}
|
170
177
|
} else {
|
171
178
|
$val = $value;
|
172
179
|
}
|
@@ -206,7 +213,7 @@ sub ExtractTags($$$;$$@)
|
|
206
213
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, $id) or next;
|
207
214
|
if (ref $val eq 'ARRAY') {
|
208
215
|
if ($$tagInfo{JoinPath}) {
|
209
|
-
$val = join '/', @$val;
|
216
|
+
$val = join '/', map { ref $_ ? '(Binary data)' : $_ } @$val;
|
210
217
|
} else {
|
211
218
|
push @more, @$val;
|
212
219
|
next if ref $more[0] eq 'ARRAY'; # continue expanding nested lists
|
@@ -273,7 +280,7 @@ sub ProcessTorrent($$)
|
|
273
280
|
my $raf = $$dirInfo{RAF};
|
274
281
|
my $buff = '';
|
275
282
|
pos($buff) = 0;
|
276
|
-
my $dict = ReadBencode($raf, \$buff);
|
283
|
+
my $dict = ReadBencode($et, $raf, \$buff);
|
277
284
|
my $err = $$raf{BencodeError};
|
278
285
|
$et->Warn("Bencode error: $err") if $err;
|
279
286
|
if (ref $dict eq 'HASH' and ($$dict{announce} or $$dict{'created by'})) {
|
@@ -170,7 +170,7 @@ sub FormatIPTC($$$$$;$)
|
|
170
170
|
} else {
|
171
171
|
my $len = int(($1 || 0) / 8);
|
172
172
|
if ($len == 1) { # 1 byte
|
173
|
-
$$valPtr = chr($$valPtr);
|
173
|
+
$$valPtr = chr($$valPtr & 0xff);
|
174
174
|
} elsif ($len == 2) { # 2-byte integer
|
175
175
|
$$valPtr = pack('n', $$valPtr);
|
176
176
|
} else { # 4-byte integer
|
@@ -293,6 +293,7 @@ sub WritePDF($$)
|
|
293
293
|
my $newTool = new Image::ExifTool;
|
294
294
|
$newTool->Options(List => 1);
|
295
295
|
$newTool->Options(Password => $et->Options('Password'));
|
296
|
+
$newTool->Options(NoPDFList => $et->Options('NoPDFList'));
|
296
297
|
$$newTool{PDF_CAPTURE} = \%capture;
|
297
298
|
my $info = $newTool->ImageInfo($raf, 'XMP', 'PDF:*', 'Error', 'Warning');
|
298
299
|
# not a valid PDF file unless we got a version number
|
@@ -179,6 +179,8 @@ sub BuildTextChunk($$$$$)
|
|
179
179
|
$tag =~ s/-$lang$//; # remove language code from tagID
|
180
180
|
} elsif ($$et{OPTIONS}{Charset} ne 'Latin' and $val =~ /[\x80-\xff]/) {
|
181
181
|
$iTXt = 1; # write as iTXt if it contains non-Latin special characters
|
182
|
+
} elsif ($$tagInfo{iTXt}) {
|
183
|
+
$iTXt = 1; # write as iTXt if specified in user-defined tag
|
182
184
|
}
|
183
185
|
}
|
184
186
|
if ($comp) {
|
@@ -163,6 +163,9 @@ sub ConvInvISO6709($)
|
|
163
163
|
# latitude must have 2 digits before the decimal, and longitude 3,
|
164
164
|
# and all values must start with a "+" or "-", and Google Photos
|
165
165
|
# requires at least 3 digits after the decimal point
|
166
|
+
# (and as of Apr 2021, Google Photos doesn't accept coordinats
|
167
|
+
# with more than 5 digits after the decimal place:
|
168
|
+
# https://exiftool.org/forum/index.php?topic=11055.msg67171#msg67171 )
|
166
169
|
my @fmt = ('%s%02d.%s%s','%s%03d.%s%s','%s%d.%s%s');
|
167
170
|
foreach (@a) {
|
168
171
|
return undef unless Image::ExifTool::IsFloat($_);
|
@@ -314,7 +317,7 @@ sub FormatQTValue($$;$$)
|
|
314
317
|
if ($writable and $qtFormat{$writable}) {
|
315
318
|
$flags = $qtFormat{$writable};
|
316
319
|
} else {
|
317
|
-
$flags = $qtFormat{$format} || 0;
|
320
|
+
$flags = $qtFormat{$format || 0} || 0;
|
318
321
|
}
|
319
322
|
} elsif ($$valPt =~ /^\xff\xd8\xff/) {
|
320
323
|
$flags = 0x0d; # JPG
|
@@ -846,7 +849,7 @@ sub WriteQuickTime($$$)
|
|
846
849
|
# --> hold this terminator to the end
|
847
850
|
$term = $hdr;
|
848
851
|
} elsif ($n != 0) {
|
849
|
-
$et->Error(
|
852
|
+
$et->Error("Unknown $n bytes at end of file", 1);
|
850
853
|
}
|
851
854
|
last;
|
852
855
|
}
|
@@ -1064,6 +1067,9 @@ sub WriteQuickTime($$$)
|
|
1064
1067
|
# 3=optional base offset, 4=optional item ID)
|
1065
1068
|
ChunkOffset => \@chunkOffset,
|
1066
1069
|
);
|
1070
|
+
# set InPlace flag so XMP will be padded properly when
|
1071
|
+
# QuickTimePad is used if this is an XMP directory
|
1072
|
+
$subdirInfo{InPlace} = 2 if $et->Options('QuickTimePad');
|
1067
1073
|
# pass the header pointer if necessary (for EXIF IFD's
|
1068
1074
|
# where the Base offset is at the end of the header)
|
1069
1075
|
if ($hdrLen and $hdrLen < $size) {
|
@@ -1086,7 +1092,9 @@ sub WriteQuickTime($$$)
|
|
1086
1092
|
$$et{CHANGED} = $oldChanged if $$et{DemoteErrors} > 1;
|
1087
1093
|
delete $$et{DemoteErrors};
|
1088
1094
|
}
|
1089
|
-
if (defined $newData and not length $newData and $$
|
1095
|
+
if (defined $newData and not length $newData and ($$tagInfo{Permanent} or
|
1096
|
+
($$tagTablePtr{PERMANENT} and not defined $$tagInfo{Permanent})))
|
1097
|
+
{
|
1090
1098
|
# do nothing if trying to delete tag from a PERMANENT table
|
1091
1099
|
$$et{CHANGED} = $oldChanged;
|
1092
1100
|
undef $newData;
|
@@ -1094,7 +1102,9 @@ sub WriteQuickTime($$$)
|
|
1094
1102
|
$$et{CUR_WRITE_GROUP} = $oldWriteGroup;
|
1095
1103
|
SetByteOrder('MM');
|
1096
1104
|
# add back header if necessary
|
1097
|
-
if ($start and defined $newData and length $newData
|
1105
|
+
if ($start and defined $newData and (length $newData or
|
1106
|
+
(defined $$tagInfo{Permanent} and not $$tagInfo{Permanent})))
|
1107
|
+
{
|
1098
1108
|
$newData = substr($buff,0,$start) . $newData;
|
1099
1109
|
$$_[1] += $start foreach @chunkOffset;
|
1100
1110
|
}
|
@@ -1324,6 +1334,13 @@ sub WriteQuickTime($$$)
|
|
1324
1334
|
}
|
1325
1335
|
# write the new atom if it was modified
|
1326
1336
|
if (defined $newData) {
|
1337
|
+
my $sizeDiff = length($buff) - length($newData);
|
1338
|
+
if ($sizeDiff > 0 and $$tagInfo{PreservePadding} and $et->Options('QuickTimePad')) {
|
1339
|
+
$newData .= "\0" x $sizeDiff;
|
1340
|
+
$et->VPrint(1, " ($$tagInfo{Name} padded to original size)");
|
1341
|
+
} elsif ($sizeDiff) {
|
1342
|
+
$et->VPrint(1, " ($$tagInfo{Name} changed size)");
|
1343
|
+
}
|
1327
1344
|
my $len = length($newData) + 8;
|
1328
1345
|
$len > 0x7fffffff and $et->Error("$$tagInfo{Name} to large to write"), last;
|
1329
1346
|
# update size in ChunkOffset list for modified 'uuid' atom
|
@@ -1469,7 +1469,7 @@ sub WriteXMP($$;$)
|
|
1469
1469
|
$long[-2] .= "$nl$sp<$prop rdf:about='${about}'";
|
1470
1470
|
# generate et:toolkit attribute if this is an exiftool RDF/XML output file
|
1471
1471
|
if (@ns and $nsCur{$ns[0]} =~ m{^http://ns.exiftool.(?:ca|org)/}) {
|
1472
|
-
$long[-2] .= "\n$sp${sp}xmlns:et='http://ns.exiftool.
|
1472
|
+
$long[-2] .= "\n$sp${sp}xmlns:et='http://ns.exiftool.org/1.0/'" .
|
1473
1473
|
" et:toolkit='Image::ExifTool $Image::ExifTool::VERSION'";
|
1474
1474
|
}
|
1475
1475
|
$long[-2] .= "\n$sp${sp}xmlns:$_='$nsCur{$_}'" foreach @ns;
|
@@ -574,6 +574,9 @@ sub SetNewValue($;$$%)
|
|
574
574
|
my $pre = $wantGroup ? $wantGroup . ':' : '';
|
575
575
|
$err = "Tag '$pre${origTag}' is not defined";
|
576
576
|
$err .= ' or has a bad language code' if $origTag =~ /-/;
|
577
|
+
if (not $pre and uc($origTag) eq 'TAG') {
|
578
|
+
$err .= " (specify a writable tag name, not '${origTag}' literally)"
|
579
|
+
}
|
577
580
|
} else {
|
578
581
|
$err = "Invalid tag name '${tag}'";
|
579
582
|
$err .= " (remove the leading '\$')" if $tag =~ /^\$/;
|
@@ -2071,6 +2074,46 @@ sub SetSystemTags($$)
|
|
2071
2074
|
last;
|
2072
2075
|
}
|
2073
2076
|
}
|
2077
|
+
# delete Windows Zone.Identifier if specified
|
2078
|
+
my $zhash = $self->GetNewValueHash($Image::ExifTool::Extra{ZoneIdentifier});
|
2079
|
+
if ($zhash) {
|
2080
|
+
my $res = -1;
|
2081
|
+
if ($^O ne 'MSWin32') {
|
2082
|
+
$self->Warn('ZoneIdentifer is a Windows-only tag');
|
2083
|
+
} elsif (ref $file) {
|
2084
|
+
$self->Warn('Writing ZoneIdentifer requires a file name');
|
2085
|
+
} elsif (defined $self->GetNewValue('ZoneIdentifier', \$zhash)) {
|
2086
|
+
$self->Warn('ZoneIndentifier may only be delted');
|
2087
|
+
} elsif (not eval { require Win32API::File }) {
|
2088
|
+
$self->Warn('Install Win32API::File to write ZoneIdentifier');
|
2089
|
+
} else {
|
2090
|
+
my ($wattr, $wide);
|
2091
|
+
my $zfile = "${file}:Zone.Identifier";
|
2092
|
+
if ($self->EncodeFileName($zfile)) {
|
2093
|
+
$wide = 1;
|
2094
|
+
$wattr = eval { Win32API::File::GetFileAttributesW($zfile) };
|
2095
|
+
} else {
|
2096
|
+
$wattr = eval { Win32API::File::GetFileAttributes($zfile) };
|
2097
|
+
}
|
2098
|
+
if ($wattr == Win32API::File::INVALID_FILE_ATTRIBUTES()) {
|
2099
|
+
$res = 0; # file doesn't exist, nothing to do
|
2100
|
+
} elsif ($wattr & Win32API::File::FILE_ATTRIBUTE_READONLY()) {
|
2101
|
+
$self->Warn('Zone.Identifier stream is read-only');
|
2102
|
+
} else {
|
2103
|
+
if ($wide) {
|
2104
|
+
$res = 1 if eval { Win32API::File::DeleteFileW($zfile) };
|
2105
|
+
} else {
|
2106
|
+
$res = 1 if eval { Win32API::File::DeleteFile($zfile) };
|
2107
|
+
}
|
2108
|
+
if ($res > 0) {
|
2109
|
+
$self->VPrint(0, " Deleting Zone.Identifier stream\n");
|
2110
|
+
} else {
|
2111
|
+
$self->Warn('Error deleting Zone.Identifier stream');
|
2112
|
+
}
|
2113
|
+
}
|
2114
|
+
}
|
2115
|
+
$result = $res if $res == 1 or not $result;
|
2116
|
+
}
|
2074
2117
|
return $result;
|
2075
2118
|
}
|
2076
2119
|
|
@@ -4755,6 +4798,8 @@ sub InverseDateTime($$;$$)
|
|
4755
4798
|
$strptimeLib = '';
|
4756
4799
|
}
|
4757
4800
|
}
|
4801
|
+
# handle factional seconds (%f), but only at the end of the string
|
4802
|
+
my $fs = ($fmt =~ s/%f$// and $val =~ s/(\.\d+)\s*$//) ? $1 : '';
|
4758
4803
|
my ($lib, $wrn, @a);
|
4759
4804
|
TryLib: for ($lib=$strptimeLib; ; $lib='') {
|
4760
4805
|
if (not $lib) {
|
@@ -4791,10 +4836,10 @@ TryLib: for ($lib=$strptimeLib; ; $lib='') {
|
|
4791
4836
|
next TryLib;
|
4792
4837
|
}
|
4793
4838
|
} elsif (length($a[$i]) < 2) {
|
4794
|
-
|
4839
|
+
$a[$i] = "0$a[$i]"; # pad to 2 digits if necessary
|
4795
4840
|
}
|
4796
4841
|
}
|
4797
|
-
$val = join(':', @a[5,4,3]) . ' ' . join(':', @a[2,1,0]);
|
4842
|
+
$val = join(':', @a[5,4,3]) . ' ' . join(':', @a[2,1,0]) . $fs;
|
4798
4843
|
last;
|
4799
4844
|
}
|
4800
4845
|
}
|
@@ -50,7 +50,7 @@ use Image::ExifTool::Exif;
|
|
50
50
|
use Image::ExifTool::GPS;
|
51
51
|
require Exporter;
|
52
52
|
|
53
|
-
$VERSION = '3.
|
53
|
+
$VERSION = '3.47';
|
54
54
|
@ISA = qw(Exporter);
|
55
55
|
@EXPORT_OK = qw(EscapeXML UnescapeXML);
|
56
56
|
|
@@ -155,7 +155,7 @@ my %xmpNS = (
|
|
155
155
|
DICOM => 'http://ns.adobe.com/DICOM/',
|
156
156
|
'drone-dji'=> 'http://www.dji.com/drone-dji/1.0/',
|
157
157
|
svg => 'http://www.w3.org/2000/svg',
|
158
|
-
et => 'http://ns.exiftool.
|
158
|
+
et => 'http://ns.exiftool.org/1.0/',
|
159
159
|
#
|
160
160
|
# namespaces defined in XMP2.pl:
|
161
161
|
#
|
@@ -195,7 +195,7 @@ my %xmpNS = (
|
|
195
195
|
);
|
196
196
|
|
197
197
|
# build reverse namespace lookup
|
198
|
-
my %uri2ns = ( 'http://ns.exiftool.
|
198
|
+
my %uri2ns = ( 'http://ns.exiftool.ca/1.0/' => 'et' ); # (allow exiftool.ca as well as exiftool.org)
|
199
199
|
{
|
200
200
|
my $ns;
|
201
201
|
foreach $ns (keys %nsURI) {
|
@@ -1533,6 +1533,9 @@ my %sPantryItem = (
|
|
1533
1533
|
CameraProfile => { },
|
1534
1534
|
LookTable => { },
|
1535
1535
|
ToneCurvePV2012 => { List => 'Seq' },
|
1536
|
+
ToneCurvePV2012Red => { List => 'Seq' },
|
1537
|
+
ToneCurvePV2012Green => { List => 'Seq' },
|
1538
|
+
ToneCurvePV2012Blue => { List => 'Seq' },
|
1536
1539
|
},
|
1537
1540
|
},
|
1538
1541
|
}
|
@@ -2017,6 +2020,11 @@ my %sPantryItem = (
|
|
2017
2020
|
Groups => { 2 => 'Location' },
|
2018
2021
|
Writable => 'integer',
|
2019
2022
|
PrintConv => {
|
2023
|
+
OTHER => sub {
|
2024
|
+
my ($val, $inv) = @_;
|
2025
|
+
return undef unless $inv and $val =~ /^([-+0-9])/;
|
2026
|
+
return($1 eq '-' ? 1 : 0);
|
2027
|
+
},
|
2020
2028
|
0 => 'Above Sea Level',
|
2021
2029
|
1 => 'Below Sea Level',
|
2022
2030
|
},
|
@@ -2134,8 +2142,8 @@ my %sPantryItem = (
|
|
2134
2142
|
NAMESPACE => 'exifEX',
|
2135
2143
|
PRIORITY => 0, # not as reliable as actual EXIF tags
|
2136
2144
|
NOTES => q{
|
2137
|
-
EXIF tags added by the EXIF 2.
|
2138
|
-
L<
|
2145
|
+
EXIF tags added by the EXIF 2.32 for XMP specification (see
|
2146
|
+
L<https://cipa.jp/std/documents/download_e.html?DC-010-2020_E>).
|
2139
2147
|
},
|
2140
2148
|
Gamma => { Writable => 'rational' },
|
2141
2149
|
PhotographicSensitivity => { Writable => 'integer' },
|
@@ -2341,6 +2349,9 @@ my %sPantryItem = (
|
|
2341
2349
|
Scene => { Groups => { 2 => 'Other' }, List => 'Bag' },
|
2342
2350
|
SubjectCode => { Groups => { 2 => 'Other' }, List => 'Bag' },
|
2343
2351
|
# Copyright - have seen this in a sample (Jan 2021), but I think it is non-standard
|
2352
|
+
# new IPTC Core 1.3 properties
|
2353
|
+
AltTextAccessibility => { Groups => { 2 => 'Other' }, Writable => 'lang-alt' },
|
2354
|
+
ExtDescrAccessibility => { Groups => { 2 => 'Other' }, Writable => 'lang-alt' },
|
2344
2355
|
);
|
2345
2356
|
|
2346
2357
|
# Adobe Lightroom namespace properties (lr) (ref PH)
|
@@ -3258,8 +3269,14 @@ NoLoop:
|
|
3258
3269
|
}
|
3259
3270
|
}
|
3260
3271
|
# generate a default tagInfo hash if necessary
|
3261
|
-
|
3262
|
-
|
3272
|
+
unless ($tagInfo) {
|
3273
|
+
# shorten tag name if necessary
|
3274
|
+
if ($$et{ShortenXmpTags}) {
|
3275
|
+
my $shorten = $$et{ShortenXmpTags};
|
3276
|
+
$name = &$shorten($name);
|
3277
|
+
}
|
3278
|
+
$tagInfo = { Name => $name, IsDefault => 1, Priority => 0 };
|
3279
|
+
}
|
3263
3280
|
# add tag Namespace entry for tags in variable-namespace tables
|
3264
3281
|
$$tagInfo{Namespace} = $xns if $xns;
|
3265
3282
|
if ($$et{curURI}{$ns} and $$et{curURI}{$ns} =~ m{^http://ns.exiftool.(?:ca|org)/(.*?)/(.*?)/}) {
|
@@ -3778,6 +3795,7 @@ sub ParseXMPElement($$$;$$$$)
|
|
3778
3795
|
# (unless we already extracted shorthand values from this element)
|
3779
3796
|
if (length $val or not $shorthand) {
|
3780
3797
|
my $lastProp = $$propList[-1];
|
3798
|
+
$lastProp = '' unless defined $lastProp;
|
3781
3799
|
if (defined $nodeID) {
|
3782
3800
|
SaveBlankInfo($blankInfo, $propList, $val);
|
3783
3801
|
} elsif ($lastProp eq 'rdf:type' and $wasEmpty) {
|
@@ -3948,7 +3966,7 @@ sub ProcessXMP($$;$)
|
|
3948
3966
|
} elsif ($1 eq 'REDXIF') {
|
3949
3967
|
$type = 'RMD';
|
3950
3968
|
$mime = 'application/xml';
|
3951
|
-
}
|
3969
|
+
} elsif ($1 ne 'fcpxml') { # Final Cut Pro XML
|
3952
3970
|
return 0;
|
3953
3971
|
}
|
3954
3972
|
} elsif ($buf2 =~ /<svg[\s>]/) {
|
@@ -3958,14 +3976,16 @@ sub ProcessXMP($$;$)
|
|
3958
3976
|
} elsif ($buf2 =~ /<plist[\s>]/) {
|
3959
3977
|
$type = 'PLIST';
|
3960
3978
|
}
|
3961
|
-
if ($isSVG and $$et{XMP_CAPTURE}) {
|
3962
|
-
$et->Error("ExifTool does not yet support writing of SVG images");
|
3963
|
-
return 0;
|
3964
|
-
}
|
3965
3979
|
}
|
3966
3980
|
$isXML = 1;
|
3967
3981
|
} elsif ($2 eq '<rdf:RDF') {
|
3968
3982
|
$isRDF = 1; # recognize XMP without x:xmpmeta element
|
3983
|
+
} elsif ($2 eq '<svg') {
|
3984
|
+
$isSVG = $isXML = 1;
|
3985
|
+
}
|
3986
|
+
if ($isSVG and $$et{XMP_CAPTURE}) {
|
3987
|
+
$et->Error("ExifTool does not yet support writing of SVG images");
|
3988
|
+
return 0;
|
3969
3989
|
}
|
3970
3990
|
if ($buff =~ /^\0\0/) {
|
3971
3991
|
$fmt = 'N'; # UTF-32 MM with or without BOM
|
@@ -537,9 +537,10 @@ my %sImageRegion = ( # new in 1.5
|
|
537
537
|
NAMESPACE => 'Iptc4xmpExt',
|
538
538
|
TABLE_DESC => 'XMP IPTC Extension',
|
539
539
|
NOTES => q{
|
540
|
-
This table contains tags defined by the IPTC Extension schema version 1.
|
540
|
+
This table contains tags defined by the IPTC Extension schema version 1.6.
|
541
541
|
The actual namespace prefix is "Iptc4xmpExt", but ExifTool shortens this for
|
542
|
-
the family 1 group name. (see
|
542
|
+
the family 1 group name. (see
|
543
|
+
L<http://www.iptc.org/standards/photo-metadata/iptc-standard/>)
|
543
544
|
},
|
544
545
|
AboutCvTerm => {
|
545
546
|
Struct => \%sCVTermDetails,
|
@@ -796,6 +797,8 @@ my %sImageRegion = ( # new in 1.5
|
|
796
797
|
audioBitsPerSample => { Groups => { 2 => 'Audio' }, Writable => 'integer' },
|
797
798
|
# new IPTC Extension schema 1.5 property
|
798
799
|
ImageRegion => { Groups => { 2 => 'Image' }, List => 'Bag', Struct => \%sImageRegion },
|
800
|
+
# new Extension 1.6 property
|
801
|
+
EventId => { Name => 'EventID', List => 'Bag' },
|
799
802
|
);
|
800
803
|
|
801
804
|
#------------------------------------------------------------------------------
|
@@ -32,7 +32,9 @@ sub SerializeStruct($;$)
|
|
32
32
|
my ($key, $val, @vals, $rtnVal);
|
33
33
|
|
34
34
|
if (ref $obj eq 'HASH') {
|
35
|
-
|
35
|
+
# support hashes with ordered keys
|
36
|
+
my @keys = $$obj{_ordered_keys_} ? @{$$obj{_ordered_keys_}} : sort keys %$obj;
|
37
|
+
foreach $key (@keys) {
|
36
38
|
push @vals, $key . '=' . SerializeStruct($$obj{$key}, '}');
|
37
39
|
}
|
38
40
|
$rtnVal = '{' . join(',', @vals) . '}';
|
@@ -14,7 +14,7 @@ use strict;
|
|
14
14
|
use vars qw($VERSION);
|
15
15
|
use Image::ExifTool qw(:DataAccess :Utils);
|
16
16
|
|
17
|
-
$VERSION = '1.
|
17
|
+
$VERSION = '1.01';
|
18
18
|
|
19
19
|
%Image::ExifTool::ZISRAW::Main = (
|
20
20
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
@@ -41,6 +41,123 @@ $VERSION = '1.00';
|
|
41
41
|
},
|
42
42
|
);
|
43
43
|
|
44
|
+
#------------------------------------------------------------------------------
|
45
|
+
# Shorten obscenely long CZI tag names
|
46
|
+
# Inputs: Tag name
|
47
|
+
# Returns: Shortened tag name
|
48
|
+
sub ShortenTagNames($)
|
49
|
+
{
|
50
|
+
local $_;
|
51
|
+
$_ = shift;
|
52
|
+
s/^HardwareSetting//;
|
53
|
+
s/^DevicesDevice/Device/;
|
54
|
+
s/LightPathNode//g;
|
55
|
+
s/Successors//g;
|
56
|
+
s/ExperimentExperiment/Experiment/g;
|
57
|
+
s/ObjectivesObjective/Objective/;
|
58
|
+
s/ChannelsChannel/Channel/;
|
59
|
+
s/TubeLensesTubeLens/TubeLens/;
|
60
|
+
s/^ExperimentHardwareSettingsPoolHardwareSetting/HardwareSetting/;
|
61
|
+
s/SharpnessMeasureSetSharpnessMeasure/Sharpness/;
|
62
|
+
s/FocusSetupAutofocusSetup/Autofocus/;
|
63
|
+
s/TracksTrack/Track/;
|
64
|
+
s/ChannelRefsChannelRef/ChannelRef/;
|
65
|
+
s/ChangerChanger/Changer/;
|
66
|
+
s/ElementsChangerElement/Changer/;
|
67
|
+
s/ChangerElements/Changer/;
|
68
|
+
s/ContrastChangerContrast/Contrast/;
|
69
|
+
s/KeyFunctionsKeyFunction/KeyFunction/;
|
70
|
+
s/ManagerContrastManager(Contrast)?/ManagerContrast/;
|
71
|
+
s/ObjectiveChangerObjective/ObjectiveChanger/;
|
72
|
+
s/ManagerLightManager/ManagerLight/;
|
73
|
+
s/WavelengthAreasWavelengthArea/WavelengthArea/;
|
74
|
+
s/ReflectorChangerReflector/ReflectorChanger/;
|
75
|
+
s/^StageStageAxesStageAxis/StageAxis/;
|
76
|
+
s/ShutterChangerShutter/ShutterChanger/;
|
77
|
+
s/OnOffChangerOnOff/OnOffChanger/;
|
78
|
+
s/UnsharpMaskStateUnsharpMask/UnsharpMask/;
|
79
|
+
s/Acquisition/Acq/;
|
80
|
+
s/Continuous/Cont/;
|
81
|
+
s/Resolution/Res/;
|
82
|
+
s/Experiment/Expt/g;
|
83
|
+
s/Threshold/Thresh/;
|
84
|
+
s/Reference/Ref/;
|
85
|
+
s/Magnification/Mag/;
|
86
|
+
s/Original/Orig/;
|
87
|
+
s/FocusSetupFocusStrategySetup/Focus/;
|
88
|
+
s/ParametersParameter/Parameter/;
|
89
|
+
s/IntervalInfo/Interval/;
|
90
|
+
s/ExptBlocksAcqBlock/AcqBlock/;
|
91
|
+
s/MicroscopesMicroscope/Microscope/;
|
92
|
+
s/TimeSeriesInterval/TimeSeries/;
|
93
|
+
s/Interval(.*Interval)/$1/;
|
94
|
+
s/SingleTileRegionsSingleTileRegion/SingleTileRegion/;
|
95
|
+
s/AcquisitionMode//;
|
96
|
+
s/DetectorsDetector/Detector/;
|
97
|
+
s/Setup//;
|
98
|
+
s/Setting//;
|
99
|
+
s/TrackTrack/Track/;
|
100
|
+
s/AnalogOutMaximumsAnalogOutMaximum/AnalogOutMaximum/;
|
101
|
+
s/AnalogOutMinimumsAnalogOutMinimum/AnalogOutMinimum/;
|
102
|
+
s/DigitalOutLabelsDigitalOutLabelLabel/DigitalOutLabelLabel/;
|
103
|
+
s/(VivaTomeOpticalSectionInformation)+VivaTomeOpticalSectionInformation/VivaTomeOpticalSectionInformation/;
|
104
|
+
s/FocusDefiniteFocus/FocusDefinite/;
|
105
|
+
s/ChangerChanger/Changer/;
|
106
|
+
s/Calibration/Cal/;
|
107
|
+
s/LightSwitchChangerRLTLSwitch/LightSwitchChangerRLTL/;
|
108
|
+
s/Parameters//;
|
109
|
+
s/Fluorescence/Fluor/;
|
110
|
+
s/CameraGeometryCameraGeometry/CameraGeometry/;
|
111
|
+
s/CameraCamera/Camera/;
|
112
|
+
s/DetectorsCamera/Camera/;
|
113
|
+
s/FilterChangerLeftChangerEmissionFilter/LeftChangerEmissionFilter/;
|
114
|
+
s/SwitchingStatesSwitchingState/SwitchingState/;
|
115
|
+
s/Information/Info/;
|
116
|
+
s/SubDimensions?//g;
|
117
|
+
s/Setups?//;
|
118
|
+
s/Parameters?//;
|
119
|
+
s/Calculate/Calc/;
|
120
|
+
s/Visibility/Vis/;
|
121
|
+
s/Orientation/Orient/;
|
122
|
+
s/ListItems/Items/;
|
123
|
+
s/Increment/Incr/;
|
124
|
+
s/Parameter/Param/;
|
125
|
+
s/(ParfocalParcentralValues)+ParfocalParcentralValue/Parcentral/;
|
126
|
+
s/ParcentralParcentral/Parcentral/;
|
127
|
+
s/CorrFocusCorrection/FocusCorr/;
|
128
|
+
s/(ApoTomeDepthInfo)+Element/ApoTomeDepth/;
|
129
|
+
s/(ApoTomeClickStopInfo)+Element/ApoTomeClickStop/;
|
130
|
+
s/DepthDepth/Depth/;
|
131
|
+
s/(Devices?)+Device/Device/;
|
132
|
+
s/(BeamPathNode)+/BeamPathNode/;
|
133
|
+
s/BeamPathsBeamPath/BeamPath/g;
|
134
|
+
s/BeamPathBeamPath/BeamPath/g;
|
135
|
+
s/Configuration/Config/;
|
136
|
+
s/StageAxesStageAxis/StageAxis/;
|
137
|
+
s/RangesRange/Range/;
|
138
|
+
s/DataGridDatasGridData(Grid)?/DataGrid/;
|
139
|
+
s/DataMicroscopeDatasMicroscopeData(Microscope)?/DataMicroscope/;
|
140
|
+
s/DataWegaDatasWegaData/DataWega/;
|
141
|
+
s/ClickStopPositionsClickStopPosition/ClickStopPosition/;
|
142
|
+
s/LightSourcess?LightSource(Settings)?(LightSource)?/LightSource/;
|
143
|
+
s/FilterSetsFilterSet/FilterSet/;
|
144
|
+
s/EmissionFiltersEmissionFilter/EmissionFilter/;
|
145
|
+
s/ExcitationFiltersExcitationFilter/ExcitationFilter/;
|
146
|
+
s/FiltersFilter/Filter/;
|
147
|
+
s/DichroicsDichroic/Dichronic/;
|
148
|
+
s/WavelengthsWavelength/Wavelength/;
|
149
|
+
s/MultiTrackSetup/MultiTrack/;
|
150
|
+
s/TrackTrack/Track/;
|
151
|
+
s/DataGrabberSetup/DataGrabber/;
|
152
|
+
s/CameraFrameSetup/CameraFrame/;
|
153
|
+
s/TimeSeries(TimeSeries|Setups)/TimeSeries/;
|
154
|
+
s/FocusFocus/Focus/;
|
155
|
+
s/FocusAutofocus/Autofocus/;
|
156
|
+
s/Focus(Hardware|Software)(Autofocus)+/Autofocus$1/;
|
157
|
+
s/AutofocusAutofocus/Autofocus/;
|
158
|
+
return $_;
|
159
|
+
}
|
160
|
+
|
44
161
|
#------------------------------------------------------------------------------
|
45
162
|
# Extract metadata from a ZISRAW (CZI) image
|
46
163
|
# Inputs: 0) ExifTool object reference, 1) dirInfo reference
|
@@ -76,7 +193,9 @@ sub ProcessCZI($$)
|
|
76
193
|
$tagTablePtr = GetTagTable('Image::ExifTool::XMP::XML');
|
77
194
|
$dirInfo{DirLen} = length $buff;
|
78
195
|
# shorten tag names somewhat by removing 'ImageDocumentMetadata' prefix from all
|
79
|
-
$$et{XmpIgnoreProps} = [ 'ImageDocument', 'Metadata' ];
|
196
|
+
$$et{XmpIgnoreProps} = [ 'ImageDocument', 'Metadata', 'Information' ];
|
197
|
+
$$et{ShortenXmpTags} = \&ShortenTagNames;
|
198
|
+
|
80
199
|
$et->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
81
200
|
|
82
201
|
return 1;
|