exiftool_vendored 12.67.0 → 12.70.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +79 -10
  3. data/bin/MANIFEST +5 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +7 -7
  7. data/bin/exiftool +32 -27
  8. data/bin/lib/Image/ExifTool/CBOR.pm +18 -2
  9. data/bin/lib/Image/ExifTool/Canon.pm +87 -16
  10. data/bin/lib/Image/ExifTool/DJI.pm +3 -2
  11. data/bin/lib/Image/ExifTool/DNG.pm +25 -2
  12. data/bin/lib/Image/ExifTool/EXE.pm +54 -6
  13. data/bin/lib/Image/ExifTool/Exif.pm +175 -14
  14. data/bin/lib/Image/ExifTool/FujiFilm.pm +158 -20
  15. data/bin/lib/Image/ExifTool/GIF.pm +5 -1
  16. data/bin/lib/Image/ExifTool/Geotag.pm +16 -11
  17. data/bin/lib/Image/ExifTool/ID3.pm +70 -7
  18. data/bin/lib/Image/ExifTool/InDesign.pm +1 -1
  19. data/bin/lib/Image/ExifTool/JPEG.pm +1 -1
  20. data/bin/lib/Image/ExifTool/Jpeg2000.pm +30 -15
  21. data/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
  22. data/bin/lib/Image/ExifTool/Nikon.pm +82 -22
  23. data/bin/lib/Image/ExifTool/Olympus.pm +7 -1
  24. data/bin/lib/Image/ExifTool/PNG.pm +3 -1
  25. data/bin/lib/Image/ExifTool/Panasonic.pm +22 -9
  26. data/bin/lib/Image/ExifTool/Pentax.pm +6 -1
  27. data/bin/lib/Image/ExifTool/PhotoMechanic.pm +2 -1
  28. data/bin/lib/Image/ExifTool/QuickTime.pm +92 -55
  29. data/bin/lib/Image/ExifTool/README +14 -5
  30. data/bin/lib/Image/ExifTool/RIFF.pm +60 -10
  31. data/bin/lib/Image/ExifTool/Sony.pm +152 -46
  32. data/bin/lib/Image/ExifTool/TagLookup.pm +6955 -6713
  33. data/bin/lib/Image/ExifTool/TagNames.pod +878 -334
  34. data/bin/lib/Image/ExifTool/Text.pm +4 -5
  35. data/bin/lib/Image/ExifTool/Validate.pm +23 -20
  36. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +2 -2
  37. data/bin/lib/Image/ExifTool/WriteExif.pl +14 -4
  38. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +3 -0
  39. data/bin/lib/Image/ExifTool/WriteRIFF.pl +31 -6
  40. data/bin/lib/Image/ExifTool/Writer.pl +40 -14
  41. data/bin/lib/Image/ExifTool/XISF.pm +185 -0
  42. data/bin/lib/Image/ExifTool/XMP.pm +67 -2
  43. data/bin/lib/Image/ExifTool/XMP2.pl +35 -0
  44. data/bin/lib/Image/ExifTool.pm +92 -45
  45. data/bin/lib/Image/ExifTool.pod +14 -8
  46. data/bin/perl-Image-ExifTool.spec +6 -6
  47. data/lib/exiftool_vendored/version.rb +1 -1
  48. metadata +4 -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