exiftool_vendored 12.55.0 → 12.57.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 +38 -1
- data/bin/MANIFEST +5 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +19 -19
- data/bin/arg_files/xmp2exif.args +4 -1
- data/bin/exiftool +97 -53
- data/bin/fmt_files/kml.fmt +3 -0
- data/bin/fmt_files/kml_track.fmt +3 -0
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +13 -6
- data/bin/lib/Image/ExifTool/Canon.pm +8 -2
- data/bin/lib/Image/ExifTool/Exif.pm +31 -2
- data/bin/lib/Image/ExifTool/FlashPix.pm +73 -8
- data/bin/lib/Image/ExifTool/FujiFilm.pm +2 -1
- data/bin/lib/Image/ExifTool/GPS.pm +7 -2
- data/bin/lib/Image/ExifTool/InfiRay.pm +227 -0
- data/bin/lib/Image/ExifTool/JPEG.pm +40 -6
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +5 -5
- data/bin/lib/Image/ExifTool/MIE.pm +3 -3
- data/bin/lib/Image/ExifTool/Nikon.pm +862 -1264
- data/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
- data/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
- data/bin/lib/Image/ExifTool/Olympus.pm +3 -1
- data/bin/lib/Image/ExifTool/OpenEXR.pm +32 -15
- data/bin/lib/Image/ExifTool/PNG.pm +80 -2
- data/bin/lib/Image/ExifTool/Photoshop.pm +36 -5
- data/bin/lib/Image/ExifTool/QuickTime.pm +18 -2
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +25 -14
- data/bin/lib/Image/ExifTool/README +11 -2
- data/bin/lib/Image/ExifTool/Real.pm +2 -2
- data/bin/lib/Image/ExifTool/Sigma.pm +2 -1
- data/bin/lib/Image/ExifTool/Sony.pm +5 -1
- data/bin/lib/Image/ExifTool/TagLookup.pm +4667 -4624
- data/bin/lib/Image/ExifTool/TagNames.pod +400 -90
- data/bin/lib/Image/ExifTool/VCard.pm +19 -5
- data/bin/lib/Image/ExifTool/Writer.pl +36 -16
- data/bin/lib/Image/ExifTool.pm +92 -35
- data/bin/lib/Image/ExifTool.pod +54 -53
- data/bin/perl-Image-ExifTool.spec +18 -18
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +3 -2
@@ -17,7 +17,7 @@ use strict;
|
|
17
17
|
use vars qw($VERSION);
|
18
18
|
use Image::ExifTool qw(:DataAccess :Utils);
|
19
19
|
|
20
|
-
$VERSION = '1.
|
20
|
+
$VERSION = '1.07';
|
21
21
|
|
22
22
|
my %unescapeVCard = ( '\\'=>'\\', ','=>',', 'n'=>"\n", 'N'=>"\n" );
|
23
23
|
|
@@ -190,6 +190,15 @@ my %timeInfo = (
|
|
190
190
|
'X-wr-alarmuid' => 'AlarmUID',
|
191
191
|
);
|
192
192
|
|
193
|
+
%Image::ExifTool::VCard::VNote = (
|
194
|
+
GROUPS => { 1 => 'VNote', 2 => 'Document' },
|
195
|
+
NOTES => 'Tags extracted from V-Note VNT files.',
|
196
|
+
Version => { },
|
197
|
+
Body => { },
|
198
|
+
Dcreated => { Name => 'CreateDate', Groups => { 2 => 'Time' }, %timeInfo },
|
199
|
+
'Last-modified' => { Name => 'ModifyDate', Groups => { 2 => 'Time' }, %timeInfo },
|
200
|
+
);
|
201
|
+
|
193
202
|
#------------------------------------------------------------------------------
|
194
203
|
# Get vCard tag, creating if necessary
|
195
204
|
# Inputs: 0) ExifTool ref, 1) tag table ref, 2) tag ID, 3) tag Name,
|
@@ -254,9 +263,14 @@ sub ProcessVCard($$)
|
|
254
263
|
my $raf = $$dirInfo{RAF};
|
255
264
|
my ($buff, $val, $ok, $component, %compNum, @count);
|
256
265
|
|
257
|
-
return 0 unless $raf->Read($buff, 24) and $raf->Seek(0,0) and $buff=~/^BEGIN:(VCARD|VCALENDAR)\r\n/i;
|
258
|
-
my
|
259
|
-
|
266
|
+
return 0 unless $raf->Read($buff, 24) and $raf->Seek(0,0) and $buff=~/^BEGIN:(VCARD|VCALENDAR|VNOTE)\r\n/i;
|
267
|
+
my %info = (
|
268
|
+
VCARD => [ qw(VCard vCard Main VCF) ],
|
269
|
+
VCALENDAR => [ qw(ICS iCalendar VCalendar ICS) ],
|
270
|
+
VNOTE => [ qw(VNote vNote VNote VNT text/v-note) ],
|
271
|
+
);
|
272
|
+
my ($type, $lbl, $tbl, $ext, $mime) = @{$info{uc($1)}};
|
273
|
+
$et->SetFileType($type, $mime, $ext);
|
260
274
|
return 1 if $$et{OPTIONS}{FastScan} and $$et{OPTIONS}{FastScan} == 3;
|
261
275
|
local $/ = "\r\n";
|
262
276
|
my $tagTablePtr = GetTagTable("Image::ExifTool::VCard::$tbl");
|
@@ -274,7 +288,7 @@ sub ProcessVCard($$)
|
|
274
288
|
}
|
275
289
|
if ($val =~ /^(BEGIN|END):(V?)(\w+)$/i) {
|
276
290
|
my ($begin, $v, $what) = ((lc($1) eq 'begin' ? 1 : 0), $2, ucfirst lc $3);
|
277
|
-
if ($what eq 'Card' or $what eq 'Calendar') {
|
291
|
+
if ($what eq 'Card' or $what eq 'Calendar' or $what eq 'Note') {
|
278
292
|
if ($begin) {
|
279
293
|
@count = ( { } ); # reset group counters
|
280
294
|
} else {
|
@@ -2727,8 +2727,10 @@ sub GetAllGroups($;$)
|
|
2727
2727
|
|
2728
2728
|
my @tableNames = keys %allTables;
|
2729
2729
|
|
2730
|
-
# loop through all tag tables and get all group names
|
2731
2730
|
my %allGroups;
|
2731
|
+
# add family 1 groups not in tables
|
2732
|
+
$family == 1 and map { $allGroups{$_} = 1 } qw(Garmin);
|
2733
|
+
# loop through all tag tables and get all group names
|
2732
2734
|
while (@tableNames) {
|
2733
2735
|
my $table = GetTagTable(pop @tableNames);
|
2734
2736
|
my ($grps, $grp, $tag, $tagInfo);
|
@@ -4267,7 +4269,7 @@ sub WriteDirectory($$$;$)
|
|
4267
4269
|
if ($out) {
|
4268
4270
|
print $out " Deleting $name\n" if defined $newData and not length $newData;
|
4269
4271
|
if ($$self{CHANGED} == $oldChanged and $$self{OPTIONS}{Verbose} > 2) {
|
4270
|
-
print $out "$$self{INDENT} [nothing changed in $
|
4272
|
+
print $out "$$self{INDENT} [nothing changed in $name]\n";
|
4271
4273
|
}
|
4272
4274
|
}
|
4273
4275
|
return $newData;
|
@@ -5432,7 +5434,6 @@ sub WriteJPEG($$)
|
|
5432
5434
|
my $verbose = $$self{OPTIONS}{Verbose};
|
5433
5435
|
my $out = $$self{OPTIONS}{TextOut};
|
5434
5436
|
my $rtnVal = 0;
|
5435
|
-
my %dumpParms = ( Out => $out );
|
5436
5437
|
my ($writeBuffer, $oldOutfile); # used to buffer writing until PreviewImage position is known
|
5437
5438
|
|
5438
5439
|
# check to be sure this is a valid JPG or EXV file
|
@@ -5447,7 +5448,6 @@ sub WriteJPEG($$)
|
|
5447
5448
|
Write($outfile,"\xff\x01") or $err = 1;
|
5448
5449
|
$isEXV = 1;
|
5449
5450
|
}
|
5450
|
-
$dumpParms{MaxLen} = 128 unless $verbose > 3;
|
5451
5451
|
|
5452
5452
|
delete $$self{PREVIEW_INFO}; # reset preview information
|
5453
5453
|
delete $$self{DEL_PREVIEW}; # reset flag to delete preview
|
@@ -6017,12 +6017,7 @@ sub WriteJPEG($$)
|
|
6017
6017
|
#
|
6018
6018
|
my $segDataPt = \$segData;
|
6019
6019
|
$length = length($segData);
|
6020
|
-
|
6021
|
-
print $out "JPEG $markerName ($length bytes):\n";
|
6022
|
-
if ($verbose > 2 and $markerName =~ /^APP/) {
|
6023
|
-
HexDump($segDataPt, undef, %dumpParms);
|
6024
|
-
}
|
6025
|
-
}
|
6020
|
+
print $out "JPEG $markerName ($length bytes)\n" if $verbose;
|
6026
6021
|
# group delete of APP segments
|
6027
6022
|
if ($$delGroup{$dirName}) {
|
6028
6023
|
$verbose and print $out " Deleting $dirName segment\n";
|
@@ -6870,6 +6865,7 @@ sub WriteBinaryData($$$)
|
|
6870
6865
|
|
6871
6866
|
# get default format ('int8u' unless specified)
|
6872
6867
|
my $dataPt = $$dirInfo{DataPt} or return undef;
|
6868
|
+
my $dataLen = length $$dataPt;
|
6873
6869
|
my $defaultFormat = $$tagTablePtr{FORMAT} || 'int8u';
|
6874
6870
|
my $increment = FormatSize($defaultFormat);
|
6875
6871
|
unless ($increment) {
|
@@ -6886,7 +6882,8 @@ sub WriteBinaryData($$$)
|
|
6886
6882
|
delete $$dirInfo{VarFormatData};
|
6887
6883
|
}
|
6888
6884
|
my $dirStart = $$dirInfo{DirStart} || 0;
|
6889
|
-
my $dirLen = $$dirInfo{DirLen}
|
6885
|
+
my $dirLen = $$dirInfo{DirLen};
|
6886
|
+
$dirLen = $dataLen - $dirStart if not defined $dirLen or $dirLen > $dataLen - $dirStart;
|
6890
6887
|
my $newData = substr($$dataPt, $dirStart, $dirLen) or return undef;
|
6891
6888
|
my $dirName = $$dirInfo{DirName};
|
6892
6889
|
my $varSize = 0;
|
@@ -7022,11 +7019,34 @@ sub WriteBinaryData($$$)
|
|
7022
7019
|
$tagInfo = $self->GetTagInfo($tagTablePtr, $tagID, \$v);
|
7023
7020
|
next unless $tagInfo;
|
7024
7021
|
}
|
7025
|
-
|
7026
|
-
my
|
7027
|
-
my $
|
7028
|
-
|
7029
|
-
|
7022
|
+
my $subdir = $$tagInfo{SubDirectory} or next;
|
7023
|
+
my $start = $$subdir{Start};
|
7024
|
+
my $len;
|
7025
|
+
if (not $start) {
|
7026
|
+
$start = $entry;
|
7027
|
+
$len = $dirLen - $start;
|
7028
|
+
} elsif ($start =~ /\$/) {
|
7029
|
+
my $count = 1;
|
7030
|
+
my $format = $$tagInfo{Format} || $defaultFormat;
|
7031
|
+
$format =~ /(.*)\[(.*)\]/ and ($format, $count) = ($1, $2);
|
7032
|
+
my $val = ReadValue($dataPt, $entry, $format, $count, $dirLen - $entry);
|
7033
|
+
# ignore directories with a zero offset (ie. missing Nikon ShotInfo entries)
|
7034
|
+
next unless $val;
|
7035
|
+
my $dirStart = 0;
|
7036
|
+
#### eval Start ($val, $dirStart)
|
7037
|
+
$start = eval($start);
|
7038
|
+
next if $start < $dirStart or $start > $dataLen;
|
7039
|
+
$len = $$subdir{DirLen};
|
7040
|
+
$len = $dataLen - $start unless $len and $len <= $dataLen - $start;
|
7041
|
+
}
|
7042
|
+
my %subdirInfo = (
|
7043
|
+
DataPt => \$newData,
|
7044
|
+
DirStart => $start,
|
7045
|
+
DirLen => $len,
|
7046
|
+
TagInfo => $tagInfo,
|
7047
|
+
);
|
7048
|
+
my $dat = $self->WriteDirectory(\%subdirInfo, GetTagTable($$subdir{TagTable}));
|
7049
|
+
substr($newData, $start, $len) = $dat if defined $dat and length $dat;
|
7030
7050
|
}
|
7031
7051
|
}
|
7032
7052
|
return $newData;
|
data/bin/lib/Image/ExifTool.pm
CHANGED
@@ -29,7 +29,7 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes
|
|
29
29
|
%jpegMarker %specialTags %fileTypeLookup $testLen $exeDir
|
30
30
|
%static_vars);
|
31
31
|
|
32
|
-
$VERSION = '12.
|
32
|
+
$VERSION = '12.57';
|
33
33
|
$RELEASE = '';
|
34
34
|
@ISA = qw(Exporter);
|
35
35
|
%EXPORT_TAGS = (
|
@@ -150,8 +150,8 @@ sub ReadValue($$$;$$$);
|
|
150
150
|
Real::Media Real::Audio Real::Metafile Red RIFF AIFF ASF WTV DICOM FITS MIE
|
151
151
|
JSON HTML XMP::SVG Palm Palm::MOBI Palm::EXTH Torrent EXE EXE::PEVersion
|
152
152
|
EXE::PEString EXE::MachO EXE::PEF EXE::ELF EXE::AR EXE::CHM LNK Font VCard
|
153
|
-
Text VCard::VCalendar RSRC Rawzor ZIP ZIP::GZIP ZIP::RAR RTF
|
154
|
-
FLIR::AFF FLIR::FPF MacOS MacOS::MDItem FlashPix::DocTable
|
153
|
+
Text VCard::VCalendar VCard::VNote RSRC Rawzor ZIP ZIP::GZIP ZIP::RAR RTF
|
154
|
+
OOXML iWork ISO FLIR::AFF FLIR::FPF MacOS MacOS::MDItem FlashPix::DocTable
|
155
155
|
);
|
156
156
|
|
157
157
|
# alphabetical list of current Lang modules
|
@@ -526,6 +526,7 @@ my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
|
|
526
526
|
VCARD=> ['VCard','Virtual Card'],
|
527
527
|
VCF => 'VCARD',
|
528
528
|
VOB => ['MPEG', 'Video Object'],
|
529
|
+
VNT => [['FPX','VCard'], 'Scene7 Vignette or V-Note text file'],
|
529
530
|
VRD => ['VRD', 'Canon VRD Recipe Data'],
|
530
531
|
VSD => ['FPX', 'Microsoft Visio Drawing'],
|
531
532
|
WAV => ['RIFF', 'WAVeform (Windows digital audio)'],
|
@@ -577,6 +578,7 @@ my %fileDescription = (
|
|
577
578
|
'Win32 DLL' => 'Windows 32-bit Dynamic Link Library',
|
578
579
|
'Win64 EXE' => 'Windows 64-bit Executable',
|
579
580
|
'Win64 DLL' => 'Windows 64-bit Dynamic Link Library',
|
581
|
+
VNote => 'V-Note document',
|
580
582
|
);
|
581
583
|
|
582
584
|
# MIME types for applicable file types above
|
@@ -977,7 +979,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
|
|
977
979
|
TAR => '.{257}ustar( )?\0', # (this doesn't catch old-style tar files)
|
978
980
|
TXT => '(\xff\xfe|(\0\0)?\xfe\xff|(\xef\xbb\xbf)?[\x07-\x0d\x20-\x7e\x80-\xfe]*$)',
|
979
981
|
TIFF => '(II|MM)', # don't test magic number (some raw formats are different)
|
980
|
-
VCard=> '(?i)BEGIN:(VCARD|VCALENDAR)\r\n',
|
982
|
+
VCard=> '(?i)BEGIN:(VCARD|VCALENDAR|VNOTE)\r\n',
|
981
983
|
VRD => 'CANON OPTIONAL DATA\0',
|
982
984
|
WMF => '(\xd7\xcd\xc6\x9a\0\0|\x01\0\x09\0\0\x03)',
|
983
985
|
WTV => '\xb7\xd8\x00\x20\x37\x49\xda\x11\xa6\x4e\x00\x07\xe9\x5e\xad\x8d',
|
@@ -2041,6 +2043,7 @@ sub new
|
|
2041
2043
|
$$self{DEL_GROUP} = { }; # lookup for groups to delete when writing
|
2042
2044
|
$$self{SAVE_COUNT} = 0; # count calls to SaveNewValues()
|
2043
2045
|
$$self{FILE_SEQUENCE} = 0; # sequence number for files when reading
|
2046
|
+
$$self{FILES_WRITTEN} = 0; # count of files successfully written
|
2044
2047
|
$$self{INDENT2} = ''; # indentation of verbose messages from SetNewValue
|
2045
2048
|
|
2046
2049
|
# initialize our new groups for writing
|
@@ -6871,7 +6874,7 @@ sub ProcessJPEG($$)
|
|
6871
6874
|
$self->Warn("Ignored APP1 segment length $length (unknown header)");
|
6872
6875
|
}
|
6873
6876
|
}
|
6874
|
-
} elsif ($marker == 0xe2) { # APP2 (ICC Profile, FPXR, MPF, PreviewImage)
|
6877
|
+
} elsif ($marker == 0xe2) { # APP2 (ICC Profile, FPXR, MPF, InfiRay, PreviewImage)
|
6875
6878
|
if ($$segDataPt =~ /^ICC_PROFILE\0/ and $length >= 14) {
|
6876
6879
|
$dumpType = 'ICC_Profile';
|
6877
6880
|
# must concatenate profile chunks (note: handle the case where
|
@@ -6933,6 +6936,12 @@ sub ProcessJPEG($$)
|
|
6933
6936
|
# extract the MPF information (it is in standard TIFF format)
|
6934
6937
|
my $tagTablePtr = GetTagTable('Image::ExifTool::MPF::Main');
|
6935
6938
|
$self->ProcessTIFF(\%dirInfo, $tagTablePtr);
|
6939
|
+
} elsif ($$segDataPt =~ /^....IJPEG\0/s) {
|
6940
|
+
$dumpType = 'InfiRay Version';
|
6941
|
+
$$self{HasIJPEG} = 1;
|
6942
|
+
SetByteOrder('II');
|
6943
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::InfiRay::Version');
|
6944
|
+
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
6936
6945
|
} elsif ($$segDataPt =~ /^(|QVGA\0|BGTH)\xff\xd8\xff[\xdb\xe0\xe1]/) {
|
6937
6946
|
# Samsung/GE/GoPro="", BenQ DC C1220/Pentacon/Polaroid="QVGA\0",
|
6938
6947
|
# Digilife DDC-690/Rollei="BGTH"
|
@@ -6973,8 +6982,8 @@ sub ProcessJPEG($$)
|
|
6973
6982
|
SetByteOrder('MM');
|
6974
6983
|
my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::JPS');
|
6975
6984
|
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
6976
|
-
} elsif ($$self{Make} eq 'DJI') {
|
6977
|
-
$dumpType = 'DJI ThermalData';
|
6985
|
+
} elsif ($$self{HasIJPEG} or $$self{Make} eq 'DJI') {
|
6986
|
+
$dumpType = $$self{HasIJPEG} ? 'InfiRay ImagingData' : 'DJI ThermalData';
|
6978
6987
|
# add this data to the combined data if it exists
|
6979
6988
|
my $dataPt = $segDataPt;
|
6980
6989
|
if (defined $combinedSegData) {
|
@@ -6984,11 +6993,14 @@ sub ProcessJPEG($$)
|
|
6984
6993
|
if ($nextMarker == $marker) {
|
6985
6994
|
$combinedSegData = $$segDataPt unless defined $combinedSegData;
|
6986
6995
|
} else {
|
6987
|
-
# process DJI
|
6996
|
+
# process InfiRay/DJI thermal data
|
6988
6997
|
my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::Main');
|
6989
6998
|
$self->HandleTag($tagTablePtr, 'APP3', $$dataPt);
|
6990
6999
|
undef $combinedSegData;
|
6991
7000
|
}
|
7001
|
+
} elsif ($$self{HasIJPEG}) {
|
7002
|
+
$dumpType = 'InfiRay Data',
|
7003
|
+
|
6992
7004
|
} elsif ($$segDataPt =~ /^\xff\xd8\xff\xdb/) {
|
6993
7005
|
$dumpType = 'PreviewImage'; # (Samsung, HP, BenQ)
|
6994
7006
|
$preview = $$segDataPt;
|
@@ -6997,7 +7009,7 @@ sub ProcessJPEG($$)
|
|
6997
7009
|
$self->FoundTag('PreviewImage', $preview);
|
6998
7010
|
undef $preview;
|
6999
7011
|
}
|
7000
|
-
} elsif ($marker == 0xe4) { # APP4 ("SCALADO", FPXR, PreviewImage)
|
7012
|
+
} elsif ($marker == 0xe4) { # APP4 (InfiRay, "SCALADO", FPXR, PreviewImage)
|
7001
7013
|
if ($$segDataPt =~ /^SCALADO\0/ and $length >= 16) {
|
7002
7014
|
$dumpType = 'SCALADO';
|
7003
7015
|
my ($num, $idx, $len) = unpack('x8n2N', $$segDataPt);
|
@@ -7028,6 +7040,11 @@ sub ProcessJPEG($$)
|
|
7028
7040
|
DirStart(\%dirInfo, 0, 0);
|
7029
7041
|
my $tagTablePtr = GetTagTable('Image::ExifTool::DJI::ThermalParams');
|
7030
7042
|
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
7043
|
+
} elsif ($$self{HasIJPEG} and $length >= 120) {
|
7044
|
+
$dumpType = 'InfiRay Factory';
|
7045
|
+
SetByteOrder('II');
|
7046
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::InfiRay::Factory');
|
7047
|
+
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
7031
7048
|
} elsif ($preview) {
|
7032
7049
|
# continued Samsung S1060 preview from APP3
|
7033
7050
|
$dumpType = 'PreviewImage';
|
@@ -7039,7 +7056,7 @@ sub ProcessJPEG($$)
|
|
7039
7056
|
$self->FoundTag('PreviewImage', $preview);
|
7040
7057
|
undef $preview;
|
7041
7058
|
}
|
7042
|
-
} elsif ($marker == 0xe5) { # APP5 (Ricoh "RMETA")
|
7059
|
+
} elsif ($marker == 0xe5) { # APP5 (InfiRay, Ricoh "RMETA")
|
7043
7060
|
if ($$segDataPt =~ /^RMETA\0/) {
|
7044
7061
|
# (NOTE: apparently these may span multiple segments, but I haven't seen
|
7045
7062
|
# a sample like this, so multi-segment support hasn't yet been implemented)
|
@@ -7054,13 +7071,18 @@ sub ProcessJPEG($$)
|
|
7054
7071
|
$dumpType = 'DJI ThermalCal';
|
7055
7072
|
my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::Main');
|
7056
7073
|
$self->HandleTag($tagTablePtr, 'APP5', $$segDataPt);
|
7074
|
+
} elsif ($$self{HasIJPEG} and $length >= 38) {
|
7075
|
+
$dumpType = 'InfiRay Picture';
|
7076
|
+
SetByteOrder('II');
|
7077
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::InfiRay::Picture');
|
7078
|
+
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
7057
7079
|
} elsif ($preview) {
|
7058
7080
|
$dumpType = 'PreviewImage';
|
7059
7081
|
$preview .= $$segDataPt;
|
7060
7082
|
$self->FoundTag('PreviewImage', $preview);
|
7061
7083
|
undef $preview;
|
7062
7084
|
}
|
7063
|
-
} elsif ($marker == 0xe6) { # APP6 (Toshiba EPPIM, NITF, HP_TDHD)
|
7085
|
+
} elsif ($marker == 0xe6) { # APP6 (InfiRay, Toshiba EPPIM, NITF, HP_TDHD)
|
7064
7086
|
if ($$segDataPt =~ /^EPPIM\0/) {
|
7065
7087
|
undef $dumpType; # (will be dumped here)
|
7066
7088
|
DirStart(\%dirInfo, 6, 6);
|
@@ -7093,8 +7115,13 @@ sub ProcessJPEG($$)
|
|
7093
7115
|
$dumpType = 'DJI_DTAT';
|
7094
7116
|
my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::Main');
|
7095
7117
|
$self->HandleTag($tagTablePtr, 'APP6', $$segDataPt);
|
7118
|
+
} elsif ($$self{HasIJPEG} and $length >= 129) {
|
7119
|
+
$dumpType = 'InfiRay MixMode';
|
7120
|
+
SetByteOrder('II');
|
7121
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::InfiRay::MixMode');
|
7122
|
+
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
7096
7123
|
}
|
7097
|
-
} elsif ($marker == 0xe7) { # APP7 (Pentax, Huawei, Qualcomm)
|
7124
|
+
} elsif ($marker == 0xe7) { # APP7 (InfiRay, Pentax, Huawei, Qualcomm)
|
7098
7125
|
if ($$segDataPt =~ /^PENTAX \0(II|MM)/) {
|
7099
7126
|
# found in K-3 images (is this multi-segment??)
|
7100
7127
|
SetByteOrder($1);
|
@@ -7133,16 +7160,26 @@ sub ProcessJPEG($$)
|
|
7133
7160
|
DirStart(\%dirInfo, 27);
|
7134
7161
|
$dirInfo{DirName} = 'Qualcomm';
|
7135
7162
|
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
7163
|
+
} elsif ($$self{HasIJPEG} and $length >= 32) {
|
7164
|
+
$dumpType = 'InfiRay OpMode';
|
7165
|
+
SetByteOrder('II');
|
7166
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::InfiRay::OpMode');
|
7167
|
+
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
7136
7168
|
}
|
7137
|
-
} elsif ($marker == 0xe8) { # APP8 (SPIFF)
|
7169
|
+
} elsif ($marker == 0xe8) { # APP8 (InfiRay, SPIFF)
|
7138
7170
|
# my sample SPIFF has 32 bytes of data, but spec states 30
|
7139
7171
|
if ($$segDataPt =~ /^SPIFF\0/ and $length == 32) {
|
7140
7172
|
$dumpType = 'SPIFF';
|
7141
7173
|
DirStart(\%dirInfo, 6);
|
7142
7174
|
my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::SPIFF');
|
7143
7175
|
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
7176
|
+
} elsif ($$self{HasIJPEG} and $length >= 32) {
|
7177
|
+
$dumpType = 'InfiRay Isothermal';
|
7178
|
+
SetByteOrder('II');
|
7179
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::InfiRay::Isothermal');
|
7180
|
+
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
7144
7181
|
}
|
7145
|
-
} elsif ($marker == 0xe9) { # APP9 (Media Jukebox)
|
7182
|
+
} elsif ($marker == 0xe9) { # APP9 (InfiRay, Media Jukebox)
|
7146
7183
|
if ($$segDataPt =~ /^Media Jukebox\0/ and $length > 22) {
|
7147
7184
|
$dumpType = 'MediaJukebox';
|
7148
7185
|
# (start parsing after the "<MJMD>")
|
@@ -7151,6 +7188,11 @@ sub ProcessJPEG($$)
|
|
7151
7188
|
require Image::ExifTool::XMP;
|
7152
7189
|
my $tagTablePtr = GetTagTable('Image::ExifTool::JPEG::MediaJukebox');
|
7153
7190
|
$self->ProcessDirectory(\%dirInfo, $tagTablePtr, \&Image::ExifTool::XMP::ProcessXMP);
|
7191
|
+
} elsif ($$self{HasIJPEG} and $length >= 768) {
|
7192
|
+
$dumpType = 'InfiRay Sensor';
|
7193
|
+
SetByteOrder('II');
|
7194
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::InfiRay::Sensor');
|
7195
|
+
$self->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
7154
7196
|
}
|
7155
7197
|
} elsif ($marker == 0xea) { # APP10 (PhotoStudio Unicode comments)
|
7156
7198
|
if ($$segDataPt =~ /^UNICODE\0/) {
|
@@ -7947,7 +7989,7 @@ sub ProcessDirectory($$$;$)
|
|
7947
7989
|
# patch for bug in Windows phone 7.5 O/S that writes incorrect InteropIFD pointer
|
7948
7990
|
return 0 unless $dirName eq 'GPS' and $$self{PROCESSED}{$addr} eq 'InteropIFD';
|
7949
7991
|
}
|
7950
|
-
$$self{PROCESSED}{$addr} = $dirName;
|
7992
|
+
$$self{PROCESSED}{$addr} = $dirName unless $$tagTablePtr{VARS} and $$tagTablePtr{VARS}{ALLOW_REPROCESS};
|
7951
7993
|
}
|
7952
7994
|
my $oldOrder = GetByteOrder();
|
7953
7995
|
my @save = @$self{'INDENT','DIR_NAME','Compression','SubfileType'};
|
@@ -8708,13 +8750,16 @@ sub ProcessBinaryData($$$)
|
|
8708
8750
|
{
|
8709
8751
|
my ($self, $dirInfo, $tagTablePtr) = @_;
|
8710
8752
|
my $dataPt = $$dirInfo{DataPt};
|
8711
|
-
my $
|
8712
|
-
my $
|
8753
|
+
my $dataLen = length $$dataPt;
|
8754
|
+
my $dirStart = $$dirInfo{DirStart} || 0;
|
8755
|
+
my $maxLen = $dataLen - $dirStart;
|
8756
|
+
my $size = $$dirInfo{DirLen};
|
8713
8757
|
my $base = $$dirInfo{Base} || 0;
|
8714
8758
|
my $verbose = $$self{OPTIONS}{Verbose};
|
8715
8759
|
my $unknown = $$self{OPTIONS}{Unknown};
|
8716
8760
|
my $dataPos = $$dirInfo{DataPos} || 0;
|
8717
8761
|
|
8762
|
+
$size = $maxLen if not defined $size or $size > $maxLen;
|
8718
8763
|
# get default format ('int8u' unless specified)
|
8719
8764
|
my $defaultFormat = $$tagTablePtr{FORMAT} || 'int8u';
|
8720
8765
|
my $increment = $formatSize{$defaultFormat};
|
@@ -8756,6 +8801,7 @@ sub ProcessBinaryData($$$)
|
|
8756
8801
|
$tagInfo = $self->GetTagInfo($tagTablePtr, $index);
|
8757
8802
|
unless ($tagInfo) {
|
8758
8803
|
next unless defined $tagInfo;
|
8804
|
+
# $entry = offset of value relative to directory start (or end if negative)
|
8759
8805
|
my $entry = int($index) * $increment + $varSize;
|
8760
8806
|
if ($entry < 0) {
|
8761
8807
|
$entry += $size;
|
@@ -8764,7 +8810,7 @@ sub ProcessBinaryData($$$)
|
|
8764
8810
|
next if $entry >= $size;
|
8765
8811
|
my $more = $size - $entry;
|
8766
8812
|
$more = 128 if $more > 128;
|
8767
|
-
my $v = substr($$dataPt, $entry+$
|
8813
|
+
my $v = substr($$dataPt, $entry+$dirStart, $more);
|
8768
8814
|
$tagInfo = $self->GetTagInfo($tagTablePtr, $index, \$v);
|
8769
8815
|
next unless $tagInfo;
|
8770
8816
|
}
|
@@ -8797,7 +8843,7 @@ sub ProcessBinaryData($$$)
|
|
8797
8843
|
$count = $more;
|
8798
8844
|
} elsif ($format eq 'pstring') {
|
8799
8845
|
$format = 'string';
|
8800
|
-
$count = Get8u($dataPt, ($entry++)+$
|
8846
|
+
$count = Get8u($dataPt, ($entry++)+$dirStart);
|
8801
8847
|
--$more;
|
8802
8848
|
} elsif (not $formatSize{$format}) {
|
8803
8849
|
if ($format =~ /(.*)\[(.*)\]/) {
|
@@ -8826,17 +8872,17 @@ sub ProcessBinaryData($$$)
|
|
8826
8872
|
} elsif ($format =~ /^var_/) {
|
8827
8873
|
# handle variable-length string formats
|
8828
8874
|
$format = substr($format, 4);
|
8829
|
-
pos($$dataPt) = $entry + $
|
8875
|
+
pos($$dataPt) = $entry + $dirStart;
|
8830
8876
|
undef $count;
|
8831
8877
|
if ($format eq 'ustring') {
|
8832
|
-
$count = pos($$dataPt) - ($entry+$
|
8878
|
+
$count = pos($$dataPt) - ($entry+$dirStart) if $$dataPt =~ /\G(..)*?\0\0/sg;
|
8833
8879
|
$varSize -= 2; # ($count includes base size of 2 bytes)
|
8834
8880
|
} elsif ($format eq 'pstring') {
|
8835
|
-
$count = Get8u($dataPt, ($entry++)+$
|
8881
|
+
$count = Get8u($dataPt, ($entry++)+$dirStart);
|
8836
8882
|
--$more;
|
8837
8883
|
} elsif ($format eq 'pstr32' or $format eq 'ustr32') {
|
8838
8884
|
last if $more < 4;
|
8839
|
-
$count = Get32u($dataPt, $entry + $
|
8885
|
+
$count = Get32u($dataPt, $entry + $dirStart);
|
8840
8886
|
$count *= 2 if $format eq 'ustr32';
|
8841
8887
|
$entry += 4;
|
8842
8888
|
$more -= 4;
|
@@ -8844,22 +8890,22 @@ sub ProcessBinaryData($$$)
|
|
8844
8890
|
} elsif ($format eq 'int16u') {
|
8845
8891
|
# int16u size of binary data to follow
|
8846
8892
|
last if $more < 2;
|
8847
|
-
$count = Get16u($dataPt, $entry + $
|
8893
|
+
$count = Get16u($dataPt, $entry + $dirStart) + 2;
|
8848
8894
|
$varSize -= 2; # ($count includes size word)
|
8849
8895
|
$format = 'undef';
|
8850
8896
|
} elsif ($format eq 'ue7') {
|
8851
8897
|
require Image::ExifTool::BPG;
|
8852
|
-
($val, $count) = Image::ExifTool::BPG::Get_ue7($dataPt, $entry + $
|
8898
|
+
($val, $count) = Image::ExifTool::BPG::Get_ue7($dataPt, $entry + $dirStart);
|
8853
8899
|
last unless defined $val;
|
8854
8900
|
--$varSize; # ($count includes base size of 1 byte)
|
8855
8901
|
} elsif ($$dataPt =~ /\0/g) {
|
8856
|
-
$count = pos($$dataPt) - ($entry+$
|
8902
|
+
$count = pos($$dataPt) - ($entry+$dirStart);
|
8857
8903
|
--$varSize; # ($count includes base size of 1 byte)
|
8858
8904
|
}
|
8859
8905
|
$count = $more if not defined $count or $count > $more;
|
8860
8906
|
$varSize += $count; # shift subsequent indices
|
8861
8907
|
unless (defined $val) {
|
8862
|
-
$val = substr($$dataPt, $entry+$
|
8908
|
+
$val = substr($$dataPt, $entry+$dirStart, $count);
|
8863
8909
|
$val = $self->Decode($val, 'UCS2') if $format eq 'ustring' or $format eq 'ustr32';
|
8864
8910
|
$val =~ s/\0.*//s unless $format eq 'undef'; # truncate at null
|
8865
8911
|
}
|
@@ -8873,7 +8919,7 @@ sub ProcessBinaryData($$$)
|
|
8873
8919
|
# hook to allow format, etc to be set dynamically
|
8874
8920
|
if (defined $$tagInfo{Hook}) {
|
8875
8921
|
my $oldVarSize = $varSize;
|
8876
|
-
my $pos = $entry + $
|
8922
|
+
my $pos = $entry + $dirStart;
|
8877
8923
|
#### eval Hook ($format, $varSize, $size, $dataPt, $pos)
|
8878
8924
|
eval $$tagInfo{Hook};
|
8879
8925
|
# save variable size data if required for writing (in case changed by Hook)
|
@@ -8898,7 +8944,7 @@ sub ProcessBinaryData($$$)
|
|
8898
8944
|
next if $$tagInfo{LargeTag} and $$self{EXCL_TAG_LOOKUP}{lc $$tagInfo{Name}};
|
8899
8945
|
# read value now if necessary
|
8900
8946
|
unless (defined $val and not $$tagInfo{SubDirectory}) {
|
8901
|
-
$val = ReadValue($dataPt, $entry+$
|
8947
|
+
$val = ReadValue($dataPt, $entry+$dirStart, $format, $count, $more, \$rational);
|
8902
8948
|
next unless defined $val;
|
8903
8949
|
$mask = $$tagInfo{Mask};
|
8904
8950
|
$val = ($val & $mask) >> $$tagInfo{BitShift} if $mask;
|
@@ -8915,8 +8961,8 @@ sub ProcessBinaryData($$$)
|
|
8915
8961
|
Value => $val,
|
8916
8962
|
DataPt => $dataPt,
|
8917
8963
|
Size => $len,
|
8918
|
-
Start => $entry+$
|
8919
|
-
Addr => $entry+$
|
8964
|
+
Start => $entry+$dirStart,
|
8965
|
+
Addr => $entry+$dirStart+$base+$dataPos,
|
8920
8966
|
Format => $format,
|
8921
8967
|
Count => $count,
|
8922
8968
|
Extra => $mask ? sprintf(', mask 0x%.2x',$mask) : undef,
|
@@ -8942,16 +8988,27 @@ sub ProcessBinaryData($$$)
|
|
8942
8988
|
my $subdirBase = $base;
|
8943
8989
|
if (defined $$subdir{Base}) {
|
8944
8990
|
#### eval Base ($start,$base)
|
8945
|
-
my $start = $entry + $
|
8991
|
+
my $start = $entry + $dirStart + $dataPos;
|
8946
8992
|
$subdirBase = eval($$subdir{Base}) + $base;
|
8947
8993
|
}
|
8948
8994
|
my $start = $$subdir{Start} || 0;
|
8995
|
+
if ($start =~ /\$/) {
|
8996
|
+
# ignore directories with a zero offset (ie. missing Nikon ShotInfo entries)
|
8997
|
+
next unless $val;
|
8998
|
+
#### eval Start ($val, $dirStart)
|
8999
|
+
$start = eval($start);
|
9000
|
+
next if $start < $dirStart or $start > $dataLen;
|
9001
|
+
$len = $$subdir{DirLen};
|
9002
|
+
$len = $dataLen - $start unless $len and $len <= $dataLen - $start;
|
9003
|
+
} else {
|
9004
|
+
$start += $dirStart + $entry;
|
9005
|
+
}
|
8949
9006
|
my %subdirInfo = (
|
8950
9007
|
DataPt => $dataPt,
|
8951
9008
|
DataPos => $dataPos,
|
8952
|
-
DataLen =>
|
8953
|
-
DirStart => $
|
8954
|
-
DirLen => $len
|
9009
|
+
DataLen => $dataLen,
|
9010
|
+
DirStart => $start,
|
9011
|
+
DirLen => $len,
|
8955
9012
|
Base => $subdirBase,
|
8956
9013
|
);
|
8957
9014
|
delete $$self{NO_UNKNOWN};
|