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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +174 -7
  3. data/bin/MANIFEST +11 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +44 -43
  7. data/bin/arg_files/xmp2exif.args +2 -1
  8. data/bin/config_files/convert_regions.config +25 -14
  9. data/bin/config_files/example.config +1 -1
  10. data/bin/exiftool +118 -92
  11. data/bin/fmt_files/gpx.fmt +1 -1
  12. data/bin/fmt_files/gpx_wpt.fmt +1 -1
  13. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +16 -3
  14. data/bin/lib/Image/ExifTool/CBOR.pm +331 -0
  15. data/bin/lib/Image/ExifTool/Canon.pm +52 -20
  16. data/bin/lib/Image/ExifTool/Charset.pm +2 -0
  17. data/bin/lib/Image/ExifTool/DPX.pm +13 -2
  18. data/bin/lib/Image/ExifTool/Exif.pm +107 -8
  19. data/bin/lib/Image/ExifTool/FLIR.pm +33 -8
  20. data/bin/lib/Image/ExifTool/FlashPix.pm +35 -10
  21. data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -0
  22. data/bin/lib/Image/ExifTool/Geotag.pm +13 -2
  23. data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
  24. data/bin/lib/Image/ExifTool/ICC_Profile.pm +96 -4
  25. data/bin/lib/Image/ExifTool/ID3.pm +15 -3
  26. data/bin/lib/Image/ExifTool/JPEG.pm +68 -2
  27. data/bin/lib/Image/ExifTool/JSON.pm +7 -3
  28. data/bin/lib/Image/ExifTool/Jpeg2000.pm +164 -36
  29. data/bin/lib/Image/ExifTool/LIF.pm +153 -0
  30. data/bin/lib/Image/ExifTool/Lang/nl.pm +60 -59
  31. data/bin/lib/Image/ExifTool/M2TS.pm +103 -7
  32. data/bin/lib/Image/ExifTool/MIE.pm +2 -1
  33. data/bin/lib/Image/ExifTool/MRC.pm +1 -1
  34. data/bin/lib/Image/ExifTool/MacOS.pm +2 -2
  35. data/bin/lib/Image/ExifTool/Nikon.pm +50 -6
  36. data/bin/lib/Image/ExifTool/NikonSettings.pm +10 -2
  37. data/bin/lib/Image/ExifTool/Olympus.pm +9 -2
  38. data/bin/lib/Image/ExifTool/Other.pm +93 -0
  39. data/bin/lib/Image/ExifTool/PDF.pm +11 -12
  40. data/bin/lib/Image/ExifTool/PNG.pm +7 -6
  41. data/bin/lib/Image/ExifTool/Panasonic.pm +14 -2
  42. data/bin/lib/Image/ExifTool/Pentax.pm +28 -5
  43. data/bin/lib/Image/ExifTool/Photoshop.pm +6 -0
  44. data/bin/lib/Image/ExifTool/QuickTime.pm +123 -25
  45. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +203 -121
  46. data/bin/lib/Image/ExifTool/README +9 -2
  47. data/bin/lib/Image/ExifTool/RIFF.pm +7 -2
  48. data/bin/lib/Image/ExifTool/Samsung.pm +47 -10
  49. data/bin/lib/Image/ExifTool/Sony.pm +113 -42
  50. data/bin/lib/Image/ExifTool/TagLookup.pm +4599 -4451
  51. data/bin/lib/Image/ExifTool/TagNames.pod +276 -41
  52. data/bin/lib/Image/ExifTool/Torrent.pm +18 -11
  53. data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
  54. data/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
  55. data/bin/lib/Image/ExifTool/WritePNG.pl +2 -0
  56. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +21 -4
  57. data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  58. data/bin/lib/Image/ExifTool/Writer.pl +47 -2
  59. data/bin/lib/Image/ExifTool/XMP.pm +32 -12
  60. data/bin/lib/Image/ExifTool/XMP2.pl +5 -2
  61. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  62. data/bin/lib/Image/ExifTool/ZISRAW.pm +121 -2
  63. data/bin/lib/Image/ExifTool.pm +153 -52
  64. data/bin/lib/Image/ExifTool.pod +70 -60
  65. data/bin/perl-Image-ExifTool.spec +43 -42
  66. data/lib/exiftool_vendored/version.rb +1 -1
  67. 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.04';
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, 1) buffer (pos must be set to current position)
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 or $value =~ /[^\t\x20-\x7e]/) {
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('File format 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 $$tagTablePtr{PERMANENT}) {
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.ca/1.0/'" .
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
- $$a[$i] = "0$a[$i]";# pad to 2 digits if necessary
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.41';
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.ca/1.0/',
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.org/1.0/' => 'et' ); # (allow exiftool.org as well as exiftool.ca)
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.31 for XMP specification (see
2138
- L<http://www.cipa.jp/std/documents/e/DC-X010-2017.pdf>).
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
- $tagInfo or $tagInfo = { Name => $name, IsDefault => 1, Priority => 0 };
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
- } else {
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.5.
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 L<http://www.iptc.org/IPTC4XMP/>)
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
- foreach $key (sort keys %$obj) {
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.00';
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;