exiftool-vendored.exe 12.67.0 → 12.70.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 (42) hide show
  1. package/bin/exiftool_files/Changes +79 -10
  2. package/bin/exiftool_files/README +7 -7
  3. package/bin/exiftool_files/exiftool.pl +37 -31
  4. package/bin/exiftool_files/lib/Image/ExifTool/CBOR.pm +18 -2
  5. package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +87 -16
  6. package/bin/exiftool_files/lib/Image/ExifTool/DJI.pm +3 -2
  7. package/bin/exiftool_files/lib/Image/ExifTool/DNG.pm +25 -2
  8. package/bin/exiftool_files/lib/Image/ExifTool/EXE.pm +54 -6
  9. package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +175 -14
  10. package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +158 -20
  11. package/bin/exiftool_files/lib/Image/ExifTool/GIF.pm +5 -1
  12. package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +16 -11
  13. package/bin/exiftool_files/lib/Image/ExifTool/ID3.pm +70 -7
  14. package/bin/exiftool_files/lib/Image/ExifTool/InDesign.pm +1 -1
  15. package/bin/exiftool_files/lib/Image/ExifTool/JPEG.pm +1 -1
  16. package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +30 -15
  17. package/bin/exiftool_files/lib/Image/ExifTool/MakerNotes.pm +2 -2
  18. package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +82 -22
  19. package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +7 -1
  20. package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +3 -1
  21. package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +22 -9
  22. package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +6 -1
  23. package/bin/exiftool_files/lib/Image/ExifTool/PhotoMechanic.pm +2 -1
  24. package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +92 -55
  25. package/bin/exiftool_files/lib/Image/ExifTool/README +14 -5
  26. package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +60 -10
  27. package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +152 -46
  28. package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +6955 -6713
  29. package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +878 -334
  30. package/bin/exiftool_files/lib/Image/ExifTool/Text.pm +4 -5
  31. package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +23 -20
  32. package/bin/exiftool_files/lib/Image/ExifTool/WriteCanonRaw.pl +2 -2
  33. package/bin/exiftool_files/lib/Image/ExifTool/WriteExif.pl +14 -4
  34. package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +3 -0
  35. package/bin/exiftool_files/lib/Image/ExifTool/WriteRIFF.pl +31 -6
  36. package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +40 -14
  37. package/bin/exiftool_files/lib/Image/ExifTool/XISF.pm +185 -0
  38. package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +67 -2
  39. package/bin/exiftool_files/lib/Image/ExifTool/XMP2.pl +35 -0
  40. package/bin/exiftool_files/lib/Image/ExifTool.pm +92 -45
  41. package/bin/exiftool_files/lib/Image/ExifTool.pod +14 -8
  42. package/package.json +3 -3
@@ -20,7 +20,7 @@ use strict;
20
20
  use vars qw($VERSION);
21
21
  use Image::ExifTool qw(:DataAccess :Utils);
22
22
 
23
- $VERSION = '1.19';
23
+ $VERSION = '1.20';
24
24
 
25
25
  # road map of directory locations in GIF images
26
26
  my %gifMap = (
@@ -85,6 +85,10 @@ my %gifMap = (
85
85
  Groups => { 2 => 'Audio' },
86
86
  Binary => 1,
87
87
  },
88
+ 'C2PA_GIF/' => { #https://c2pa.org/specifications/ (NC) (authentication code is 0x010000 binary, so removed from tag ID)
89
+ Name => 'JUMBF',
90
+ SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::Main' },
91
+ },
88
92
  );
89
93
 
90
94
  # GIF locical screen descriptor
@@ -29,7 +29,7 @@ use vars qw($VERSION);
29
29
  use Image::ExifTool qw(:Public);
30
30
  use Image::ExifTool::GPS;
31
31
 
32
- $VERSION = '1.72';
32
+ $VERSION = '1.73';
33
33
 
34
34
  sub JITTER() { return 2 } # maximum time jitter
35
35
 
@@ -1196,24 +1196,29 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
1196
1196
  # write GPSDateStamp if date included in track log, otherwise delete it
1197
1197
  $gpsDate = sprintf('%.2d:%.2d:%.2d', $t[5]+1900, $t[4]+1, $t[3]) unless $noDate;
1198
1198
  # write GPSAltitude tags if altitude included in track log, otherwise delete them
