exiftool_vendored 12.17.1 → 12.32.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.
- checksums.yaml +4 -4
- data/bin/Changes +225 -1
- data/bin/MANIFEST +23 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +45 -43
- data/bin/arg_files/xmp2exif.args +2 -1
- data/bin/config_files/acdsee.config +193 -6
- data/bin/config_files/convert_regions.config +25 -14
- data/bin/config_files/cuepointlist.config +70 -0
- data/bin/config_files/example.config +2 -9
- data/bin/exiftool +142 -87
- data/bin/fmt_files/gpx.fmt +2 -2
- data/bin/fmt_files/gpx_wpt.fmt +2 -2
- data/bin/fmt_files/kml.fmt +1 -1
- data/bin/fmt_files/kml_track.fmt +1 -1
- data/bin/lib/Image/ExifTool/Apple.pm +3 -2
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +30 -12
- data/bin/lib/Image/ExifTool/CBOR.pm +277 -0
- data/bin/lib/Image/ExifTool/Canon.pm +49 -18
- data/bin/lib/Image/ExifTool/DJI.pm +6 -6
- data/bin/lib/Image/ExifTool/DPX.pm +13 -2
- data/bin/lib/Image/ExifTool/DjVu.pm +6 -5
- data/bin/lib/Image/ExifTool/Exif.pm +28 -11
- data/bin/lib/Image/ExifTool/FITS.pm +13 -2
- data/bin/lib/Image/ExifTool/FlashPix.pm +35 -10
- data/bin/lib/Image/ExifTool/FujiFilm.pm +19 -8
- data/bin/lib/Image/ExifTool/GPS.pm +22 -11
- data/bin/lib/Image/ExifTool/Geotag.pm +13 -2
- data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +2 -2
- data/bin/lib/Image/ExifTool/ID3.pm +15 -3
- data/bin/lib/Image/ExifTool/JPEG.pm +74 -4
- data/bin/lib/Image/ExifTool/JSON.pm +27 -4
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +393 -16
- data/bin/lib/Image/ExifTool/LIF.pm +153 -0
- data/bin/lib/Image/ExifTool/Lang/nl.pm +60 -59
- data/bin/lib/Image/ExifTool/M2TS.pm +137 -5
- data/bin/lib/Image/ExifTool/MIE.pm +4 -3
- data/bin/lib/Image/ExifTool/MRC.pm +341 -0
- data/bin/lib/Image/ExifTool/MWG.pm +3 -3
- data/bin/lib/Image/ExifTool/MXF.pm +1 -1
- data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
- data/bin/lib/Image/ExifTool/Microsoft.pm +298 -82
- data/bin/lib/Image/ExifTool/Nikon.pm +19 -8
- data/bin/lib/Image/ExifTool/NikonSettings.pm +28 -11
- data/bin/lib/Image/ExifTool/Olympus.pm +6 -3
- data/bin/lib/Image/ExifTool/Other.pm +93 -0
- data/bin/lib/Image/ExifTool/PDF.pm +9 -12
- data/bin/lib/Image/ExifTool/PNG.pm +8 -7
- data/bin/lib/Image/ExifTool/Panasonic.pm +28 -3
- data/bin/lib/Image/ExifTool/Pentax.pm +28 -5
- data/bin/lib/Image/ExifTool/PhaseOne.pm +4 -3
- data/bin/lib/Image/ExifTool/Photoshop.pm +6 -0
- data/bin/lib/Image/ExifTool/QuickTime.pm +247 -88
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +283 -141
- data/bin/lib/Image/ExifTool/README +3 -0
- data/bin/lib/Image/ExifTool/RIFF.pm +89 -12
- data/bin/lib/Image/ExifTool/Samsung.pm +48 -10
- data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -0
- data/bin/lib/Image/ExifTool/Sony.pm +237 -78
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +1 -0
- data/bin/lib/Image/ExifTool/TagLookup.pm +4125 -4028
- data/bin/lib/Image/ExifTool/TagNames.pod +644 -286
- data/bin/lib/Image/ExifTool/Torrent.pm +18 -11
- data/bin/lib/Image/ExifTool/WriteExif.pl +1 -1
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
- data/bin/lib/Image/ExifTool/WritePNG.pl +2 -0
- data/bin/lib/Image/ExifTool/WritePostScript.pl +1 -0
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +55 -21
- data/bin/lib/Image/ExifTool/WriteXMP.pl +7 -3
- data/bin/lib/Image/ExifTool/Writer.pl +47 -10
- data/bin/lib/Image/ExifTool/XMP.pm +39 -14
- data/bin/lib/Image/ExifTool/XMP2.pl +2 -1
- data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
- data/bin/lib/Image/ExifTool/ZISRAW.pm +121 -2
- data/bin/lib/Image/ExifTool.pm +223 -72
- data/bin/lib/Image/ExifTool.pod +114 -93
- data/bin/perl-Image-ExifTool.spec +43 -42
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +28 -13
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#
|
|
6
6
|
# Revisions: 2010/10/01 - P. Harvey Created
|
|
7
7
|
# 2011/10/05 - PH Added ProcessXtra()
|
|
8
|
+
# 2021/02/23 - PH Added abiltity to write Xtra tags
|
|
8
9
|
#
|
|
9
10
|
# References: 1) http://research.microsoft.com/en-us/um/redmond/groups/ivm/hdview/hdmetadataspec.htm
|
|
10
11
|
#------------------------------------------------------------------------------
|
|
@@ -16,9 +17,11 @@ use vars qw($VERSION);
|
|
|
16
17
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
17
18
|
use Image::ExifTool::XMP;
|
|
18
19
|
|
|
19
|
-
$VERSION = '1.
|
|
20
|
+
$VERSION = '1.23';
|
|
20
21
|
|
|
21
22
|
sub ProcessXtra($$$);
|
|
23
|
+
sub WriteXtra($$$);
|
|
24
|
+
sub CheckXtra($$$);
|
|
22
25
|
|
|
23
26
|
# tags written by Microsoft HDView (ref 1)
|
|
24
27
|
%Image::ExifTool::Microsoft::Stitch = (
|
|
@@ -196,11 +199,20 @@ my %sRegions = (
|
|
|
196
199
|
# and Image::ExifTool::WTV::Metadata
|
|
197
200
|
%Image::ExifTool::Microsoft::Xtra = (
|
|
198
201
|
PROCESS_PROC => \&ProcessXtra,
|
|
202
|
+
WRITE_PROC => \&WriteXtra,
|
|
203
|
+
CHECK_PROC => \&CheckXtra,
|
|
204
|
+
WRITE_GROUP => 'Microsoft',
|
|
205
|
+
AVOID => 1,
|
|
199
206
|
GROUPS => { 0 => 'QuickTime', 2 => 'Video' },
|
|
200
207
|
VARS => { NO_ID => 1 },
|
|
201
208
|
NOTES => q{
|
|
202
|
-
Tags
|
|
203
|
-
|
|
209
|
+
Tags found in the Microsoft "Xtra" atom of QuickTime videos. Tag ID's are
|
|
210
|
+
not shown because some are unruly GUID's. Currently most of these tags are
|
|
211
|
+
not writable because the Microsoft documentation is poor and samples were
|
|
212
|
+
not available, but more tags may be made writable in the future if samples
|
|
213
|
+
are provided. Note that writable tags in this table are are flagged to
|
|
214
|
+
"Avoid", which means that other more common tags will be written instead if
|
|
215
|
+
possible unless the Microsoft group is specified explicitly.
|
|
204
216
|
},
|
|
205
217
|
Abstract => { },
|
|
206
218
|
AcquisitionTime => { Groups => { 2 => 'Time' } },
|
|
@@ -327,30 +339,34 @@ my %sRegions = (
|
|
|
327
339
|
UserServiceRating => { },
|
|
328
340
|
VideoBitrate => { },
|
|
329
341
|
VideoFormat => { },
|
|
330
|
-
'WM/AlbumArtist' => 'AlbumArtist',
|
|
331
|
-
'WM/AlbumCoverURL' => 'AlbumCoverURL',
|
|
332
|
-
'WM/AlbumTitle' => 'AlbumTitle',
|
|
342
|
+
'WM/AlbumArtist' => { Name => 'AlbumArtist', Writable => 'Unicode' }, # (NC)
|
|
343
|
+
'WM/AlbumCoverURL' => { Name => 'AlbumCoverURL', Writable => 'Unicode' }, # (NC)
|
|
344
|
+
'WM/AlbumTitle' => { Name => 'AlbumTitle', Writable => 'Unicode' }, # (NC)
|
|
333
345
|
'WM/BeatsPerMinute' => 'BeatsPerMinute',
|
|
334
|
-
'WM/Category' => 'Category',
|
|
335
|
-
'WM/Composer' => 'Composer',
|
|
336
|
-
'WM/Conductor' => 'Conductor',
|
|
337
|
-
'WM/ContentDistributor' => 'ContentDistributor',
|
|
346
|
+
'WM/Category' => { Name => 'Category', Writable => 'Unicode', List => 1 },
|
|
347
|
+
'WM/Composer' => { Name => 'Composer', Writable => 'Unicode' }, # (NC)
|
|
348
|
+
'WM/Conductor' => { Name => 'Conductor', Writable => 'Unicode', List => 1 },
|
|
349
|
+
'WM/ContentDistributor' => { Name => 'ContentDistributor', Writable => 'Unicode' },
|
|
338
350
|
'WM/ContentDistributorType' => 'ContentDistributorType',
|
|
339
351
|
'WM/ContentGroupDescription'=> 'ContentGroupDescription',
|
|
340
|
-
'WM/Director' => 'Director',
|
|
352
|
+
'WM/Director' => { Name => 'Director', Writable => 'Unicode', List => 1 },
|
|
341
353
|
'WM/EncodingTime' => {
|
|
342
354
|
Name => 'EncodingTime',
|
|
343
355
|
Groups => { 2 => 'Time' },
|
|
356
|
+
Shift => 'Time',
|
|
357
|
+
Writable => 'date',
|
|
344
358
|
PrintConv => '$self->ConvertDateTime($val)',
|
|
359
|
+
PrintConvInv => '$self->InverseDateTime($val)',
|
|
345
360
|
},
|
|
346
361
|
'WM/Genre' => 'Genre',
|
|
347
362
|
'WM/GenreID' => 'GenreID',
|
|
348
|
-
'WM/InitialKey' => 'InitialKey',
|
|
363
|
+
'WM/InitialKey' => { Name => 'InitialKey', Writable => 'Unicode' },
|
|
349
364
|
'WM/Language' => 'Language',
|
|
350
365
|
'WM/Lyrics' => 'Lyrics',
|
|
351
366
|
'WM/MCDI' => 'MCDI',
|
|
352
367
|
'WM/MediaClassPrimaryID' => {
|
|
353
368
|
Name => 'MediaClassPrimaryID',
|
|
369
|
+
Writable => 'GUID',
|
|
354
370
|
PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx
|
|
355
371
|
'D1607DBC-E323-4BE2-86A1-48A42A28441E' => 'Music',
|
|
356
372
|
'DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B' => 'Video',
|
|
@@ -360,6 +376,7 @@ my %sRegions = (
|
|
|
360
376
|
},
|
|
361
377
|
'WM/MediaClassSecondaryID' => {
|
|
362
378
|
Name => 'MediaClassSecondaryID',
|
|
379
|
+
Writable => 'GUID',
|
|
363
380
|
PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx
|
|
364
381
|
'E0236BEB-C281-4EDE-A36D-7AF76A3D45B5' => 'Audio Book',
|
|
365
382
|
'3A172A13-2BD9-4831-835B-114F6A95943F' => 'Spoken Word',
|
|
@@ -385,22 +402,22 @@ my %sRegions = (
|
|
|
385
402
|
},
|
|
386
403
|
'WM/MediaOriginalChannel' => 'MediaOriginalChannel',
|
|
387
404
|
'WM/MediaStationName' => 'MediaStationName',
|
|
388
|
-
'WM/Mood' => 'Mood',
|
|
389
|
-
'WM/OriginalAlbumTitle' => 'OriginalAlbumTitle',
|
|
390
|
-
'WM/OriginalArtist' => 'OriginalArtist',
|
|
391
|
-
'WM/OriginalLyricist' => 'OriginalLyricist',
|
|
392
|
-
'WM/ParentalRating' => 'ParentalRating',
|
|
405
|
+
'WM/Mood' => { Name => 'Mood', Writable => 'Unicode' },
|
|
406
|
+
'WM/OriginalAlbumTitle' => { Name => 'OriginalAlbumTitle', Writable => 'Unicode' }, # (NC)
|
|
407
|
+
'WM/OriginalArtist' => { Name => 'OriginalArtist', Writable => 'Unicode' }, # (NC)
|
|
408
|
+
'WM/OriginalLyricist' => { Name => 'OriginalLyricist', Writable => 'Unicode' }, # (NC)
|
|
409
|
+
'WM/ParentalRating' => { Name => 'ParentalRating', Writable => 'Unicode' },
|
|
393
410
|
'WM/PartOfSet' => 'PartOfSet',
|
|
394
|
-
'WM/Period' => 'Period',
|
|
395
|
-
'WM/Producer' => 'Producer',
|
|
411
|
+
'WM/Period' => { Name => 'Period', Writable => 'Unicode' },
|
|
412
|
+
'WM/Producer' => { Name => 'Producer', Writable => 'Unicode', List => 1 },
|
|
396
413
|
'WM/ProtectionType' => 'ProtectionType',
|
|
397
|
-
'WM/Provider' => 'Provider',
|
|
414
|
+
'WM/Provider' => { Name => 'Provider', Writable => 'Unicode' }, # (NC)
|
|
398
415
|
'WM/ProviderRating' => 'ProviderRating',
|
|
399
416
|
'WM/ProviderStyle' => 'ProviderStyle',
|
|
400
|
-
'WM/Publisher' => 'Publisher',
|
|
401
|
-
'WM/SharedUserRating' => 'SharedUserRating',
|
|
417
|
+
'WM/Publisher' => { Name => 'Publisher', Writable => 'Unicode' }, # (multiple entries separated by semicolon)
|
|
418
|
+
'WM/SharedUserRating' => { Name => 'SharedUserRating', Writable => 'int64u' },
|
|
402
419
|
'WM/SubscriptionContentID' => 'SubscriptionContentID',
|
|
403
|
-
'WM/SubTitle' => 'Subtitle',
|
|
420
|
+
'WM/SubTitle' => { Name => 'Subtitle', Writable => 'Unicode' },
|
|
404
421
|
'WM/SubTitleDescription' => 'SubtitleDescription',
|
|
405
422
|
'WM/TrackNumber' => 'TrackNumber',
|
|
406
423
|
'WM/UniqueFileIdentifier' => 'UniqueFileIdentifier',
|
|
@@ -412,8 +429,11 @@ my %sRegions = (
|
|
|
412
429
|
'WM/WMContentID' => 'WMContentID',
|
|
413
430
|
'WM/WMShadowFileSourceDRMType' => 'WMShadowFileSourceDRMType',
|
|
414
431
|
'WM/WMShadowFileSourceFileType' => 'WMShadowFileSourceFileType',
|
|
415
|
-
'WM/Writer' => 'Writer',
|
|
416
|
-
'WM/Year' => { Name => 'Year',
|
|
432
|
+
'WM/Writer' => { Name => 'Writer', Groups => { 2 => 'Author' }, Writable => 'Unicode' }, # (NC)
|
|
433
|
+
'WM/Year' => { Name => 'Year', Groups => { 2 => 'Time' } },
|
|
434
|
+
'WM/PromotionURL' => { Name => 'PromotionURL',Writable => 'Unicode' },
|
|
435
|
+
'WM/AuthorURL' => { Name => 'AuthorURL', Groups => { 2 => 'Author' }, Writable => 'Unicode' },
|
|
436
|
+
'WM/EncodedBy', => { Name => 'EncodedBy', Writable => 'Unicode' },
|
|
417
437
|
|
|
418
438
|
# I can't find documentation for the following tags in videos,
|
|
419
439
|
# but the tag ID's correspond to Microsoft property GUID+ID's
|
|
@@ -422,9 +442,12 @@ my %sRegions = (
|
|
|
422
442
|
# http://multi-rename-script.googlecode.com/svn-history/r4/trunk/plugins/ShellDetails/ShellDetails.ini
|
|
423
443
|
# I have observed only 1 so far:
|
|
424
444
|
'{2CBAA8F5-D81F-47CA-B17A-F8D822300131} 100' => {
|
|
425
|
-
Name => 'DateAcquired',
|
|
445
|
+
Name => 'DateAcquired', # (seems to be when videos are downloaded from the camera)
|
|
426
446
|
Groups => { 2 => 'Time' },
|
|
447
|
+
Shift => 'Time',
|
|
448
|
+
Writable => 'vt_filetime',
|
|
427
449
|
PrintConv => '$self->ConvertDateTime($val)',
|
|
450
|
+
PrintConvInv => '$self->InverseDateTime($val,undef)',
|
|
428
451
|
},
|
|
429
452
|
# the following have not yet been observed...
|
|
430
453
|
'{B725F130-47EF-101A-A5F1-02608C9EEBAC} 10' => 'Name',
|
|
@@ -764,6 +787,245 @@ my %sRegions = (
|
|
|
764
787
|
'{64440491-4C8B-11D1-8B70-080036B11A03} 43' => 'TotalBitrate',
|
|
765
788
|
);
|
|
766
789
|
|
|
790
|
+
#------------------------------------------------------------------------------
|
|
791
|
+
# check new value for Xtra tag
|
|
792
|
+
# Inputs: 0) ExifTool object ref, 1) tagInfo hash ref, 2) raw value ref
|
|
793
|
+
# Returns: error string, or undef on success
|
|
794
|
+
sub CheckXtra($$$)
|
|
795
|
+
{
|
|
796
|
+
my ($et, $tagInfo, $valPt) = @_;
|
|
797
|
+
my $format = $$tagInfo{Writable};
|
|
798
|
+
return 'Unknown format' unless $format;
|
|
799
|
+
if ($format =~ /^int/) {
|
|
800
|
+
return 'Not an integer' unless Image::ExifTool::IsInt($$valPt);
|
|
801
|
+
} elsif ($format ne 'Unicode') {
|
|
802
|
+
my @vals = ($$valPt);
|
|
803
|
+
return 'Invalid format' unless WriteXtraValue($et, $tagInfo, \@vals);
|
|
804
|
+
}
|
|
805
|
+
return undef;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
#------------------------------------------------------------------------------
|
|
809
|
+
# Decode value(s) in Microsoft Xtra tag
|
|
810
|
+
# Inputs: 0) ExifTool object ref, 1) value data
|
|
811
|
+
# Returns: Scalar context: decoded value, List context: 0) decoded value, 1) format string
|
|
812
|
+
sub ReadXtraValue($$)
|
|
813
|
+
{
|
|
814
|
+
my ($et, $data) = @_;
|
|
815
|
+
my ($format, $i, @vals);
|
|
816
|
+
|
|
817
|
+
return undef if length($data) < 10;
|
|
818
|
+
|
|
819
|
+
# (version flags according to the reference, but looks more like a count - PH)
|
|
820
|
+
my $count = Get32u(\$data, 0);
|
|
821
|
+
# point to start of first value (after 4-byte count, 4-byte length and 2-byte type)
|
|
822
|
+
my $valPos = 10;
|
|
823
|
+
for ($i=0; ;) {
|
|
824
|
+
# (stored value includes size of $valLen and $valType, so subtract 6)
|
|
825
|
+
my $valLen = Get32u(\$data, $valPos - 6) - 6;
|
|
826
|
+
last if $valPos + $valLen > length($data);
|
|
827
|
+
my $valType = Get16u(\$data, $valPos - 2);
|
|
828
|
+
my $val = substr($data, $valPos, $valLen);
|
|
829
|
+
# Note: all dumb Microsoft values are little-endian inside a big-endian-format file
|
|
830
|
+
SetByteOrder('II');
|
|
831
|
+
if ($valType == 8) {
|
|
832
|
+
$format = 'Unicode';
|
|
833
|
+
$val = $et->Decode($val, 'UCS2');
|
|
834
|
+
} elsif ($valType == 19 and $valLen == 8) {
|
|
835
|
+
$format = 'int64u';
|
|
836
|
+
$val = Get64u(\$val, 0);
|
|
837
|
+
} elsif ($valType == 21 and $valLen == 8) {
|
|
838
|
+
$format = 'date';
|
|
839
|
+
$val = Get64u(\$val, 0);
|
|
840
|
+
# convert time from 100 ns intervals since Jan 1, 1601
|
|
841
|
+
$val = $val * 1e-7 - 11644473600 if $val;
|
|
842
|
+
# (the Nikon S100 uses UTC timezone, same as ASF - PH)
|
|
843
|
+
$val = Image::ExifTool::ConvertUnixTime($val, 1);
|
|
844
|
+
} elsif ($valType == 72 and $valLen == 16) {
|
|
845
|
+
$format = 'GUID';
|
|
846
|
+
$val = uc unpack('H*',pack('NnnNN',unpack('VvvNN',$val)));
|
|
847
|
+
$val =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/;
|
|
848
|
+
} elsif ($valType == 65 and $valLen > 4) { #PH (empirical)
|
|
849
|
+
$format = 'variant';
|
|
850
|
+
require Image::ExifTool::FlashPix;
|
|
851
|
+
my $vPos = 0; # (necessary because ReadFPXValue updates this)
|
|
852
|
+
# read entry as a VT_VARIANT (use FlashPix module for this)
|
|
853
|
+
$val = Image::ExifTool::FlashPix::ReadFPXValue($et, \$val, $vPos,
|
|
854
|
+
Image::ExifTool::FlashPix::VT_VARIANT(), $valLen, 1);
|
|
855
|
+
} else {
|
|
856
|
+
$format = "Unknown($valType)";
|
|
857
|
+
}
|
|
858
|
+
SetByteOrder('MM'); # back to native QuickTime byte ordering
|
|
859
|
+
push @vals, $val;
|
|
860
|
+
last if ++$i >= $count;
|
|
861
|
+
$valPos += $valLen + 6; # step to next value
|
|
862
|
+
last if $valPos > length($data);
|
|
863
|
+
}
|
|
864
|
+
return wantarray ? (\@vals, $format) : \@vals;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
#------------------------------------------------------------------------------
|
|
868
|
+
# Write a Microsoft Xtra value
|
|
869
|
+
# Inputs: 0) ExifTool object ref, 1) tagInfo ref, 2) reference to list of values
|
|
870
|
+
# Returns: new value binary data (or empty string)
|
|
871
|
+
sub WriteXtraValue($$$)
|
|
872
|
+
{
|
|
873
|
+
my ($et, $tagInfo, $vals) = @_;
|
|
874
|
+
my $format = $$tagInfo{Writable};
|
|
875
|
+
my $buff = '';
|
|
876
|
+
my $count = 0;
|
|
877
|
+
my $val;
|
|
878
|
+
foreach $val (@$vals) {
|
|
879
|
+
SetByteOrder('II');
|
|
880
|
+
my ($type, $dat);
|
|
881
|
+
if ($format eq 'Unicode') {
|
|
882
|
+
$dat = $et->Encode($val,'UCS2','II') . "\0\0"; # (must be null terminated)
|
|
883
|
+
$type = 8;
|
|
884
|
+
} elsif ($format eq 'int64u') {
|
|
885
|
+
if (Image::ExifTool::IsInt($val)) {
|
|
886
|
+
$dat = Set64u($val);
|
|
887
|
+
$type = 19;
|
|
888
|
+
}
|
|
889
|
+
} elsif ($format eq 'date') {
|
|
890
|
+
$dat = Image::ExifTool::GetUnixTime($val, 1); # (convert to UTC, NC)
|
|
891
|
+
if ($dat) {
|
|
892
|
+
# 100ns intervals since Jan 1, 1601
|
|
893
|
+
$dat = Set64u(($dat + 11644473600) * 1e7);
|
|
894
|
+
$type = 21;
|
|
895
|
+
}
|
|
896
|
+
} elsif ($format eq 'vt_filetime') { # 'date' value inside a VT_VARIANT
|
|
897
|
+
$dat = Image::ExifTool::GetUnixTime($val); # (leave as local time, NC)
|
|
898
|
+
if ($dat) {
|
|
899
|
+
# 100ns intervals since Jan 1, 1601
|
|
900
|
+
$dat = Set32u(64) . Set64u(($dat + 11644473600) * 1e7);
|
|
901
|
+
$type = 65;
|
|
902
|
+
}
|
|
903
|
+
} elsif ($format eq 'GUID') {
|
|
904
|
+
($dat = $val) =~ tr/-//d;
|
|
905
|
+
if (length($dat) == 32) {
|
|
906
|
+
$dat = pack('VvvNN',unpack('NnnNN',pack('H*', $dat)));
|
|
907
|
+
$type = 72;
|
|
908
|
+
}
|
|
909
|
+
} else {
|
|
910
|
+
$et->WarnOnce("Error converting value for Microsoft:$$tagInfo{Name}");
|
|
911
|
+
}
|
|
912
|
+
SetByteOrder('MM');
|
|
913
|
+
if (defined $type) {
|
|
914
|
+
++$count;
|
|
915
|
+
$buff .= Set32u(length($dat)+6) . Set16u($type) . $dat;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return $count ? Set32u($count) . $buff : '';
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
#------------------------------------------------------------------------------
|
|
922
|
+
# Add new values to list
|
|
923
|
+
# Inputs: 0) ExifTool ref, 1) new value list ref, 2) nvHash ref
|
|
924
|
+
# Returns: true if something was added
|
|
925
|
+
sub AddNewValues($$$)
|
|
926
|
+
{
|
|
927
|
+
my ($et, $vals, $nvHash) = @_;
|
|
928
|
+
my @newVals = $et->GetNewValue($nvHash) or return undef;
|
|
929
|
+
if ($$et{OPTIONS}{Verbose} > 1) {
|
|
930
|
+
$et->VPrint(1, " + Microsoft:$$nvHash{TagInfo}{Name} = $_\n") foreach @newVals;
|
|
931
|
+
}
|
|
932
|
+
push @$vals, @newVals;
|
|
933
|
+
return 1;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
#------------------------------------------------------------------------------
|
|
937
|
+
# Write tags to a Microsoft Xtra MP4 atom
|
|
938
|
+
# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref
|
|
939
|
+
# Returns: Microsoft Xtra data block (may be empty if no Xtra data) or undef on error
|
|
940
|
+
sub WriteXtra($$$)
|
|
941
|
+
{
|
|
942
|
+
my ($et, $dirInfo, $tagTablePtr) = @_;
|
|
943
|
+
$et or return 1; # allow dummy access
|
|
944
|
+
|
|
945
|
+
my $delGroup = ($$et{DEL_GROUP} and $$et{DEL_GROUP}{Microsoft});
|
|
946
|
+
my $newTags = $et->GetNewTagInfoHash($tagTablePtr);
|
|
947
|
+
|
|
948
|
+
return undef unless $delGroup or %$newTags; # don't rewrite if nothing to do
|
|
949
|
+
|
|
950
|
+
my $dataPt = $$dirInfo{DataPt};
|
|
951
|
+
my $dataLen = length $$dataPt;
|
|
952
|
+
my $newData = '';
|
|
953
|
+
my $pos = 0;
|
|
954
|
+
my ($err, %done, $changed, $tag);
|
|
955
|
+
|
|
956
|
+
if ($delGroup) {
|
|
957
|
+
$changed = 1 if $dataLen;
|
|
958
|
+
my $empty = '';
|
|
959
|
+
$dataPt = $empty;
|
|
960
|
+
$dataLen = 0;
|
|
961
|
+
}
|
|
962
|
+
for (;;) {
|
|
963
|
+
last if $pos + 4 > $dataLen;
|
|
964
|
+
my $size = Get32u($dataPt, $pos); # (includes $size word)
|
|
965
|
+
($size < 8 or $pos + $size > $dataLen) and $err=1, last;
|
|
966
|
+
my $tagLen = Get32u($dataPt, $pos + 4);
|
|
967
|
+
$tagLen + 18 > $size and $err=1, last;
|
|
968
|
+
$tag = substr($$dataPt, $pos + 8, $tagLen);
|
|
969
|
+
my @newVals;
|
|
970
|
+
while ($$newTags{$tag}) {
|
|
971
|
+
my $nvHash = $et->GetNewValueHash($$newTags{$tag});
|
|
972
|
+
$$nvHash{CreateOnly} and delete($$newTags{$tag}), last; # don't edit this tag
|
|
973
|
+
my $valPos = $pos + 8 + $tagLen;
|
|
974
|
+
my $valLen = $size - 8 - $tagLen;
|
|
975
|
+
my $val = ReadXtraValue($et, substr($$dataPt, $valPos, $valLen));
|
|
976
|
+
foreach $val (@$val) {
|
|
977
|
+
my $overwrite = $et->IsOverwriting($nvHash, $val);
|
|
978
|
+
$overwrite or push(@newVals, $val), next;
|
|
979
|
+
$et->VPrint(1, " - Microsoft:$$newTags{$tag}{Name} = $val\n");
|
|
980
|
+
next if $done{$tag};
|
|
981
|
+
$done{$tag} = 1;
|
|
982
|
+
AddNewValues($et, \@newVals, $nvHash);
|
|
983
|
+
}
|
|
984
|
+
# add to the end of the list if this was a List-type tag and we didn't delete anything
|
|
985
|
+
if (not $done{$tag} and $$newTags{$tag}{List}) {
|
|
986
|
+
AddNewValues($et, \@newVals, $nvHash) or last;
|
|
987
|
+
$done{$tag} = 1;
|
|
988
|
+
}
|
|
989
|
+
last; # (it was a cheap goto)
|
|
990
|
+
}
|
|
991
|
+
if ($done{$tag}) {
|
|
992
|
+
$changed = 1;
|
|
993
|
+
# write changed values
|
|
994
|
+
my $buff = WriteXtraValue($et, $$newTags{$tag}, \@newVals);
|
|
995
|
+
if (length $buff) {
|
|
996
|
+
$newData .= Set32u(8+length($tag)+length($buff)) . Set32u(length($tag)) . $tag . $buff;
|
|
997
|
+
}
|
|
998
|
+
} else {
|
|
999
|
+
# nothing changed; just copy over
|
|
1000
|
+
$newData .= substr($$dataPt, $pos, $size);
|
|
1001
|
+
}
|
|
1002
|
+
$pos += $size; # step to next entry
|
|
1003
|
+
}
|
|
1004
|
+
if ($err) {
|
|
1005
|
+
$et->Warn('Microsoft Xtra format error');
|
|
1006
|
+
return undef;
|
|
1007
|
+
}
|
|
1008
|
+
# add any new tags
|
|
1009
|
+
foreach $tag (sort keys %$newTags) {
|
|
1010
|
+
next if $done{$tag};
|
|
1011
|
+
my $nvHash = $et->GetNewValueHash($$newTags{$tag});
|
|
1012
|
+
next unless $$nvHash{IsCreating} and not $$nvHash{EditOnly};
|
|
1013
|
+
my @newVals;
|
|
1014
|
+
AddNewValues($et, \@newVals, $nvHash) or next;
|
|
1015
|
+
my $buff = WriteXtraValue($et, $$newTags{$tag}, \@newVals);
|
|
1016
|
+
if (length $buff) {
|
|
1017
|
+
$newData .= Set32u(8+length($tag)+length($buff)) . Set32u(length($tag)) . $tag . $buff;
|
|
1018
|
+
$changed = 1;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
if ($changed) {
|
|
1022
|
+
++$$et{CHANGED};
|
|
1023
|
+
} else {
|
|
1024
|
+
undef $newData;
|
|
1025
|
+
}
|
|
1026
|
+
return $newData;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
767
1029
|
#------------------------------------------------------------------------------
|
|
768
1030
|
# Extract information from Xtra MP4 atom
|
|
769
1031
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
|
@@ -783,61 +1045,13 @@ sub ProcessXtra($$$)
|
|
|
783
1045
|
last if $size < 8 or $pos + $size > $dataLen;
|
|
784
1046
|
my $tagLen = Get32u($dataPt, $pos + 4);
|
|
785
1047
|
last if $tagLen + 18 > $size;
|
|
786
|
-
my $
|
|
787
|
-
# (version flags according to the reference, but looks more like a count - PH)
|
|
788
|
-
my $count = Get32u($dataPt, $pos + $tagLen + 8);
|
|
789
|
-
my ($i, $valPos, $valLen, $valType, $val, $format, @vals);
|
|
790
|
-
# point to start of first value (after 4-byte length and 2-byte type)
|
|
791
|
-
$valPos = $pos + $tagLen + 18;
|
|
792
|
-
for ($i=0; ;) {
|
|
793
|
-
# (stored value includes size of $valLen and $valType, so subtract 6)
|
|
794
|
-
$valLen = Get32u($dataPt, $valPos - 6) - 6;
|
|
795
|
-
my $more = $pos + $size - $valPos - $valLen;
|
|
796
|
-
last if $more < 0;
|
|
797
|
-
$valType = Get16u($dataPt, $valPos - 2);
|
|
798
|
-
$val = substr($$dataPt, $valPos, $valLen);
|
|
799
|
-
# Note: all dumb Microsoft values are little-endian inside a big-endian-format file
|
|
800
|
-
SetByteOrder('II');
|
|
801
|
-
if ($valType == 8) {
|
|
802
|
-
$format = 'Unicode';
|
|
803
|
-
$val = $et->Decode($val, 'UCS2');
|
|
804
|
-
} elsif ($valType == 19 and $valLen == 8) {
|
|
805
|
-
$format = 'int64u';
|
|
806
|
-
$val = Get64u(\$val, 0);
|
|
807
|
-
} elsif ($valType == 21 and $valLen == 8) {
|
|
808
|
-
$format = 'date';
|
|
809
|
-
$val = Get64u(\$val, 0);
|
|
810
|
-
# convert time from 100 ns intervals since Jan 1, 1601
|
|
811
|
-
$val = $val * 1e-7 - 11644473600 if $val;
|
|
812
|
-
# (the Nikon S100 uses UTC timezone, same as ASF - PH)
|
|
813
|
-
$val = Image::ExifTool::ConvertUnixTime($val) . 'Z';
|
|
814
|
-
} elsif ($valType == 72 and $valLen == 16) {
|
|
815
|
-
$format = 'GUID';
|
|
816
|
-
$val = uc unpack('H*',pack('NnnNN',unpack('VvvNN',$val)));
|
|
817
|
-
$val =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/;
|
|
818
|
-
} elsif ($valType == 65 && $valLen > 4) { #PH (empirical)
|
|
819
|
-
$format = 'variant';
|
|
820
|
-
require Image::ExifTool::FlashPix;
|
|
821
|
-
my $vPos = $valPos; # (necessary because ReadFPXValue updates this)
|
|
822
|
-
# read entry as a VT_VARIANT (use FlashPix module for this)
|
|
823
|
-
$val = Image::ExifTool::FlashPix::ReadFPXValue($et, $dataPt, $vPos,
|
|
824
|
-
Image::ExifTool::FlashPix::VT_VARIANT(), $valPos+$valLen, 1);
|
|
825
|
-
} else {
|
|
826
|
-
$format = "Unknown($valType)";
|
|
827
|
-
}
|
|
828
|
-
SetByteOrder('MM'); # back to native QuickTime byte ordering
|
|
829
|
-
last if ++$i >= $count or $more < 6;
|
|
830
|
-
push @vals, $val;
|
|
831
|
-
undef $val;
|
|
832
|
-
$valPos += $valLen + 6; # step to next value
|
|
833
|
-
}
|
|
834
|
-
if (@vals) {
|
|
835
|
-
push @vals, $val if defined $val;
|
|
836
|
-
$val = \@vals;
|
|
837
|
-
$valPos = $pos + $tagLen + 18;
|
|
838
|
-
$valLen = $size - 18 - $tagLen;
|
|
839
|
-
}
|
|
1048
|
+
my $valLen = $size - 8 - $tagLen;
|
|
840
1049
|
if ($tagLen > 0 and $valLen > 0) {
|
|
1050
|
+
my $tag = substr($$dataPt, $pos + 8, $tagLen);
|
|
1051
|
+
my $valPos = $pos + 8 + $tagLen;
|
|
1052
|
+
my ($val, $format) = ReadXtraValue($et, substr($$dataPt, $valPos, $valLen));
|
|
1053
|
+
last unless defined $val;
|
|
1054
|
+
$val = $$val[0] if @$val == 1;
|
|
841
1055
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
|
|
842
1056
|
unless ($tagInfo) {
|
|
843
1057
|
# generate tag information for unrecognized tags
|
|
@@ -850,6 +1064,7 @@ sub ProcessXtra($$$)
|
|
|
850
1064
|
$et->VPrint(0, $$et{INDENT}, "[adding Microsoft:$tag]\n");
|
|
851
1065
|
}
|
|
852
1066
|
}
|
|
1067
|
+
my $count = ref $val ? scalar @$val : 1;
|
|
853
1068
|
$et->HandleTag($tagTablePtr, $tag, $val,
|
|
854
1069
|
TagInfo => $tagInfo,
|
|
855
1070
|
DataPt => $dataPt,
|
|
@@ -857,7 +1072,7 @@ sub ProcessXtra($$$)
|
|
|
857
1072
|
Start => $valPos,
|
|
858
1073
|
Size => $valLen,
|
|
859
1074
|
Format => $format,
|
|
860
|
-
Extra => " count=$count
|
|
1075
|
+
Extra => " count=$count",
|
|
861
1076
|
);
|
|
862
1077
|
}
|
|
863
1078
|
$pos += $size; # step to next entry
|
|
@@ -880,7 +1095,8 @@ This module is used by Image::ExifTool
|
|
|
880
1095
|
=head1 DESCRIPTION
|
|
881
1096
|
|
|
882
1097
|
This module contains definitions required by Image::ExifTool to interpret
|
|
883
|
-
Microsoft-specific EXIF and XMP tags
|
|
1098
|
+
Microsoft-specific EXIF and XMP tags, and routines to read/write Microsoft
|
|
1099
|
+
Xtra tags in videos.
|
|
884
1100
|
|
|
885
1101
|
=head1 AUTHOR
|
|
886
1102
|
|
|
@@ -62,7 +62,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
62
62
|
use Image::ExifTool::Exif;
|
|
63
63
|
use Image::ExifTool::GPS;
|
|
64
64
|
|
|
65
|
-
$VERSION = '
|
|
65
|
+
$VERSION = '4.00';
|
|
66
66
|
|
|
67
67
|
sub LensIDConv($$$);
|
|
68
68
|
sub ProcessNikonAVI($$$);
|
|
@@ -272,6 +272,7 @@ sub GetAFPointGrid($$;$);
|
|
|
272
272
|
'9F 58 44 44 14 14 A1 06' => 'AF-S DX Nikkor 35mm f/1.8G', #27
|
|
273
273
|
'A0 54 50 50 0C 0C A2 06' => 'AF-S Nikkor 50mm f/1.4G',
|
|
274
274
|
'A1 40 18 37 2C 34 A3 06' => 'AF-S DX Nikkor 10-24mm f/3.5-4.5G ED',
|
|
275
|
+
'A1 40 2D 53 2C 3C CB 86' => 'AF-P DX Nikkor 18-55mm f/3.5-5.6G', #30
|
|
275
276
|
'A2 48 5C 80 24 24 A4 0E' => 'AF-S Nikkor 70-200mm f/2.8G ED VR II',
|
|
276
277
|
'A3 3C 29 44 30 30 A5 0E' => 'AF-S Nikkor 16-35mm f/4G ED VR',
|
|
277
278
|
'A4 54 37 37 0C 0C A6 06' => 'AF-S Nikkor 24mm f/1.4G ED',
|
|
@@ -495,6 +496,7 @@ sub GetAFPointGrid($$;$);
|
|
|
495
496
|
'02 46 5C 82 25 25 02 00' => 'Sigma 70-210mm F2.8 APO', #JD
|
|
496
497
|
'02 40 5C 82 2C 35 02 00' => 'Sigma APO 70-210mm F3.5-4.5',
|
|
497
498
|
'26 3C 5C 82 30 3C 1C 02' => 'Sigma 70-210mm F4-5.6 UC-II',
|
|
499
|
+
'02 3B 5C 82 30 3C 02 00' => 'Sigma Zoom-K 70-210mm F4-5.6', #30
|
|
498
500
|
'26 3C 5C 8E 30 3C 1C 02' => 'Sigma 70-300mm F4-5.6 DG Macro',
|
|
499
501
|
'56 3C 5C 8E 30 3C 1C 02' => 'Sigma 70-300mm F4-5.6 APO Macro Super II',
|
|
500
502
|
'E0 3C 5C 8E 30 3C 4B 06' => 'Sigma 70-300mm F4-5.6 APO DG Macro HSM', #22
|
|
@@ -554,6 +556,7 @@ sub GetAFPointGrid($$;$);
|
|
|
554
556
|
'F3 54 2B 50 24 24 84 0E' => 'Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical (IF) (B005)',
|
|
555
557
|
'00 3F 2D 80 2B 40 00 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) (A14)',
|
|
556
558
|
'00 3F 2D 80 2C 40 00 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14)',
|
|
559
|
+
'EC 3E 3C 8E 2C 40 DF 0E' => 'Tamron 28-300mm f/3.5-6.3 Di VC PZD A010', #30
|
|
557
560
|
'00 40 2D 80 2C 40 00 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)', #NJ
|
|
558
561
|
'FC 40 2D 80 2C 40 DF 06' => 'Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)', #PH (NC)
|
|
559
562
|
'E6 40 2D 80 2C 40 DF 0E' => 'Tamron 18-200mm f/3.5-6.3 Di II VC (B018)', #Tanel (removed AF designation, ref 37)
|
|
@@ -563,7 +566,7 @@ sub GetAFPointGrid($$;$);
|
|
|
563
566
|
'F0 3F 2D 8A 2C 40 DF 0E' => 'Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD (B008)',
|
|
564
567
|
'E0 40 2D 98 2C 41 DF 4E' => 'Tamron 18-400mm f/3.5-6.3 Di II VC HLD (B028)', # (removed AF designation, ref 37)
|
|
565
568
|
'07 40 2F 44 2C 34 03 02' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)',
|
|
566
|
-
'07 40 30 45 2D 35 03 02' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)',
|
|
569
|
+
'07 40 30 45 2D 35 03 02.1' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)',
|
|
567
570
|
'00 49 30 48 22 2B 00 02' => 'Tamron SP AF 20-40mm f/2.7-3.5 (166D)',
|
|
568
571
|
'0E 4A 31 48 23 2D 0E 02' => 'Tamron SP AF 20-40mm f/2.7-3.5 (166D)',
|
|
569
572
|
'FE 48 37 5C 24 24 DF 0E' => 'Tamron SP 24-70mm f/2.8 Di VC USD (A007)', #24
|
|
@@ -595,6 +598,7 @@ sub GetAFPointGrid($$;$);
|
|
|
595
598
|
'00 48 5C 8E 30 3C 00 06' => 'Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17NII)', #JD
|
|
596
599
|
'F1 47 5C 8E 30 3C DF 0E' => 'Tamron SP 70-300mm f/4-5.6 Di VC USD (A005)',
|
|
597
600
|
'CF 47 5C 8E 31 3D DF 0E' => 'Tamron SP 70-300mm f/4-5.6 Di VC USD (A030)', #forum9773
|
|
601
|
+
'CC 44 68 98 34 41 DF 0E' => 'Tamron 100-400mm f/4.5-6.3 Di VC USD', #30
|
|
598
602
|
'EB 40 76 A6 38 40 DF 0E' => 'Tamron SP AF 150-600mm f/5-6.3 VC USD (A011)',
|
|
599
603
|
'E3 40 76 A6 38 40 DF 4E' => 'Tamron SP 150-600mm f/5-6.3 Di VC USD G2', #30
|
|
600
604
|
'20 3C 80 98 3D 3D 1E 02' => 'Tamron AF 200-400mm f/5.6 LD IF (75D)',
|
|
@@ -612,6 +616,7 @@ sub GetAFPointGrid($$;$);
|
|
|
612
616
|
'7A 48 1C 29 24 24 7E 06' => 'Tokina AT-X 116 PRO DX II (AF 11-16mm f/2.8)',
|
|
613
617
|
'80 48 1C 29 24 24 7A 06' => 'Tokina atx-i 11-16mm F2.8 CF', #exiv2 issue 1078
|
|
614
618
|
'7A 48 1C 30 24 24 7E 06' => 'Tokina AT-X 11-20 F2.8 PRO DX (AF 11-20mm f/2.8)',
|
|
619
|
+
'8B 48 1C 30 24 24 85 06' => 'Tokina AT-X 11-20 F2.8 PRO DX (AF 11-20mm f/2.8)', #forum12687
|
|
615
620
|
'00 3C 1F 37 30 30 00 06' => 'Tokina AT-X 124 AF PRO DX (AF 12-24mm f/4)',
|
|
616
621
|
'7A 3C 1F 37 30 30 7E 06.2' => 'Tokina AT-X 124 AF PRO DX II (AF 12-24mm f/4)',
|
|
617
622
|
'7A 3C 1F 3C 30 30 7E 06' => 'Tokina AT-X 12-28 PRO DX (AF 12-28mm f/4)',
|
|
@@ -640,6 +645,7 @@ sub GetAFPointGrid($$;$);
|
|
|
640
645
|
'24 44 60 98 34 3C 1A 02' => 'Tokina AT-X 840 AF-II (AF 80-400mm f/4.5-5.6)',
|
|
641
646
|
'00 44 60 98 34 3C 00 02' => 'Tokina AT-X 840 D (AF 80-400mm f/4.5-5.6)',
|
|
642
647
|
'14 48 68 8E 30 30 0B 00' => 'Tokina AT-X 340 AF (AF 100-300mm f/4)',
|
|
648
|
+
'8C 48 29 3C 24 24 86 06' => 'Tokina opera 16-28mm F2.8 FF', #30
|
|
643
649
|
#
|
|
644
650
|
'06 3F 68 68 2C 2C 06 00' => 'Cosina AF 100mm F3.5 Macro',
|
|
645
651
|
'07 36 3D 5F 2C 3C 03 00' => 'Cosina AF Zoom 28-80mm F3.5-5.6 MC Macro',
|
|
@@ -655,6 +661,7 @@ sub GetAFPointGrid($$;$);
|
|
|
655
661
|
'00 54 48 48 18 18 00 00' => 'Voigtlander Ultron 40mm F2 SLII Aspherical',
|
|
656
662
|
'00 54 55 55 0C 0C 00 00' => 'Voigtlander Nokton 58mm F1.4 SLII',
|
|
657
663
|
'00 40 64 64 2C 2C 00 00' => 'Voigtlander APO-Lanthar 90mm F3.5 SLII Close Focus',
|
|
664
|
+
'07 40 30 45 2D 35 03 02.2' => 'Voigtlander Ultragon 19-35mm F3.5-4.5 VMV', #NJ
|
|
658
665
|
#
|
|
659
666
|
'00 40 2D 2D 2C 2C 00 00' => 'Carl Zeiss Distagon T* 3.5/18 ZF.2',
|
|
660
667
|
'00 48 27 27 24 24 00 00' => 'Carl Zeiss Distagon T* 2.8/15 ZF.2', #MykytaKozlov
|
|
@@ -716,6 +723,9 @@ sub GetAFPointGrid($$;$);
|
|
|
716
723
|
'00 40 11 11 2C 2C 00 00' => 'Samyang 8mm f/3.5 Fish-Eye',
|
|
717
724
|
'00 58 64 64 20 20 00 00' => 'Soligor C/D Macro MC 90mm f/2.5',
|
|
718
725
|
'4A 58 30 30 14 0C 4D 02' => 'Rokinon 20mm f/1.8 ED AS UMC', #30
|
|
726
|
+
#
|
|
727
|
+
'A0 56 44 44 14 14 A2 06' => 'Sony FE 35mm F1.8', #IB (Techart adapter)
|
|
728
|
+
'A0 37 5C 8E 34 3C A2 06' => 'Sony FE 70-300mm F4.5-5.6 G OSS', #IB (Techart adapter)
|
|
719
729
|
);
|
|
720
730
|
|
|
721
731
|
# text encoding used in LocationInfo (ref PH)
|
|
@@ -4718,6 +4728,9 @@ my %nikonFocalConversions = (
|
|
|
4718
4728
|
21 => 'Nikkor Z 50mm f/1.2 S', #IB
|
|
4719
4729
|
22 => 'Nikkor Z 24-50mm f/4-6.3', #IB
|
|
4720
4730
|
23 => 'Nikkor Z 14-24mm f/2.8 S', #IB
|
|
4731
|
+
24 => 'Nikkor Z MC 105mm f/2.8 VR S', #IB
|
|
4732
|
+
27 => 'Nikkor Z MC 50mm f/2.8', #IB
|
|
4733
|
+
29 => 'Nikkor Z 28mm f/2.8', #IB
|
|
4721
4734
|
},
|
|
4722
4735
|
},
|
|
4723
4736
|
0x36 => {
|
|
@@ -8490,8 +8503,8 @@ my %nikonFocalConversions = (
|
|
|
8490
8503
|
# 0x02 - undef[148]
|
|
8491
8504
|
# 0x03 - undef[284]
|
|
8492
8505
|
# 0x04 - undef[148,212]
|
|
8493
|
-
# 0x05 - undef[84]
|
|
8494
|
-
# 0x06 - undef[116]
|
|
8506
|
+
# 0x05 - undef[84] (barrel distortion params at offsets 0x14,0x1c,0x24, ref 28)
|
|
8507
|
+
# 0x06 - undef[116] (vignette correction params at offsets 0x24,0x34,0x44, ref 28)
|
|
8495
8508
|
# 0x07 - undef[104]
|
|
8496
8509
|
# 0x08 - undef[24]
|
|
8497
8510
|
# 0x09 - undef[36]
|
|
@@ -9466,7 +9479,7 @@ sub GetAFPointGrid($$;$)
|
|
|
9466
9479
|
return undef unless $val =~ /^([A-J])(\d+)$/i;
|
|
9467
9480
|
return (ord(uc($1))-65) * $ncol + $2 - 1;
|
|
9468
9481
|
} else {
|
|
9469
|
-
my $row = int(($val + 0.5) / $ncol);
|
|
9482
|
+
my $row = int(($val + 0.5) / $ncol) & 0xff;
|
|
9470
9483
|
my $col = $val - $ncol * $row + 1;
|
|
9471
9484
|
return chr(65+$row) . $col;
|
|
9472
9485
|
}
|
|
@@ -9945,12 +9958,10 @@ sub PrescanExif($$$)
|
|
|
9945
9958
|
$dataLen = length $data;
|
|
9946
9959
|
$dirStart = 0;
|
|
9947
9960
|
}
|
|
9948
|
-
# loop through
|
|
9949
|
-
my ($lastTag) = sort { $b <=> $a } keys %$tagHash; # (reverse sort)
|
|
9961
|
+
# loop through Nikon MakerNote IFD entries
|
|
9950
9962
|
for ($index=0; $index<$numEntries; ++$index) {
|
|
9951
9963
|
my $entry = $dirStart + 2 + 12 * $index;
|
|
9952
9964
|
my $tagID = Get16u($dataPt, $entry);
|
|
9953
|
-
last if $tagID > $lastTag; # (assuming tags are in order)
|
|
9954
9965
|
next unless exists $$tagHash{$tagID}; # only extract required tags
|
|
9955
9966
|
my $format = Get16u($dataPt, $entry+2);
|
|
9956
9967
|
next if $format < 1 or $format > 13;
|