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.
- checksums.yaml +4 -4
- data/bin/Changes +79 -10
- data/bin/MANIFEST +5 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +7 -7
- data/bin/exiftool +32 -27
- data/bin/lib/Image/ExifTool/CBOR.pm +18 -2
- data/bin/lib/Image/ExifTool/Canon.pm +87 -16
- data/bin/lib/Image/ExifTool/DJI.pm +3 -2
- data/bin/lib/Image/ExifTool/DNG.pm +25 -2
- data/bin/lib/Image/ExifTool/EXE.pm +54 -6
- data/bin/lib/Image/ExifTool/Exif.pm +175 -14
- data/bin/lib/Image/ExifTool/FujiFilm.pm +158 -20
- data/bin/lib/Image/ExifTool/GIF.pm +5 -1
- data/bin/lib/Image/ExifTool/Geotag.pm +16 -11
- data/bin/lib/Image/ExifTool/ID3.pm +70 -7
- data/bin/lib/Image/ExifTool/InDesign.pm +1 -1
- data/bin/lib/Image/ExifTool/JPEG.pm +1 -1
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +30 -15
- data/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +82 -22
- data/bin/lib/Image/ExifTool/Olympus.pm +7 -1
- data/bin/lib/Image/ExifTool/PNG.pm +3 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +22 -9
- data/bin/lib/Image/ExifTool/Pentax.pm +6 -1
- data/bin/lib/Image/ExifTool/PhotoMechanic.pm +2 -1
- data/bin/lib/Image/ExifTool/QuickTime.pm +92 -55
- data/bin/lib/Image/ExifTool/README +14 -5
- data/bin/lib/Image/ExifTool/RIFF.pm +60 -10
- data/bin/lib/Image/ExifTool/Sony.pm +152 -46
- data/bin/lib/Image/ExifTool/TagLookup.pm +6955 -6713
- data/bin/lib/Image/ExifTool/TagNames.pod +878 -334
- data/bin/lib/Image/ExifTool/Text.pm +4 -5
- data/bin/lib/Image/ExifTool/Validate.pm +23 -20
- data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +2 -2
- data/bin/lib/Image/ExifTool/WriteExif.pl +14 -4
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +3 -0
- data/bin/lib/Image/ExifTool/WriteRIFF.pl +31 -6
- data/bin/lib/Image/ExifTool/Writer.pl +40 -14
- data/bin/lib/Image/ExifTool/XISF.pm +185 -0
- data/bin/lib/Image/ExifTool/XMP.pm +67 -2
- data/bin/lib/Image/ExifTool/XMP2.pl +35 -0
- data/bin/lib/Image/ExifTool.pm +92 -45
- data/bin/lib/Image/ExifTool.pod +14 -8
- data/bin/perl-Image-ExifTool.spec +6 -6
- data/lib/exiftool_vendored/version.rb +1 -1
- 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.
|
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.
|
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
|
-
|
1200
|
-
|
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
|
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.
|
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 => \&
|
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
|
-
|
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 => \&
|
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 => \&
|
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
|
-
$
|
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
|
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
|
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
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
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.
|
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.
|
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
|
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[
|
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
|
-
{ # (
|
2584
|
-
|
2585
|
-
Condition => '$$valPt =~ /^
|
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
|
-
{ # (
|
2594
|
-
|
2595
|
-
|
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::
|
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',
|
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',
|
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{
|
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
|
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.
|
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
|