exiftool_vendored 12.25.0 → 12.35.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 +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;
|