1199
- if (defined $$fix{alt}) {
1200
- $gpsAlt = abs $$fix{alt};
1201
- $gpsAltRef = ($$fix{alt} < 0 ? 1 : 0);
1202
- } elsif ($$has{alt} and defined $iExt) {
1199
+ my $alt = $$fix{alt};
1200
+ if (not defined $alt and $$has{alt} and defined $iExt) {
1203
1201
  my $tFix = FindFix($et,'alt',$times,$points,$iExt,$iDir,$geoMaxExtSecs);
1204
- if ($tFix) {
1205
- $gpsAlt = abs $$tFix{alt};
1206
- $gpsAltRef = ($$tFix{alt} < 0 ? 1 : 0);
1207
- }
1202
+ $alt = $$tFix{alt} if $tFix;
1208
1203
  }
1209
1204
  # set new GPS tag values (EXIF, or XMP if write group is 'xmp')
1210
- my ($xmp, $exif, @r);
1205
+ my ($xmp, $exif, $qt, @r);
1211
1206
  my %opts = ( Type => 'ValueConv' ); # write ValueConv values
1212
1207
  if ($writeGroup) {
1213
1208
  $opts{Group} = $writeGroup;
1214
1209
  $xmp = ($writeGroup =~ /xmp/i);
1215
1210
  $exif = ($writeGroup =~ /^(exif|gps)$/i);
1211
+ $qt = $writeGroup =~ /^(quicktime|keys|itemlist|userdata)$/i;
1212
+ }
1213
+ # set QuickTime GPSCoordinates
1214
+ my $coords = "$$fix{lat} $$fix{lon}";
1215
+ if (defined $alt) {
1216
+ $gpsAlt = abs $alt;
1217
+ $gpsAltRef = ($alt < 0 ? 1 : 0);
1218
+ $coords .= " $alt";
1216
1219
  }
1220
+ @r = $et->SetNewValue(GPSCoordinates => $coords, %opts);
1221
+ return $err if $qt; # all done if writing to QuickTime only
1217
1222
  # (capture error messages by calling SetNewValue in list context)
1218
1223
  @r = $et->SetNewValue(GPSLatitude => $$fix{lat}, %opts);
1219
1224
  @r = $et->SetNewValue(GPSLongitude => $$fix{lon}, %opts);
@@ -1288,7 +1293,7 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
1288
1293
  GPSAltitude GPSAltitudeRef GPSDateStamp GPSTimeStamp GPSDateTime
1289
1294
  GPSTrack GPSTrackRef GPSSpeed GPSSpeedRef GPSImgDirection
1290
1295
  GPSImgDirectionRef GPSPitch GPSRoll CameraElevationAngle
1291
- AmbientTemperature))
1296
+ AmbientTemperature GPSCoordinates))
1292
1297
  {
1293
1298
  my @r = $et->SetNewValue($_, undef, %opts);
1294
1299
  }
@@ -18,12 +18,13 @@ use strict;
18
18
  use vars qw($VERSION);
19
19
  use Image::ExifTool qw(:DataAccess :Utils);
20
20
 
21
- $VERSION = '1.58';
21
+ $VERSION = '1.59';
22
22
 
23
23
  sub ProcessID3v2($$$);
24
24
  sub ProcessPrivate($$$);
25
25
  sub ProcessSynText($$$);
26
26
  sub ProcessID3Dir($$$);
27
+ sub ProcessGEOB($$$);
27
28
  sub ConvertID3v1Text($$);
28
29
  sub ConvertTimeStamp($);
29
30
 
