exiftool-vendored.pl 12.56.0 → 12.62.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.
- package/bin/Changes +115 -5
- package/bin/LICENSE +674 -0
- package/bin/MANIFEST +11 -0
- package/bin/META.json +1 -1
- package/bin/META.yml +1 -1
- package/bin/README +45 -44
- package/bin/config_files/example.config +1 -0
- package/bin/config_files/rotate_regions.config +1 -1
- package/bin/exiftool +262 -160
- package/bin/lib/Image/ExifTool/AIFF.pm +2 -2
- package/bin/lib/Image/ExifTool/APE.pm +2 -2
- package/bin/lib/Image/ExifTool/BMP.pm +0 -1
- package/bin/lib/Image/ExifTool/BuildTagLookup.pm +23 -19
- package/bin/lib/Image/ExifTool/Canon.pm +26 -6
- package/bin/lib/Image/ExifTool/CanonRaw.pm +5 -1
- package/bin/lib/Image/ExifTool/DJI.pm +28 -2
- package/bin/lib/Image/ExifTool/Exif.pm +77 -19
- package/bin/lib/Image/ExifTool/FlashPix.pm +33 -10
- package/bin/lib/Image/ExifTool/FujiFilm.pm +7 -3
- package/bin/lib/Image/ExifTool/GPS.pm +7 -2
- package/bin/lib/Image/ExifTool/Geotag.pm +30 -7
- package/bin/lib/Image/ExifTool/JPEG.pm +14 -2
- package/bin/lib/Image/ExifTool/Jpeg2000.pm +36 -11
- package/bin/lib/Image/ExifTool/LIF.pm +10 -2
- package/bin/lib/Image/ExifTool/LNK.pm +5 -4
- package/bin/lib/Image/ExifTool/MIE.pm +3 -3
- package/bin/lib/Image/ExifTool/MPEG.pm +2 -2
- package/bin/lib/Image/ExifTool/MakerNotes.pm +3 -2
- package/bin/lib/Image/ExifTool/Minolta.pm +6 -7
- package/bin/lib/Image/ExifTool/MinoltaRaw.pm +2 -1
- package/bin/lib/Image/ExifTool/Nikon.pm +1005 -909
- package/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
- package/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
- package/bin/lib/Image/ExifTool/Olympus.pm +88 -6
- package/bin/lib/Image/ExifTool/PDF.pm +17 -8
- package/bin/lib/Image/ExifTool/PNG.pm +10 -2
- package/bin/lib/Image/ExifTool/PanasonicRaw.pm +27 -1
- package/bin/lib/Image/ExifTool/Pentax.pm +8 -5
- package/bin/lib/Image/ExifTool/PhaseOne.pm +14 -1
- package/bin/lib/Image/ExifTool/Photoshop.pm +38 -7
- package/bin/lib/Image/ExifTool/QuickTime.pm +48 -14
- package/bin/lib/Image/ExifTool/QuickTimeStream.pl +91 -27
- package/bin/lib/Image/ExifTool/README +19 -2
- package/bin/lib/Image/ExifTool/RIFF.pm +34 -13
- package/bin/lib/Image/ExifTool/Rawzor.pm +2 -2
- package/bin/lib/Image/ExifTool/Ricoh.pm +2 -1
- package/bin/lib/Image/ExifTool/Sigma.pm +5 -4
- package/bin/lib/Image/ExifTool/SigmaRaw.pm +9 -3
- package/bin/lib/Image/ExifTool/Sony.pm +39 -10
- package/bin/lib/Image/ExifTool/TagLookup.pm +4687 -4628
- package/bin/lib/Image/ExifTool/TagNames.pod +338 -117
- package/bin/lib/Image/ExifTool/Validate.pm +5 -5
- package/bin/lib/Image/ExifTool/WPG.pm +296 -0
- package/bin/lib/Image/ExifTool/WriteExif.pl +42 -0
- package/bin/lib/Image/ExifTool/WritePDF.pl +7 -8
- package/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
- package/bin/lib/Image/ExifTool/Writer.pl +162 -40
- package/bin/lib/Image/ExifTool/XMP.pm +35 -8
- package/bin/lib/Image/ExifTool/XMP2.pl +2 -1
- package/bin/lib/Image/ExifTool/ZIP.pm +159 -41
- package/bin/lib/Image/ExifTool.pm +286 -65
- package/bin/lib/Image/ExifTool.pod +95 -51
- package/bin/perl-Image-ExifTool.spec +44 -43
- package/bin/pp_build_exe.args +5 -4
- package/package.json +3 -3
|
@@ -56,7 +56,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
|
|
|
56
56
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
57
57
|
use Image::ExifTool::MakerNotes;
|
|
58
58
|
|
|
59
|
-
$VERSION = '4.
|
|
59
|
+
$VERSION = '4.44';
|
|
60
60
|
|
|
61
61
|
sub ProcessExif($$$);
|
|
62
62
|
sub WriteExif($$$);
|
|
@@ -65,6 +65,7 @@ sub RebuildMakerNotes($$$);
|
|
|
65
65
|
sub EncodeExifText($$);
|
|
66
66
|
sub ValidateIFD($;$);
|
|
67
67
|
sub ValidateImageData($$$;$);
|
|
68
|
+
sub AddImageDataMD5($$$);
|
|
68
69
|
sub ProcessTiffIFD($$$);
|
|
69
70
|
sub PrintParameter($$$);
|
|
70
71
|
sub GetOffList($$$$$);
|
|
@@ -573,6 +574,7 @@ my %opcodeInfo = (
|
|
|
573
574
|
],
|
|
574
575
|
Name => 'StripOffsets',
|
|
575
576
|
IsOffset => 1,
|
|
577
|
+
IsImageData => 1,
|
|
576
578
|
OffsetPair => 0x117, # point to associated byte counts
|
|
577
579
|
# A200 stores this information in the wrong byte order!!
|
|
578
580
|
ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
|
|
@@ -582,6 +584,7 @@ my %opcodeInfo = (
|
|
|
582
584
|
Condition => '$$self{Compression} and $$self{Compression} eq "34892"', # DNG Lossy JPEG
|
|
583
585
|
Name => 'OtherImageStart',
|
|
584
586
|
IsOffset => 1,
|
|
587
|
+
IsImageData => 1,
|
|
585
588
|
OffsetPair => 0x117, # point to associated byte counts
|
|
586
589
|
DataTag => 'OtherImage',
|
|
587
590
|
},
|
|
@@ -594,6 +597,7 @@ my %opcodeInfo = (
|
|
|
594
597
|
],
|
|
595
598
|
Name => 'StripOffsets',
|
|
596
599
|
IsOffset => 1,
|
|
600
|
+
IsImageData => 1,
|
|
597
601
|
OffsetPair => 0x117, # point to associated byte counts
|
|
598
602
|
ValueConv => 'length($val) > 32 ? \$val : $val',
|
|
599
603
|
},
|
|
@@ -630,6 +634,7 @@ my %opcodeInfo = (
|
|
|
630
634
|
# JpgFromRawStart in various IFD's of DNG images except SubIFD2
|
|
631
635
|
Name => 'JpgFromRawStart',
|
|
632
636
|
IsOffset => 1,
|
|
637
|
+
IsImageData => 1,
|
|
633
638
|
OffsetPair => 0x117,
|
|
634
639
|
DataTag => 'JpgFromRaw',
|
|
635
640
|
Writable => 'int32u',
|
|
@@ -933,6 +938,7 @@ my %opcodeInfo = (
|
|
|
933
938
|
0x144 => {
|
|
934
939
|
Name => 'TileOffsets',
|
|
935
940
|
IsOffset => 1,
|
|
941
|
+
IsImageData => 1,
|
|
936
942
|
OffsetPair => 0x145,
|
|
937
943
|
ValueConv => 'length($val) > 32 ? \$val : $val',
|
|
938
944
|
},
|
|
@@ -1187,6 +1193,7 @@ my %opcodeInfo = (
|
|
|
1187
1193
|
Name => 'JpgFromRawStart',
|
|
1188
1194
|
Condition => '$$self{DIR_NAME} eq "SubIFD"',
|
|
1189
1195
|
IsOffset => 1,
|
|
1196
|
+
IsImageData => 1,
|
|
1190
1197
|
OffsetPair => 0x202,
|
|
1191
1198
|
DataTag => 'JpgFromRaw',
|
|
1192
1199
|
Writable => 'int32u',
|
|
@@ -1199,6 +1206,7 @@ my %opcodeInfo = (
|
|
|
1199
1206
|
Name => 'JpgFromRawStart',
|
|
1200
1207
|
Condition => '$$self{DIR_NAME} eq "IFD2"',
|
|
1201
1208
|
IsOffset => 1,
|
|
1209
|
+
IsImageData => 1,
|
|
1202
1210
|
OffsetPair => 0x202,
|
|
1203
1211
|
DataTag => 'JpgFromRaw',
|
|
1204
1212
|
Writable => 'int32u',
|
|
@@ -1210,6 +1218,7 @@ my %opcodeInfo = (
|
|
|
1210
1218
|
{
|
|
1211
1219
|
Name => 'OtherImageStart',
|
|
1212
1220
|
Condition => '$$self{DIR_NAME} eq "SubIFD1"',
|
|
1221
|
+
IsImageData => 1,
|
|
1213
1222
|
IsOffset => 1,
|
|
1214
1223
|
OffsetPair => 0x202,
|
|
1215
1224
|
DataTag => 'OtherImage',
|
|
@@ -1222,6 +1231,7 @@ my %opcodeInfo = (
|
|
|
1222
1231
|
Name => 'OtherImageStart',
|
|
1223
1232
|
Condition => '$$self{DIR_NAME} eq "SubIFD2"',
|
|
1224
1233
|
IsOffset => 1,
|
|
1234
|
+
IsImageData => 1,
|
|
1225
1235
|
OffsetPair => 0x202,
|
|
1226
1236
|
DataTag => 'OtherImage',
|
|
1227
1237
|
Writable => 'int32u',
|
|
@@ -1232,6 +1242,7 @@ my %opcodeInfo = (
|
|
|
1232
1242
|
{
|
|
1233
1243
|
Name => 'OtherImageStart',
|
|
1234
1244
|
IsOffset => 1,
|
|
1245
|
+
IsImageData => 1,
|
|
1235
1246
|
OffsetPair => 0x202,
|
|
1236
1247
|
},
|
|
1237
1248
|
],
|
|
@@ -1500,9 +1511,10 @@ my %opcodeInfo = (
|
|
|
1500
1511
|
0x7031 => {
|
|
1501
1512
|
Name => 'VignettingCorrection',
|
|
1502
1513
|
Notes => 'found in Sony ARW images',
|
|
1503
|
-
Protected => 1,
|
|
1504
1514
|
Writable => 'int16s',
|
|
1505
1515
|
WriteGroup => 'SubIFD',
|
|
1516
|
+
Permanent => 1,
|
|
1517
|
+
Protected => 1,
|
|
1506
1518
|
PrintConv => {
|
|
1507
1519
|
256 => 'Off',
|
|
1508
1520
|
257 => 'Auto',
|
|
@@ -1513,17 +1525,19 @@ my %opcodeInfo = (
|
|
|
1513
1525
|
0x7032 => {
|
|
1514
1526
|
Name => 'VignettingCorrParams', #forum7640
|
|
1515
1527
|
Notes => 'found in Sony ARW images',
|
|
1516
|
-
Protected => 1,
|
|
1517
1528
|
Writable => 'int16s',
|
|
1518
1529
|
WriteGroup => 'SubIFD',
|
|
1519
1530
|
Count => 17,
|
|
1531
|
+
Permanent => 1,
|
|
1532
|
+
Protected => 1,
|
|
1520
1533
|
},
|
|
1521
1534
|
0x7034 => {
|
|
1522
1535
|
Name => 'ChromaticAberrationCorrection',
|
|
1523
1536
|
Notes => 'found in Sony ARW images',
|
|
1524
|
-
Protected => 1,
|
|
1525
1537
|
Writable => 'int16s',
|
|
1526
1538
|
WriteGroup => 'SubIFD',
|
|
1539
|
+
Permanent => 1,
|
|
1540
|
+
Protected => 1,
|
|
1527
1541
|
PrintConv => {
|
|
1528
1542
|
0 => 'Off',
|
|
1529
1543
|
1 => 'Auto',
|
|
@@ -1533,17 +1547,19 @@ my %opcodeInfo = (
|
|
|
1533
1547
|
0x7035 => {
|
|
1534
1548
|
Name => 'ChromaticAberrationCorrParams', #forum6509
|
|
1535
1549
|
Notes => 'found in Sony ARW images',
|
|
1536
|
-
Protected => 1,
|
|
1537
1550
|
Writable => 'int16s',
|
|
1538
1551
|
WriteGroup => 'SubIFD',
|
|
1539
1552
|
Count => 33,
|
|
1553
|
+
Permanent => 1,
|
|
1554
|
+
Protected => 1,
|
|
1540
1555
|
},
|
|
1541
1556
|
0x7036 => {
|
|
1542
1557
|
Name => 'DistortionCorrection',
|
|
1543
1558
|
Notes => 'found in Sony ARW images',
|
|
1544
|
-
Protected => 1,
|
|
1545
1559
|
Writable => 'int16s',
|
|
1546
1560
|
WriteGroup => 'SubIFD',
|
|
1561
|
+
Permanent => 1,
|
|
1562
|
+
Protected => 1,
|
|
1547
1563
|
PrintConv => {
|
|
1548
1564
|
0 => 'Off',
|
|
1549
1565
|
1 => 'Auto',
|
|
@@ -1554,10 +1570,38 @@ my %opcodeInfo = (
|
|
|
1554
1570
|
0x7037 => {
|
|
1555
1571
|
Name => 'DistortionCorrParams', #forum6509
|
|
1556
1572
|
Notes => 'found in Sony ARW images',
|
|
1557
|
-
Protected => 1,
|
|
1558
1573
|
Writable => 'int16s',
|
|
1559
1574
|
WriteGroup => 'SubIFD',
|
|
1560
1575
|
Count => 17,
|
|
1576
|
+
Permanent => 1,
|
|
1577
|
+
Protected => 1,
|
|
1578
|
+
},
|
|
1579
|
+
0x7038 => { #github#195 (Sony ARW)
|
|
1580
|
+
Name => 'SonyRawImageSize',
|
|
1581
|
+
Notes => 'size of actual image in Sony ARW files',
|
|
1582
|
+
Writable => 'int32u',
|
|
1583
|
+
WriteGroup => 'SubIFD',
|
|
1584
|
+
Count => 2,
|
|
1585
|
+
Permanent => 1,
|
|
1586
|
+
Protected => 1,
|
|
1587
|
+
},
|
|
1588
|
+
0x7310 => { #github#195 (Sony ARW)
|
|
1589
|
+
Name => 'BlackLevel',
|
|
1590
|
+
Notes => 'found in Sony ARW images',
|
|
1591
|
+
Writable => 'int16u',
|
|
1592
|
+
WriteGroup => 'SubIFD',
|
|
1593
|
+
Count => 4,
|
|
1594
|
+
Permanent => 1,
|
|
1595
|
+
Protected => 1,
|
|
1596
|
+
},
|
|
1597
|
+
0x7313 => { #github#195 (Sony ARW)
|
|
1598
|
+
Name => 'WB_RGGBLevels',
|
|
1599
|
+
Notes => 'found in Sony ARW images',
|
|
1600
|
+
Writable => 'int16s',
|
|
1601
|
+
WriteGroup => 'SubIFD',
|
|
1602
|
+
Count => 4,
|
|
1603
|
+
Permanent => 1,
|
|
1604
|
+
Protected => 1,
|
|
1561
1605
|
},
|
|
1562
1606
|
0x74c7 => { #IB (in ARW images from some Sony cameras)
|
|
1563
1607
|
Name => 'SonyCropTopLeft',
|
|
@@ -2968,6 +3012,7 @@ my %opcodeInfo = (
|
|
|
2968
3012
|
0xbcc0 => { #13
|
|
2969
3013
|
Name => 'ImageOffset',
|
|
2970
3014
|
IsOffset => 1,
|
|
3015
|
+
IsImageData => 1,
|
|
2971
3016
|
OffsetPair => 0xbcc1, # point to associated byte count
|
|
2972
3017
|
},
|
|
2973
3018
|
0xbcc1 => { #13
|
|
@@ -2977,6 +3022,7 @@ my %opcodeInfo = (
|
|
|
2977
3022
|
0xbcc2 => { #13
|
|
2978
3023
|
Name => 'AlphaOffset',
|
|
2979
3024
|
IsOffset => 1,
|
|
3025
|
+
IsImageData => 1,
|
|
2980
3026
|
OffsetPair => 0xbcc3, # point to associated byte count
|
|
2981
3027
|
},
|
|
2982
3028
|
0xbcc3 => { #13
|
|
@@ -5880,15 +5926,17 @@ sub ProcessExif($$$)
|
|
|
5880
5926
|
my $base = $$dirInfo{Base} || 0;
|
|
5881
5927
|
my $firstBase = $base;
|
|
5882
5928
|
my $raf = $$dirInfo{RAF};
|
|
5883
|
-
my $verbose =
|
|
5884
|
-
my $validate = $et->Options('Validate');
|
|
5885
|
-
my $saveFormat = $et->Options('SaveFormat');
|
|
5929
|
+
my ($verbose,$validate,$saveFormat) = @{$$et{OPTIONS}}{qw(Verbose Validate SaveFormat)};
|
|
5886
5930
|
my $htmlDump = $$et{HTML_DUMP};
|
|
5887
5931
|
my $success = 1;
|
|
5888
|
-
my ($tagKey, $dirSize, $makerAddr, $strEnc, %offsetInfo, $offName, $nextOffName);
|
|
5932
|
+
my ($tagKey, $dirSize, $makerAddr, $strEnc, %offsetInfo, $offName, $nextOffName, $doMD5);
|
|
5889
5933
|
my $inMakerNotes = $$tagTablePtr{GROUPS}{0} eq 'MakerNotes';
|
|
5890
5934
|
my $isExif = ($tagTablePtr eq \%Image::ExifTool::Exif::Main);
|
|
5891
5935
|
|
|
5936
|
+
# set flag to calculate image data MD5 if requested
|
|
5937
|
+
$doMD5 = 1 if $$et{ImageDataMD5} and (($$et{FILE_TYPE} eq 'TIFF' and not $base and not $inMakerNotes) or
|
|
5938
|
+
($$et{FILE_TYPE} eq 'RAF' and $dirName eq 'FujiIFD'));
|
|
5939
|
+
|
|
5892
5940
|
# set encoding to assume for strings
|
|
5893
5941
|
$strEnc = $et->Options('CharsetEXIF') if $$tagTablePtr{GROUPS}{0} eq 'EXIF';
|
|
5894
5942
|
|
|
@@ -5897,7 +5945,12 @@ sub ProcessExif($$$)
|
|
|
5897
5945
|
$isExif and $$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/)
|
|
5898
5946
|
{
|
|
5899
5947
|
my $path = $et->MetadataPath();
|
|
5900
|
-
|
|
5948
|
+
if ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) {
|
|
5949
|
+
unless ($$et{DOC_NUM}) {
|
|
5950
|
+
$et->Warn("Duplicate EXIF at $path") if $$et{HasExif};
|
|
5951
|
+
$$et{HasExif} = 1;
|
|
5952
|
+
}
|
|
5953
|
+
} else {
|
|
5901
5954
|
if ($Image::ExifTool::MWG::strict) {
|
|
5902
5955
|
$et->Warn("Ignored non-standard EXIF at $path");
|
|
5903
5956
|
return 0;
|
|
@@ -6361,10 +6414,10 @@ sub ProcessExif($$$)
|
|
|
6361
6414
|
$tval .= " ($rational)" if defined $rational;
|
|
6362
6415
|
if ($htmlDump) {
|
|
6363
6416
|
my ($tagName, $colName);
|
|
6364
|
-
if ($
|
|
6365
|
-
$tagName = 'MakerNotes';
|
|
6366
|
-
} elsif ($tagInfo) {
|
|
6417
|
+
if ($tagInfo) {
|
|
6367
6418
|
$tagName = $$tagInfo{Name};
|
|
6419
|
+
} elsif ($tagID == 0x927c and $dirName eq 'ExifIFD') {
|
|
6420
|
+
$tagName = 'MakerNotes';
|
|
6368
6421
|
} else {
|
|
6369
6422
|
$tagName = sprintf("Tag 0x%.4x",$tagID);
|
|
6370
6423
|
}
|
|
@@ -6439,6 +6492,9 @@ sub ProcessExif($$$)
|
|
|
6439
6492
|
}
|
|
6440
6493
|
# add value data block (underlining maker notes data)
|
|
6441
6494
|
$et->HDump($exifDumpPos,$size,"$tagName value",'SAME', $flag, $sid);
|
|
6495
|
+
if ($subdir and $$tagInfo{MakerNotes} and $$tagInfo{NotIFD}) {
|
|
6496
|
+
$et->HDump($exifDumpPos,$size,"$tagName value",undef,undef,$$dirInfo{OffsetName});
|
|
6497
|
+
}
|
|
6442
6498
|
}
|
|
6443
6499
|
} else {
|
|
6444
6500
|
if ($tagID <= $lastID and not $inMakerNotes) {
|
|
@@ -6725,7 +6781,7 @@ sub ProcessExif($$$)
|
|
|
6725
6781
|
}
|
|
6726
6782
|
$val = join(' ', @vals);
|
|
6727
6783
|
}
|
|
6728
|
-
if ($validate) {
|
|
6784
|
+
if ($validate or $doMD5) {
|
|
6729
6785
|
if ($$tagInfo{OffsetPair}) {
|
|
6730
6786
|
$offsetInfo{$tagID} = [ $tagInfo, $val ];
|
|
6731
6787
|
} elsif ($saveForValidate{$tagID} and $isExif) {
|
|
@@ -6743,9 +6799,11 @@ sub ProcessExif($$$)
|
|
|
6743
6799
|
}
|
|
6744
6800
|
}
|
|
6745
6801
|
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6802
|
+
if (%offsetInfo) {
|
|
6803
|
+
# calculate image data MD5 if requested
|
|
6804
|
+
AddImageDataMD5($et, $dirInfo, \%offsetInfo) if $doMD5;
|
|
6805
|
+
# validate image data offsets for this IFD (note: modifies %offsetInfo)
|
|
6806
|
+
Image::ExifTool::Validate::ValidateOffsetInfo($et, \%offsetInfo, $dirName, $inMakerNotes) if $validate;
|
|
6749
6807
|
}
|
|
6750
6808
|
|
|
6751
6809
|
# scan for subsequent IFD's if specified
|
|
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
21
21
|
use Image::ExifTool::Exif;
|
|
22
22
|
use Image::ExifTool::ASF; # for GetGUID()
|
|
23
23
|
|
|
24
|
-
$VERSION = '1.
|
|
24
|
+
$VERSION = '1.45';
|
|
25
25
|
|
|
26
26
|
sub ProcessFPX($$);
|
|
27
27
|
sub ProcessFPXR($$$);
|
|
@@ -318,6 +318,10 @@ my %fpxFileType = (
|
|
|
318
318
|
unrecognized Windows Compound Binary file as a FlashPix (FPX) file. See
|
|
319
319
|
L<http://graphcomp.com/info/specs/livepicture/fpx.pdf> for the FlashPix
|
|
320
320
|
specification.
|
|
321
|
+
|
|
322
|
+
Note that Microsoft is not consistent with the time zone used for some
|
|
323
|
+
date/time tags, and it may be either UTC or local time depending on the
|
|
324
|
+
software used to create the file.
|
|
321
325
|
},
|
|
322
326
|
"\x05SummaryInformation" => {
|
|
323
327
|
Name => 'SummaryInfo',
|
|
@@ -484,16 +488,27 @@ my %fpxFileType = (
|
|
|
484
488
|
IeImg => {
|
|
485
489
|
Name => 'EmbeddedImage',
|
|
486
490
|
Notes => q{
|
|
487
|
-
embedded images in Scene7 vignette VNT files.
|
|
488
|
-
|
|
489
|
-
corresponding EmbeddedImage via the family 3 group name
|
|
491
|
+
embedded images in Scene7 vignette VNT files. The EmbeddedImage Class and
|
|
492
|
+
Rectangle are also extracted for applicable images, and may be associated
|
|
493
|
+
with the corresponding EmbeddedImage via the family 3 group name
|
|
490
494
|
},
|
|
491
495
|
Groups => { 2 => 'Preview' },
|
|
492
496
|
Binary => 1,
|
|
493
497
|
},
|
|
494
|
-
|
|
498
|
+
IeImg_class => {
|
|
499
|
+
Name => 'EmbeddedImageClass',
|
|
500
|
+
Notes => q{
|
|
501
|
+
not a real tag. This information is extracted if available for the
|
|
502
|
+
corresponding EmbeddedImage from the Contents of a VNT file
|
|
503
|
+
},
|
|
504
|
+
# eg. "Cache", "Mask"
|
|
505
|
+
},
|
|
506
|
+
IeImg_rect => { #
|
|
495
507
|
Name => 'EmbeddedImageRectangle',
|
|
496
|
-
|
|
508
|
+
Notes => q{
|
|
509
|
+
not a real tag. This information is extracted if available for the
|
|
510
|
+
corresponding EmbeddedImage from the Contents of a VNT file
|
|
511
|
+
},
|
|
497
512
|
},
|
|
498
513
|
);
|
|
499
514
|
|
|
@@ -1524,6 +1539,7 @@ sub ReadFPXValue($$$$$;$$)
|
|
|
1524
1539
|
}
|
|
1525
1540
|
$_[2] = $valPos; # return updated value position
|
|
1526
1541
|
|
|
1542
|
+
push @vals, '' if $type eq 0; # (VT_EMPTY)
|
|
1527
1543
|
if (wantarray) {
|
|
1528
1544
|
return @vals;
|
|
1529
1545
|
} elsif (@vals > 1) {
|
|
@@ -1573,13 +1589,16 @@ sub ProcessContents($$$)
|
|
|
1573
1589
|
pos($$dataPt) += $size;
|
|
1574
1590
|
}
|
|
1575
1591
|
$$et{IeImg_lkup} = { };
|
|
1576
|
-
|
|
1592
|
+
$$et{IeImg_class} = { };
|
|
1593
|
+
# - the byte before \x80 is 0x0d, 0x11 or 0x1f for separate images in my samples,
|
|
1577
1594
|
# and 0x1c or 0x23 for inline masks
|
|
1578
|
-
|
|
1579
|
-
|
|
1595
|
+
# - the byte after \xff\xff is 0x3b in my samples for $1 containing 'VnMask' or 'VnCache'
|
|
1596
|
+
while ($$dataPt =~ /\x0bTargetRole1(?:.\x80|\xff\xff.\0.\0Vn(\w+))\0\0\x01.{4}(.{24})/sg) {
|
|
1597
|
+
my ($index, @coords) = unpack('Vx4V4', $2);
|
|
1580
1598
|
next if $index == 0xffffffff;
|
|
1581
1599
|
$$et{IeImg_lkup}{$index} and $et->WarnOnce('Duplicate image index');
|
|
1582
1600
|
$$et{IeImg_lkup}{$index} = "@coords";
|
|
1601
|
+
$$et{IeImg_class}{$index} = $1 if $1;
|
|
1583
1602
|
}
|
|
1584
1603
|
}
|
|
1585
1604
|
}
|
|
@@ -2391,6 +2410,10 @@ sub ProcessFPX($$)
|
|
|
2391
2410
|
# save position of this image
|
|
2392
2411
|
$et->HandleTag($tagTablePtr, IeImg_rect => $$et{IeImg_lkup}{$num});
|
|
2393
2412
|
delete $$et{IeImg_lkup}{$num};
|
|
2413
|
+
if ($$et{IeImg_class} and $$et{IeImg_class}{$num}) {
|
|
2414
|
+
$et->HandleTag($tagTablePtr, IeImg_class => $$et{IeImg_class}{$num});
|
|
2415
|
+
delete $$et{IeImg_class}{$num};
|
|
2416
|
+
}
|
|
2394
2417
|
}
|
|
2395
2418
|
delete $$et{DOC_NUM};
|
|
2396
2419
|
} else {
|
|
@@ -2437,7 +2460,7 @@ sub ProcessFPX($$)
|
|
|
2437
2460
|
}
|
|
2438
2461
|
$$et{INDENT} = $oldIndent if $verbose;
|
|
2439
2462
|
# try to better identify the file type
|
|
2440
|
-
if ($$et{
|
|
2463
|
+
if ($$et{FileType} eq 'FPX') {
|
|
2441
2464
|
my $val = $$et{CompObjUserType} || $$et{Software};
|
|
2442
2465
|
if ($val) {
|
|
2443
2466
|
my %type = ( '^3ds Max' => 'MAX', Word => 'DOC', PowerPoint => 'PPT', Excel => 'XLS' );
|
|
@@ -1372,6 +1372,7 @@ my %faceCategories = (
|
|
|
1372
1372
|
0xf007 => {
|
|
1373
1373
|
Name => 'StripOffsets',
|
|
1374
1374
|
IsOffset => 1,
|
|
1375
|
+
IsImageData => 1,
|
|
1375
1376
|
OffsetPair => 0xf008, # point to associated byte counts
|
|
1376
1377
|
},
|
|
1377
1378
|
0xf008 => {
|
|
@@ -1670,11 +1671,11 @@ sub ProcessRAF($$)
|
|
|
1670
1671
|
my ($rafNum, $ifdNum) = ('','');
|
|
1671
1672
|
foreach $offset (0x5c, 0x64, 0x78, 0x80) {
|
|
1672
1673
|
last if $offset >= $jpos;
|
|
1673
|
-
unless ($raf->Seek($offset, 0) and $raf->Read($buff,
|
|
1674
|
+
unless ($raf->Seek($offset, 0) and $raf->Read($buff, 8)) {
|
|
1674
1675
|
$warn = 1;
|
|
1675
1676
|
last;
|
|
1676
1677
|
}
|
|
1677
|
-
my $start = unpack('
|
|
1678
|
+
my ($start, $len) = unpack('N2',$buff);
|
|
1678
1679
|
next unless $start;
|
|
1679
1680
|
if ($offset == 0x64 or $offset == 0x80) {
|
|
1680
1681
|
# parse FujiIFD directory
|
|
@@ -1685,7 +1686,10 @@ sub ProcessRAF($$)
|
|
|
1685
1686
|
$$et{SET_GROUP1} = "FujiIFD$ifdNum";
|
|
1686
1687
|
my $tagTablePtr = GetTagTable('Image::ExifTool::FujiFilm::IFD');
|
|
1687
1688
|
# this is TIFF-format data only for some models, so no warning if it fails
|
|
1688
|
-
$et->ProcessTIFF(\%dirInfo, $tagTablePtr, \&Image::ExifTool::ProcessTIFF)
|
|
1689
|
+
unless ($et->ProcessTIFF(\%dirInfo, $tagTablePtr, \&Image::ExifTool::ProcessTIFF)) {
|
|
1690
|
+
# do MD5 of image data if necessary
|
|
1691
|
+
$et->ImageDataMD5($raf, $len, 'raw') if $$et{ImageDataMD5} and $raf->Seek($start,0);
|
|
1692
|
+
}
|
|
1689
1693
|
delete $$et{SET_GROUP1};
|
|
1690
1694
|
$ifdNum = ($ifdNum || 1) + 1;
|
|
1691
1695
|
} else {
|
|
@@ -482,13 +482,13 @@ sub PrintTimeStamp($)
|
|
|
482
482
|
#------------------------------------------------------------------------------
|
|
483
483
|
# Convert degrees to DMS, or whatever the current settings are
|
|
484
484
|
# Inputs: 0) ExifTool reference, 1) Value in degrees,
|
|
485
|
-
# 2) format code (0=no format, 1=CoordFormat, 2=XMP format)
|
|
485
|
+
# 2) format code (0=no format, 1=CoordFormat, 2=XMP format, 3=signed unformatted)
|
|
486
486
|
# 3) 'N' or 'E' if sign is significant and N/S/E/W should be added
|
|
487
487
|
# Returns: DMS string
|
|
488
488
|
sub ToDMS($$;$$)
|
|
489
489
|
{
|
|
490
490
|
my ($et, $val, $doPrintConv, $ref) = @_;
|
|
491
|
-
my ($fmt, @fmt, $num, $sign, $rtnVal);
|
|
491
|
+
my ($fmt, @fmt, $num, $sign, $rtnVal, $neg);
|
|
492
492
|
|
|
493
493
|
unless (length $val) {
|
|
494
494
|
# don't convert an empty value
|
|
@@ -505,6 +505,10 @@ sub ToDMS($$;$$)
|
|
|
505
505
|
}
|
|
506
506
|
$ref = " $ref" unless $doPrintConv and $doPrintConv eq '2';
|
|
507
507
|
} else {
|
|
508
|
+
if ($doPrintConv and $doPrintConv eq '3') {
|
|
509
|
+
$neg = 1 if $val < 0;
|
|
510
|
+
$doPrintConv = 0;
|
|
511
|
+
}
|
|
508
512
|
$val = abs($val);
|
|
509
513
|
$ref = '';
|
|
510
514
|
}
|
|
@@ -554,6 +558,7 @@ sub ToDMS($$;$$)
|
|
|
554
558
|
# trim trailing zeros in XMP
|
|
555
559
|
$rtnVal =~ s/(\d)0+$ref$/$1$ref/ if $doPrintConv eq '2';
|
|
556
560
|
} else {
|
|
561
|
+
$neg and map { $_ *= -1 } @c;
|
|
557
562
|
$rtnVal = "@c$ref";
|
|
558
563
|
}
|
|
559
564
|
return $rtnVal;
|
|
@@ -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.71';
|
|
33
33
|
|
|
34
34
|
sub JITTER() { return 2 } # maximum time jitter
|
|
35
35
|
|
|
@@ -92,7 +92,7 @@ my %isOrient = ( dir => 1, pitch => 1, roll => 1 ); # test for orientation key
|
|
|
92
92
|
# tags which may exist separately in some formats (eg. CSV)
|
|
93
93
|
my %sepTags = ( dir => 1, pitch => 1, roll => 1, track => 1, speed => 1 );
|
|
94
94
|
|
|
95
|
-
# conversion factors for GPSSpeed
|
|
95
|
+
# conversion factors for GPSSpeed (standard EXIF units only)
|
|
96
96
|
my %speedConv = (
|
|
97
97
|
'K' => 1.852, # km/h per knot
|
|
98
98
|
'M' => 1.150779448, # mph per knot
|
|
@@ -102,7 +102,14 @@ my %speedConv = (
|
|
|
102
102
|
'mph' => 'M',
|
|
103
103
|
);
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
# all recognized speed conversion factors (non-EXIF included)
|
|
106
|
+
my %otherConv = (
|
|
107
|
+
'km/h' => 1.852,
|
|
108
|
+
'mph' => 1.150779448,
|
|
109
|
+
'm/s' => 0.514444,
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
my $secPerDay = 24 * 3600; # a useful constant
|
|
106
113
|
|
|
107
114
|
#------------------------------------------------------------------------------
|
|
108
115
|
# Load GPS track log file
|
|
@@ -140,6 +147,7 @@ sub LoadTrackLog($$;$)
|
|
|
140
147
|
my ($raf, $from, $time, $isDate, $noDate, $noDateChanged, $lastDate, $dateFlarm);
|
|
141
148
|
my ($nmeaStart, $fixSecs, @fixTimes, $lastFix, %nmea, @csvHeadings, $sortFixes);
|
|
142
149
|
my ($canCut, $cutPDOP, $cutHDOP, $cutSats, $e0, $e1, @tmp, $trackFile, $trackTime);
|
|
150
|
+
my $scaleSpeed;
|
|
143
151
|
|
|
144
152
|
unless (eval { require Time::Local }) {
|
|
145
153
|
return 'Geotag feature requires Time::Local installed';
|
|
@@ -246,7 +254,9 @@ sub LoadTrackLog($$;$)
|
|
|
246
254
|
$format = 'CSV';
|
|
247
255
|
# convert recognized headings to our parameter names
|
|
248
256
|
foreach (@csvHeadings) {
|
|
257
|
+
my $head = $_;
|
|
249
258
|
my $param;
|
|
259
|
+
my $xtra = '';
|
|
250
260
|
s/^GPS ?//; # remove leading "GPS" to simplify regex patterns
|
|
251
261
|
if (/^Time ?\(seconds\)$/i) { # DJI
|
|
252
262
|
# DJI CSV log files have a column "Time(seconds)" which is seconds since
|
|
@@ -274,7 +284,16 @@ sub LoadTrackLog($$;$)
|
|
|
274
284
|
/ref$/i and $param .= 'ref';
|
|
275
285
|
} elsif (/^(Pos)?Alt/i) {
|
|
276
286
|
$param = 'alt';
|
|
277
|
-
} elsif (/^
|
|
287
|
+
} elsif (/^Speed/i) {
|
|
288
|
+
$param = 'speed';
|
|
289
|
+
# (recognize units in brackets)
|
|
290
|
+
if (m{\((mph|km/h|m/s)\)}) {
|
|
291
|
+
$scaleSpeed = $otherConv{$1};
|
|
292
|
+
$xtra = " in $1";
|
|
293
|
+
} else {
|
|
294
|
+
$xtra = ' in knots';
|
|
295
|
+
}
|
|
296
|
+
} elsif (/^(Angle)?(Heading|Track|Bearing)/i) {
|
|
278
297
|
$param = 'track';
|
|
279
298
|
} elsif (/^(Angle)?Pitch/i or /^Camera ?Elevation ?Angle/i) {
|
|
280
299
|
$param = 'pitch';
|
|
@@ -284,10 +303,10 @@ sub LoadTrackLog($$;$)
|
|
|
284
303
|
$param = 'dir';
|
|
285
304
|
}
|
|
286
305
|
if ($param) {
|
|
287
|
-
$et->VPrint(2, "CSV column '${
|
|
306
|
+
$et->VPrint(2, "CSV column '${head}' is $param$xtra\n");
|
|
288
307
|
$_ = $param;
|
|
289
308
|
} else {
|
|
290
|
-
$et->VPrint(2, "CSV column '${
|
|
309
|
+
$et->VPrint(2, "CSV column '${head}' ignored\n");
|
|
291
310
|
$_ = ''; # ignore this column
|
|
292
311
|
}
|
|
293
312
|
}
|
|
@@ -479,9 +498,11 @@ DoneFix: $isDate = 1;
|
|
|
479
498
|
my ($param, $date, $secs, %neg);
|
|
480
499
|
foreach $param (@csvHeadings) {
|
|
481
500
|
my $val = shift @vals;
|
|
482
|
-
last unless defined $val;
|
|
501
|
+
last unless defined $val and length($val);
|
|
483
502
|
next unless $param;
|
|
484
503
|
if ($param eq 'datetime') {
|
|
504
|
+
# (fix formats like "24.07.2016 13:47:30")
|
|
505
|
+
$val =~ s/^(\d{2})[^\d](\d{2})[^\d](\d{4}) /$3:$2:$1 /;
|
|
485
506
|
local $SIG{'__WARN__'} = sub { };
|
|
486
507
|
my $dateTime = $et->InverseDateTime($val);
|
|
487
508
|
if ($dateTime) {
|
|
@@ -510,6 +531,7 @@ DoneFix: $isDate = 1;
|
|
|
510
531
|
$date = $trackTime;
|
|
511
532
|
$secs = $val;
|
|
512
533
|
} else {
|
|
534
|
+
$val /= $scaleSpeed if $scaleSpeed and $param eq 'speed';
|
|
513
535
|
$$fix{$param} = $val;
|
|
514
536
|
$$has{$param} = 1 if $sepTags{$param};
|
|
515
537
|
}
|
|
@@ -1204,6 +1226,7 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
|
|
|
1204
1226
|
@r = $et->SetNewValue(GPSTrackRef => (defined $$tFix{track} ? 'T' : undef), %opts);
|
|
1205
1227
|
my ($spd, $ref);
|
|
1206
1228
|
if (defined($spd = $$tFix{speed})) {
|
|
1229
|
+
# convert to specified units if necessary
|
|
1207
1230
|
$ref = $$et{OPTIONS}{GeoSpeedRef};
|
|
1208
1231
|
if ($ref and defined $speedConv{$ref}) {
|
|
1209
1232
|
$ref = $speedConv{$ref} if $speedConv{$speedConv{$ref}};
|
|
@@ -11,7 +11,7 @@ use strict;
|
|
|
11
11
|
use vars qw($VERSION);
|
|
12
12
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
13
13
|
|
|
14
|
-
$VERSION = '1.
|
|
14
|
+
$VERSION = '1.35';
|
|
15
15
|
|
|
16
16
|
sub ProcessOcad($$$);
|
|
17
17
|
sub ProcessJPEG_HDR($$$);
|
|
@@ -134,9 +134,17 @@ sub ProcessJPEG_HDR($$$);
|
|
|
134
134
|
Condition => '$$self{HasIJPEG}"',
|
|
135
135
|
SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Factory' },
|
|
136
136
|
}, {
|
|
137
|
-
Name => 'ThermalParams', # (written by DJI FLIR models)
|
|
137
|
+
Name => 'ThermalParams', # (written by some DJI FLIR models)
|
|
138
138
|
Condition => '$$self{Make} eq "DJI" and $$valPt =~ /^\xaa\x55\x12\x06/',
|
|
139
139
|
SubDirectory => { TagTable => 'Image::ExifTool::DJI::ThermalParams' },
|
|
140
|
+
}, {
|
|
141
|
+
Name => 'ThermalParams2', # (written by M3T)
|
|
142
|
+
Condition => '$$self{Make} eq "DJI" and $$valPt =~ /^(.{32})?.{32}\x2c\x01\x20\0/s',
|
|
143
|
+
SubDirectory => { TagTable => 'Image::ExifTool::DJI::ThermalParams2' },
|
|
144
|
+
}, {
|
|
145
|
+
Name => 'ThermalParams3', # (written by M30T)
|
|
146
|
+
Condition => '$$self{Make} eq "DJI" and $$valPt =~ /^.{32}\xaa\x55\x38\0/s',
|
|
147
|
+
SubDirectory => { TagTable => 'Image::ExifTool::DJI::ThermalParams3' },
|
|
140
148
|
}, {
|
|
141
149
|
Name => 'PreviewImage', # (eg. Samsung S1060)
|
|
142
150
|
Notes => 'continued from APP3',
|
|
@@ -207,6 +215,10 @@ sub ProcessJPEG_HDR($$$);
|
|
|
207
215
|
Name => 'InfiRayOpMode',
|
|
208
216
|
Condition => '$$self{HasIJPEG}',
|
|
209
217
|
SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::OpMode' },
|
|
218
|
+
}, {
|
|
219
|
+
Name => 'DJI-DBG',
|
|
220
|
+
Condition => '$$valPt =~ /^DJI-DBG\0/',
|
|
221
|
+
SubDirectory => { TagTable => 'Image::ExifTool::DJI::Info' },
|
|
210
222
|
}],
|
|
211
223
|
APP8 => [{
|
|
212
224
|
Name => 'SPIFF',
|