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.
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;