@@ -419,7 +420,7 @@ my %genre = (
419
420
 
420
421
  # Tags for ID2v2.2
421
422
  %Image::ExifTool::ID3::v2_2 = (
422
- PROCESS_PROC => \&Image::ExifTool::ID3::ProcessID3v2,
423
+ PROCESS_PROC => \&ProcessID3v2,
423
424
  GROUPS => { 1 => 'ID3v2_2', 2 => 'Audio' },
424
425
  NOTES => q{
425
426
  ExifTool extracts mainly text-based tags from ID3v2 information. The tags
@@ -511,6 +512,9 @@ my %genre = (
511
512
  TSC => 'ComposerSortOrder',
512
513
  ITU => { Name => 'iTunesU', Description => 'iTunes U', Binary => 1, Unknown => 1 },
513
514
  PCS => { Name => 'Podcast', Binary => 1, Unknown => 1 },
515
+ GP1 => 'Grouping', #github142 (NC)
516
+ MVN => 'MovementName', #github142 (NC)
517
+ MVI => 'MovementNumber', #github142 (NC)
514
518
  );
515
519
 
516
520
  # tags common to ID3v2.3 and ID3v2.4
@@ -534,7 +538,10 @@ my %id3v2_common = (
534
538
  # COMR => 'Commercial',
535
539
  # ENCR => 'EncryptionMethod',
536
540
  # ETCO => 'EventTimingCodes',
537
- # GEOB => 'GeneralEncapsulatedObject',
541
+ GEOB => {
542
+ Name => 'GeneralEncapsulatedObject',
543
+ SubDirectory => { TagTable => 'Image::ExifTool::ID3::GEOB' },
544
+ },
538
545
  # GRID => 'GroupIdentification',
539
546
  # LINK => 'LinkedInformation',
540
547
  MCDI => { Name => 'MusicCDIdentifier', Binary => 1 },
@@ -640,9 +647,25 @@ my %id3v2_common = (
640
647
  MVIN => 'MovementNumber', # (NC)
641
648
  );
642
649
 
650
+ %Image::ExifTool::ID3::GEOB = (
651
+ GROUPS => { 1 => 'ID3v2_3', 2 => 'Other' },
652
+ PROCESS_PROC => \&ProcessGEOB,
653
+ 'application/x-c2pa-manifest-store' => {
654
+ Name => 'JUMBF',
655
+ SubDirectory => {
656
+ TagTable => 'Image::ExifTool::Jpeg2000::Main',
657
+ ByteOrder => 'BigEndian',
658
+ },
659
+ },
660
+ 'GEOB-Mime' => { },
661
+ 'GEOB-File' => { },
662
+ 'GEOB-Desc' => { },
663
+ 'GEOB-Data' => { },
664
+ );
665
+
643
666
  # Tags for ID3v2.3 (http://www.id3.org/id3v2.3.0)
644
667
  %Image::ExifTool::ID3::v2_3 = (
645
- PROCESS_PROC => \&Image::ExifTool::ID3::ProcessID3v2,
668
+ PROCESS_PROC => \&ProcessID3v2,
646
669
  GROUPS => { 1 => 'ID3v2_3', 2 => 'Audio' },
647
670
  NOTES => q{
648
671
  ID3 version 2.3 tags. Includes some non-standard tags written by other
@@ -662,7 +685,7 @@ my %id3v2_common = (
662
685
 
663
686
  # Tags for ID3v2.4 (http://www.id3.org/id3v2.4.0-frames)
664
687
  %Image::ExifTool::ID3::v2_4 = (
665
- PROCESS_PROC => \&Image::ExifTool::ID3::ProcessID3v2,
688
+ PROCESS_PROC => \&ProcessID3v2,
666
689
  GROUPS => { 1 => 'ID3v2_4', 2 => 'Audio' },
667
690
  NOTES => q{
668
691
  ID3 version 2.4 tags. Includes some non-standard tags written by other
@@ -1101,7 +1124,11 @@ sub ProcessID3v2($$$)
1101
1124
  my $oldLen = $len;
1102
1125
  $len = UnSyncSafe($len);
1103
1126
  if (not defined $len or $offset + $len + 10 > $size) {
1104
- $et->Warn('Invalid ID3 frame size');
1127
+ if ($offset + $len == $size) {
1128
+ $et->Warn('Missing ID3 terminating frame', 1);
1129
+ } else {
1130
+ $et->Warn('Invalid ID3 frame size');
1131
+ }
1105
1132
  last;
1106
1133
  }
1107
1134
  # check next ID to see if it makes sense
@@ -1218,7 +1245,7 @@ sub ProcessID3v2($$$)
1218
1245
  my @vals = DecodeString($et, $val);
1219
1246
  foreach (0..1) { $vals[$_] = '' unless defined $vals[$_]; }
1220
1247
  ($val = "($vals[0]) $vals[1]") =~ s/^\(\) //;
1221
- } elsif ($id =~ /^T/ or $id =~ /^(IPL|IPLS)$/) {
1248
+ } elsif ($id =~ /^T/ or $id =~ /^(IPL|IPLS|GP1|MVI|MVN)$/) {
1222
1249
  $val = DecodeString($et, $val);
1223
1250
  } elsif ($id =~ /^(WXX|WXXX)$/) {
1224
1251
  # one encoded string and one Latin string separated by a null
@@ -1582,6 +1609,42 @@ sub ProcessID3Dir($$$)
1582
1609
  return ProcessID3($et, $dirInfo);
1583
1610
  }
1584
1611
 
1612
+ #------------------------------------------------------------------------------
1613
+ # Process ID3 General Encapsulated Object
1614
+ # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
1615
+ # Returns: 1 on success
1616
+ sub ProcessGEOB($$$)
1617
+ {
1618
+ my ($et, $dirInfo, $tagTablePtr) = @_;
1619
+ $et->VerboseDir('GEOB', undef, length ${$$dirInfo{DataPt}});
1620
+ my $dataPt = $$dirInfo{DataPt};
1621
+ my $len = length $$dataPt;
1622
+ $len >= 4 or $et->Warn("Short GEOB frame"), return 0;
1623
+ my ($hdr, $attr);
1624
+ my $enc = unpack('C', $$dataPt);
1625
+ if ($enc == 1 or $enc == 2) {
1626
+ $hdr = ".(.*?)\0((?:..)*?)\0\0((?:..)*?)\0\0";
1627
+ } else {
1628
+ $hdr = ".(.*?)\0(.*?)\0(.*?)\0";
1629
+ }
1630
+ # remove header (encoding, mime, filename, description)
1631
+ $$dataPt =~ s/^$hdr//s or $et->Warn("Invalid GEOB frame"), return 0;
1632
+ my ($mime, $file, $desc) = ($1, DecodeString($et, $2, $enc), DecodeString($et, $3, $enc));
1633
+ $et->HandleTag($tagTablePtr, 'GEOB-Mime', $mime) if length $mime;
1634
+ $et->HandleTag($tagTablePtr, 'GEOB-File', $file) if length $file;
1635
+ $et->HandleTag($tagTablePtr, 'GEOB-Desc', $desc) if length $desc;
1636
+ if ($$tagTablePtr{$mime}) {
1637
+ $et->HandleTag($tagTablePtr, $mime, undef,
1638
+ DataPt => $dataPt,
1639
+ Start => 0,
1640
+ Size => length($$dataPt),
1641
+ );
1642
+ } else {
1643
+ $et->HandleTag($tagTablePtr, 'GEOB-Data', $dataPt);
1644
+ }
1645
+ return 1;
1646
+ }
1647
+
1585
1648
  #------------------------------------------------------------------------------
1586
1649
  # Extract ID3 information from an MP3 audio file
1587
1650
  # Inputs: 0) ExifTool object reference, 1) dirInfo reference
@@ -122,7 +122,7 @@ sub ProcessIND($$)
122
122
  # memory troubles (with its apparent 1 GB limit) if the XMP is larger
123
123
  # than about 400 MB, so guard against this
124
124
  if ($len > 300 * 1024 * 1024) {
125
- my $msg = sprintf('Insanely large XMP (%.0f MB)', $len / (1024 * 1024));
125
+ my $msg = sprintf('Insanely large XMP (%.0f MiB)', $len / (1024 * 1024));
126
126
  if ($outfile) {
127
127
  $et->Error($msg, 2) and $err = 1, last;
128
128
  } elsif ($et->Options('IgnoreMinorErrors')) {
@@ -251,7 +251,7 @@ sub ProcessJPEG_HDR($$$);
251
251
  Name => 'JUMBF',
252
252
  Condition => '$$valPt =~ /^JP/',
253
253
  SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::Main' },
254
- # Note: The recommended options for reading C2PA JUMBF metadata are "-G3 -b -j -u"
254
+ # Note: The suggested options for reading C2PA CAI JUMBF metadata are "-G3 -b -j -u"
255
255
  }],
256
256
  APP12 => [{
257
257
  Name => 'PictureInfo',
@@ -89,12 +89,14 @@ my %uuid = (
89
89
  # JPEG2000 codestream markers (ref ISO/IEC FCD15444-1/2)
90
90
  my %j2cMarker = (
91
91
  0x4f => 'SOC', # start of codestream
92
+ # 0x50 - seen in JPH codestream
92
93
  0x51 => 'SIZ', # image and tile size
93
94
  0x52 => 'COD', # coding style default
94
95
  0x53 => 'COC', # coding style component
95
96
  0x55 => 'TLM', # tile-part lengths
96
97
  0x57 => 'PLM', # packet length, main header
97
98
  0x58 => 'PLT', # packet length, tile-part header
99
+ # 0x59 - seen in JPH codestream
98
100
  0x5c => 'QCD', # quantization default
99
101
  0x5d => 'QCC', # quantization component
100
102
  0x5e => 'RGN', # region of interest
@@ -128,12 +130,21 @@ my %j2cMarker = (
128
130
  WRITE_PROC => \&ProcessJpeg2000Box,
129
131
  PREFERRED => 1, # always add these tags when writing
130
132
  NOTES => q{
131
- The tags below are found in JPEG 2000 images and the JUMBF metadata in JPEG
132
- images, but not all of these are extracted. Note that ExifTool currently
133
- writes only EXIF, IPTC and XMP tags in Jpeg2000 images, and EXIF and XMP in
134
- JXL images. ExifTool will read/write Brotli-compressed EXIF and XMP in JXL
135
- images, but the API L<Compress|../ExifTool.html#Compress> option must be set to create new EXIF and XMP
136
- in compressed format.
133
+ The tags below are found in JPEG 2000 images and the C2PA CAI JUMBF metadata
134
+ in various file types (see below). Note that ExifTool currently writes only
135
+ EXIF, IPTC and XMP tags in Jpeg2000 images, and EXIF and XMP in JXL images.
136
+ ExifTool will read/write Brotli-compressed EXIF and XMP in JXL images, but
137
+ the API L<Compress|../ExifTool.html#Compress> option must be set to create new EXIF and XMP in compressed
138
+ format.
139
+
140
+ C2PA (Coalition for Content Provenance and Authenticity) CAI (Content
141
+ Authenticity Initiative) JUMBF (JPEG Universal Metadata Box Format) metdata
142
+ is currently extracted from JPEG, PNG, TIFF-based (eg. TIFF, DNG),
143
+ QuickTime-based (eg. MP4, MOV, HEIF, AVIF), RIFF-based (eg. WAV, AVI, WebP),
144
+ GIF files and ID3v2 metadata. The suggested ExifTool command-line arguments
145
+ for reading C2PA metadata are C<-jumbf:all -G3 -b -j -u -struct>. This
146
+ metadata may be deleted from writable JPEG, PNG, WebP, TIFF-based, and
147
+ QuickTime-based files by deleting the JUMBF group with C<-jumbf:all=>.
137
148
  },
138
149
  #
139
150
  # NOTE: ONLY TAGS WITH "Format" DEFINED ARE EXTRACTED!
@@ -345,13 +356,6 @@ my %j2cMarker = (
345
356
  Start => '$valuePtr + 16',
346
357
  },
347
358
  },
348
- {
349
- Name => 'UUID-Signature', # (seen in JUMB data of JPEG images)
350
- # (may be able to remove this when JUMBF specification is finalized)
351
- Condition => '$$valPt=~/^casg\x00\x11\x00\x10\x80\x00\x00\xaa\x00\x38\x9b\x71/',
352
- Format => 'undef',
353
- ValueConv => 'substr($val,16)',
354
- },
355
359
  {
356
360
  Name => 'UUID-C2PAClaimSignature', # (seen in incorrectly-formatted JUMB data of JPEG images)
357
361
  # (may be able to remove this when JUMBF specification is finalized)
@@ -361,6 +365,13 @@ my %j2cMarker = (
361
365
  Start => '$valuePtr + 16',
362
366
  },
363
367
  },
368
+ {
369
+ Name => 'UUID-Signature', # (seen in JUMB data of JPEG images)
370
+ # (may be able to remove this when JUMBF specification is finalized)
371
+ Condition => '$$valPt=~/^casg\x00\x11\x00\x10\x80\x00\x00\xaa\x00\x38\x9b\x71/',
372
+ Format => 'undef',
373
+ ValueConv => 'substr($val,16)',
374
+ },
364
375
  {
365
376
  Name => 'UUID-Unknown',
366
377
  },
@@ -549,6 +560,7 @@ my %j2cMarker = (
549
560
  'jpm ' => 'JPEG 2000 Compound Image (.JPM)', # image/jpm
550
561
  'jpx ' => 'JPEG 2000 with extensions (.JPX)', # image/jpx
551
562
  'jxl ' => 'JPEG XL Image (.JXL)', # image/jxl
563
+ 'jph ' => 'High-throughput JPEG 2000 (.JPH)', # image/jph
552
564
  },
553
565
  },
554
566
  1 => {
@@ -993,10 +1005,12 @@ sub ProcessJpeg2000Box($$$)
993
1005
  my $dirLen = $$dirInfo{DirLen} || 0;
994
1006
  my $dirStart = $$dirInfo{DirStart} || 0;
995
1007
  my $base = $$dirInfo{Base} || 0;
996
- my $raf = $$dirInfo{RAF};
997
1008
  my $outfile = $$dirInfo{OutFile};
998
1009
  my $dirEnd = $dirStart + $dirLen;
999
- my ($err, $outBuff, $verbose, $doColour, $hash);
1010
+ my ($err, $outBuff, $verbose, $doColour, $hash, $raf);
1011
+
1012
+ # read from RAF unless reading from buffer
1013
+ $raf = $$dirInfo{RAF} unless $dataPt;
1000
1014
 
1001
1015
  if ($outfile) {
1002
1016
  unless ($raf) {
@@ -1516,6 +1530,7 @@ sub ProcessJP2($$)
1516
1530
  $fileType = 'JPX' if $1 eq 'jpx ';
1517
1531
  $fileType = 'JPM' if $1 eq 'jpm ';
1518
1532
  $fileType = 'JXL' if $1 eq 'jxl ';
1533
+ $fileType = 'JPH' if $1 eq 'jph ';
1519
1534
  }
1520
1535
  $raf->Seek(-length($buff), 1) if defined $buff;
1521
1536
  $et->SetFileType($fileType);
@@ -21,7 +21,7 @@ sub ProcessKodakPatch($$$);
21
21
  sub WriteUnknownOrPreview($$$);
22
22
  sub FixLeicaBase($$;$);
23
23
 
24
- $VERSION = '2.14';
24
+ $VERSION = '2.15';
25
25
 
26
26
  my $debug; # set to 1 to enable debugging code
27
27
 
@@ -694,7 +694,7 @@ my $debug; # set to 1 to enable debugging code
694
694
  Name => 'MakerNoteLeica8', # used by the Q (Type 116)
695
695
  # (Q (Typ 116) starts with "LEICA\0\x08\0", Make is "LEICA CAMERA AG")
696
696
  # (SL (Typ 601) and CL start with "LEICA\0\x09\0", Make is "LEICA CAMERA AG")
697
- Condition => '$$valPt =~ /^LEICA\0[\x08\x09]\0/',
697
+ Condition => '$$valPt =~ /^LEICA\0[\x08\x09\x0a]\0/',
698
698
  SubDirectory => {
699
699
  TagTable => 'Image::ExifTool::Panasonic::Leica5',
700
700
  Start => '$valuePtr + 8',
@@ -65,7 +65,7 @@ use Image::ExifTool::Exif;
65
65
  use Image::ExifTool::GPS;
66
66
  use Image::ExifTool::XMP;
67
67
 
68
- $VERSION = '4.25';
68
+ $VERSION = '4.27';
69
69
 
70
70
  sub LensIDConv($$$);
71
71
  sub ProcessNikonAVI($$$);
@@ -676,6 +676,7 @@ sub GetAFPointGrid($$;$);
676
676
  '07 40 30 45 2D 35 03 02.2' => 'Voigtlander Ultragon 19-35mm F3.5-4.5 VMV', #NJ
677
677
  '71 48 64 64 24 24 00 00' => 'Voigtlander APO-Skopar 90mm F2.8 SL IIs', #30
678
678
  'FD 00 50 50 18 18 DF 00' => 'Voigtlander APO-Lanthar 50mm F2 Aspherical', #35
679
+ 'FD 00 44 44 18 18 DF 00' => 'Voigtlander APO-Lanthar 35mm F2', #30
679
680
  #
680
681
  '00 40 2D 2D 2C 2C 00 00' => 'Carl Zeiss Distagon T* 3.5/18 ZF.2',
681
682
  '00 48 27 27 24 24 00 00' => 'Carl Zeiss Distagon T* 2.8/15 ZF.2', #MykytaKozlov
@@ -961,8 +962,8 @@ my %imageAreaZ9b = (
961
962
  );
962
963
 
963
964
  my %infoZSeries = (
964
- Condition => '$$self{Model} =~ /^NIKON Z (30|5|50|6|6_2|7|7_2|8|fc|9)\b/i',
965
- Notes => 'Z Series cameras thru July 2023',
965
+ Condition => '$$self{Model} =~ /^NIKON Z (30|5|50|6|6_2|7|7_2|8|f|fc|9)\b/i',
966
+ Notes => 'Z Series cameras thru October 2023',
966
967
  );
967
968
 
968
969
  my %iSOAutoHiLimitZ7 = (
@@ -1188,6 +1189,7 @@ my %subjectDetectionZ9 = (
1188
1189
  2 => 'People',
1189
1190
  3 => 'Animals',
1190
1191
  4 => 'Vehicles',
1192
+ 5 => 'Birds',
1191
1193
  6 => 'Airplanes',
1192
1194
  );
1193
1195
 
@@ -2421,8 +2423,8 @@ my %base64coord = (
2421
2423
  },
2422
2424
  },
2423
2425
  { # (Z6_2 firmware version 1.00 and Z7II firmware versions 1.00 & 1.01, ref 28)
2424
- # 0800=Z6/Z7 0801=Z50 0802=Z5 0803=Z6II/Z7II 0804=Zfc 0807=Z30
2425
- Condition => '$$valPt =~ /^080[012347]/',
2426
+ # 0800=Z6/Z7 0801=Z50 0802=Z5 0803=Z6II/Z7II 0804=Zfc 0807=Z30 0808=Zf
2427
+ Condition => '$$valPt =~ /^080[0123478]/',
2426
2428
  Name => 'ShotInfoZ7II',
2427
2429
  SubDirectory => {
2428
2430
  TagTable => 'Image::ExifTool::Nikon::ShotInfoZ7II',
@@ -2481,7 +2483,7 @@ my %base64coord = (
2481
2483
  },
2482
2484
  0x0094 => { Name => 'SaturationAdj', Writable => 'int16s' },
2483
2485
  0x0095 => { Name => 'NoiseReduction', Writable => 'string' }, # ("Off" or "FPNR"=long exposure NR)
2484
- 0x0096 => {
2486
+ 0x0096 => { # (not found in NRW files, but also not in all NEF's)
2485
2487
  Name => 'NEFLinearizationTable', # same table as DNG LinearizationTable (ref JD)
2486
2488
  Writable => 'undef',
2487
2489
  Flags => [ 'Binary', 'Protected' ],
@@ -2580,9 +2582,21 @@ my %base64coord = (
2580
2582
  DirOffset => 4,
2581
2583
  },
2582
2584
  },
2583
- { # (D5200/D7100=0218, D5300=0219, D610/Df=0220, D3300=0221, CoolpixA=0601)
2584
- Name => 'ColorBalanceUnknown02',
2585
- Condition => '$$valPt =~ /^0[26]/',
2585
+ { #PH (NC)
2586
+ # (D5300=0219, D3300=0221, D4S=0222, D750/D810=0223, D3400/D3500/D5500/D5600/D7200=0224)
2587
+ Condition => '$$valPt =~ /^02(19|2[1234])/',
2588
+ Name => 'ColorBalance0219',
2589
+ SubDirectory => {
2590
+ TagTable => 'Image::ExifTool::Nikon::ColorBalance2',
2591
+ ProcessProc => \&ProcessNikonEncrypted,
2592
+ WriteProc => \&ProcessNikonEncrypted,
2593
+ DecryptStart => 4,
2594
+ DirOffset => 0x7c,
2595
+ },
2596
+ },
2597
+ { # (D610/Df=0220, CoolpixA=0601)
2598
+ Name => 'ColorBalanceUnknown1',
2599
+ Condition => '$$valPt =~ /^0(220|6)/',
2586
2600
  SubDirectory => {
2587
2601
  TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown',
2588
2602
  ProcessProc => \&ProcessNikonEncrypted,
@@ -2590,11 +2604,12 @@ my %base64coord = (
2590
2604
  DecryptStart => 284,
2591
2605
  },
2592
2606
  },
2593
- { # (1J1/1J2/1V1=0400, 1V2=0401, 1J3/1S1=0402, 1AW1=0403, Z6/Z7=0800)
2594
- Name => 'ColorBalanceUnknown04',
2595
- Condition => '$$valPt =~ /^0[48]/',
2607
+ { # (D5200/D7200=0218, D5/D500=0225, D7500=0226, D850=0227, D6/D780=0228,
2608
+ # 1J1/1J2/1V1=0400, 1V2=0401, 1J3/1S1=0402, 1AW1=0403, Z6/Z7=0800)
2609
+ Name => 'ColorBalanceUnknown2',
2610
+ Condition => '$$valPt =~ /^0(18|[248])/',
2596
2611
  SubDirectory => {
2597
- TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown',
2612
+ TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown2',
2598
2613
  ProcessProc => \&ProcessNikonEncrypted,
2599
2614
  WriteProc => \&ProcessNikonEncrypted, # (necessary to recrypt this if serial number changed)
2600
2615
  DecryptStart => 4,
@@ -4586,7 +4601,7 @@ my %base64coord = (
4586
4601
  RawConv => '$$self{AFInfo2Version} = $val',
4587
4602
  },
4588
4603
  5 => { #28
4589
- Name => 'AFAreaMode', #reflects the mode active when the shutter is tripped, not the position of the Focus Mode button (which is recorded in MenuSettingsZ9 tag also named AfAreaMode)
4604
+ Name => 'AFAreaMode', #reflects the mode active when the shutter is tripped, not the position of the Focus Mode button (which is recorded in MenuSettingsZ9 tag also named AfAreaMode)
4590
4605
  PrintConv => {
4591
4606
  192 => 'Pinpoint',
4592
4607
  193 => 'Single',
@@ -4602,7 +4617,7 @@ my %base64coord = (
4602
4617
  },
4603
4618
  10 => {
4604
4619
  Name => 'AFPointsUsed',
4605
- Condition => '$$self{AFAreaMode} == 6', #only valid for Auto AF Area mode. Other modes handled via AFAreaXPosition/AFAreaYPosition
4620
+ Condition => 'defined $$self{AFAreaMode} and $$self{AFAreaMode} == 6', #only valid for Auto AF Area mode. Other modes handled via AFAreaXPosition/AFAreaYPosition
4606
4621
  Format => 'undef[51]',
4607
4622
  ValueConv => 'join(" ", unpack("H2"x51, $val))',
4608
4623
  ValueConvInv => '$val=~tr/ //d; pack("H*",$val)',
@@ -4954,6 +4969,16 @@ my %nrwLevels = (
4954
4969
  },
4955
4970
  );
4956
4971
 
4972
+ %Image::ExifTool::Nikon::ColorBalanceUnknown2 = (
4973
+ %binaryDataAttrs,
4974
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
4975
+ FORMAT => 'int16u',
4976
+ 0 => {
4977
+ Name => 'ColorBalanceVersion',
4978
+ Format => 'undef[4]',
4979
+ },
4980
+ );
4981
+
4957
4982
  %Image::ExifTool::Nikon::Type2 = (
4958
4983
  WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
4959
4984
  CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
@@ -5440,6 +5465,13 @@ my %nikonFocalConversions = (
5440
5465
  37 => 'Nikkor Z 600mm f/4 TC VR S', #28
5441
5466
  38 => 'Nikkor Z 85mm f/1.2 S', #28
5442
5467
  39 => 'Nikkor Z 17-28mm f/2.8', #IB
5468
+ 40 => 'NIKKOR Z 26mm f/2.8', #28
5469
+ 41 => 'NIKKOR Z DX 12-28mm f/3.5-5.6 PZ VR', #28
5470
+ 42 => 'Nikkor Z 180-600mm f/5.6-6.3 VR', #30
5471
+ 43 => 'NIKKOR Z DX 24mm f/1.7', #28
5472
+ 44 => 'NIKKOR Z 70-180mm f/2.8', #28
5473
+ 45 => 'NIKKOR Z 600mm f/6.3 VR S', #28
5474
+ 46 => 'Nikkor Z 135mm f/1.8 S Plena', #28
5443
5475
  32768 => 'Nikkor Z 400mm f/2.8 TC VR S TC-1.4x', #28
5444
5476
  32769 => 'Nikkor Z 600mm f/4 TC VR S TC-1.4x', #28
5445
5477
  },
@@ -6056,6 +6088,24 @@ my %nikonFocalConversions = (
6056
6088
  Format => 'int32u',
6057
6089
  Priority => 0,
6058
6090
  },
6091
+ 671.1 => { # 0x29f
6092
+ Name => 'JPGCompression',
6093
+ Mask => 0x40,
6094
+ PrintConv => {
6095
+ 0 => 'Size Priority',
6096
+ 1 => 'Optimal Quality',
6097
+ },
6098
+ },
6099
+ # this works for one set of D3S samples, but is 0 in some others
6100
+ #671.2 => { # 0x29f
6101
+ # Name => 'Quality',
6102
+ # Mask => 0x03,
6103
+ # PrintConv => {
6104
+ # 1 => 'Fine',
6105
+ # 2 => 'Normal',
6106
+ # 3 => 'Basic',
6107
+ # },
6108
+ #},
6059
6109
  0x2ce => { #(NC)
6060
6110
  Name => 'CustomSettingsD3S',
6061
6111
  Format => 'undef[27]',
@@ -8168,7 +8218,7 @@ my %nikonFocalConversions = (
8168
8218
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
8169
8219
  VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
8170
8220
  DATAMEMBER => [ 0x04 ],
8171
- IS_SUBDIR => [ 0x30, 0x38, 0x98, 0xa0 ],
8221
+ IS_SUBDIR => [ 0x30, 0x38, 0x88, 0x98, 0xa0 ],
8172
8222
  WRITABLE => 1,
8173
8223
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8174
8224
  NOTES => 'These tags are extracted from encrypted data in images from the Z7II.',
@@ -8218,9 +8268,19 @@ my %nikonFocalConversions = (
8218
8268
  Start => '$val',
8219
8269
  }
8220
8270
  },
8271
+ 0x88 => {
8272
+ Name => 'OrientationOffset',
8273
+ Format => 'int32u',
8274
+ Condition => '$$self{Model} =~ /^NIKON Z f\b/i',
8275
+ SubDirectory => {
8276
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
8277
+ Start => '$val',
8278
+ }
8279
+ },
8221
8280
  0x98 => {
8222
8281
  Name => 'OrientationOffset',
8223
8282
  Format => 'int32u',
8283
+ Condition => '$$self{Model} =~ /^NIKON Z (30|5|50|6|6_2|7|7_2|8|fc)\b/i', #models other then the Z f
8224
8284
  SubDirectory => {
8225
8285
  TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
8226
8286
  Start => '$val',
@@ -8487,7 +8547,7 @@ my %nikonFocalConversions = (
8487
8547
  0x002a => {
8488
8548
  Name => 'IntervalFrame',
8489
8549
  RawConv => '$$self{IntervalFrame} = $val',
8490
- Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8550
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{IntervalShooting} > 0', #not valid for C30/C60/C120
8491
8551
  Format => 'int16u',
8492
8552
  Hidden => 1,
8493
8553
  },
@@ -8500,7 +8560,7 @@ my %nikonFocalConversions = (
8500
8560
  DATAMEMBER => [ 0x0bea, 0x0beb ],
8501
8561
  0x0be8 => {
8502
8562
  Name => 'AFAreaInitialXPosition', #stored as a representation of the horizontal position of the center of the portion of the focus box positioned top left when in Wide Area (L/S/C1/C2) focus modes (before subject detection potentially refines focus)
8503
- Condition => '$$self{ShutterMode} ne 96 and $$self{AFAreaMode} < 2 ', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8563
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and defined $$self{AFAreaMode} and $$self{AFAreaMode} < 2 ', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8504
8564
  Format => 'int8s',
8505
8565
  PrintConv => q{
8506
8566
  #in FX mode and Single-point, the 29 horizontal focus points are spaced 259 pixels apart starting at pixel 502 and ending at 7754. Spacing is the same for Wide(L/C1/C2) with different start points.
@@ -8562,7 +8622,7 @@ my %nikonFocalConversions = (
8562
8622
  },
8563
8623
  0x0be9 => {
8564
8624
  Name =>'AFAreaInitialYPosition', #stored as a representation of the vertical position of the center of the portion of the focus box positioned top left when in Wide Area (L/S/C1/C2) focus modes (before subject detection potentially refines focus)
8565
- Condition => '$$self{ShutterMode} ne 96 and $$self{AFAreaMode} < 2', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8625
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and defined $$self{AFAreaMode} and $$self{AFAreaMode} < 2', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8566
8626
  Format => 'int8s',
8567
8627
  PrintConv => q{
8568
8628
  #in FX mode and Single-point, the 17 vertical focus points are spaced 291 pixels apart starting at pixel 424 and ending at 5080. Spacing is the same for Wide(L/C1/C2)
@@ -8626,13 +8686,13 @@ my %nikonFocalConversions = (
8626
8686
  },
8627
8687
  0x0bea => {
8628
8688
  Name => 'AFAreaInitialWidth',
8629
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8689
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8630
8690
  ValueConv => '$$self{VALUE}{PhotoShootingMenuBankImageArea} eq 0 ? $val : int($val * 2 / 3)', #DX mode requires scaling down TODO: add support ImageAreas 1:1 and 16:9
8631
8691
  RawConv => '$$self{AFAreaInitialWidth} = 1 + int ($val / 4)', #convert from [3, 11, 19, 35, 51, 75] to [1, 3, 5, 9 13, 19] to match camera options for C1/C2 focus modes .. input/output of 11/3 is for Wide(S)
8632
8692
  },
8633
8693
  0x0beb => {
8634
8694
  Name => 'AFAreaInitialHeight',
8635
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8695
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8636
8696
  ValueConv => '$$self{VALUE}{PhotoShootingMenuBankImageArea} eq 0 ? $val : int($val * 2 / 3)', #DX mode requires scaling down TODO: add support ImageAreas 1:1 and 16:9
8637
8697
  RawConv => '$$self{AFAreaInitialHeight} = 1 + int ($val / 7) ', #convert from [6, 20, 33, 46, 73] to [1, 3, 5, 7, 11] to match camera options for C1/C2 focus modes .. input/output of 33/5 is for Wide(L)
8638
8698
  },
@@ -8848,7 +8908,7 @@ my %nikonFocalConversions = (
8848
8908
  %binaryDataAttrs,
8849
8909
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8850
8910
  DATAMEMBER => [ 90, 176, 180, 328, 352, 858 ],
8851
- NOTES => 'These tags are used by the Z5, Z6, Z7, Z6II, Z7II, Z50 and Zfc.',
8911
+ NOTES => 'These tags are used by the Z5, Z6, Z7, Z6II, Z7II, Z50, Zfc and Zf.',
8852
8912
  #48 SelfTimer' #0=> no 1=> yes works for Z7II firmware 1.40, but not 1.30. Follow-up required.
8853
8913
  90 => {
8854
8914
  Name => 'SingleFrame', #0=> Single Frame 1=> one of the continuous modes
@@ -40,7 +40,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
40
40
  use Image::ExifTool::Exif;
41
41
  use Image::ExifTool::APP12;
42
42
 
43
- $VERSION = '2.81';
43
+ $VERSION = '2.82';
44
44
 
45
45
  sub PrintLensInfo($$$);
46
46
 
@@ -186,7 +186,9 @@ my %olympusLensTypes = (
186
186
  '2 36 10' => 'Leica DG Elmarit 200mm F2.8 Power OIS', #IB
187
187
  '2 37 10' => 'Leica DG Vario-Elmarit 50-200mm F2.8-4 Asph. Power OIS', #IB
188
188
  '2 38 10' => 'Leica DG Vario-Summilux 10-25mm F1.7 Asph.', #IB
189
+ '2 39 10' => 'Leica DG Summilux 25mm F1.4 II Asph.', #forum15345
189
190
  '2 40 10' => 'Leica DG Vario-Summilux 25-50mm F1.7 Asph.', #IB (H-X2550)
191
+ '2 41 10' => 'Leica DG Summilux 9mm F1.7 Asph.', #forum15345
190
192
  '3 01 00' => 'Leica D Vario Elmarit 14-50mm F2.8-3.5 Asph.', #11
191
193
  '3 02 00' => 'Leica D Summilux 25mm F1.4 Asph.', #11
192
194
  # Tamron lenses
@@ -358,6 +360,7 @@ my %olympusCameraTypes = (
358
360
  D4521 => 'SH-25MR',
359
361
  D4523 => 'SP-720UZ',
360
362
  D4529 => 'VG170',
363
+ D4530 => 'VH210',
361
364
  D4531 => 'XZ-2',
362
365
  D4535 => 'SP-620UZ',
363
366
  D4536 => 'TG-320',
@@ -383,9 +386,11 @@ my %olympusCameraTypes = (
383
386
  D4585 => 'SH-2 / SH-3',
384
387
  D4586 => 'TG-4',
385
388
  D4587 => 'TG-860',
389
+ D4590 => 'TG-TRACKER',
386
390
  D4591 => 'TG-870',
387
391
  D4593 => 'TG-5', #IB
388
392
  D4603 => 'TG-6', #IB
393
+ D4605 => 'TG-7',
389
394
  D4809 => 'C2500L',
390
395
  D4842 => 'E-10',
391
396
  D4856 => 'C-1',
@@ -431,6 +436,7 @@ my %olympusCameraTypes = (
431
436
  S0076 => 'E-PL9', #IB
432
437
  S0080 => 'E-M1X', #IB
433
438
  S0085 => 'E-PL10', #IB
439
+ S0088 => 'E-M10MarkIV',
434
440
  S0089 => 'E-M5MarkIII',
435
441
  S0092 => 'E-M1MarkIII', #IB
436
442
  S0093 => 'E-P7', #IB