exiftool_vendored 12.32.0 → 12.36.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 +77 -3
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/exiftool +57 -39
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +7 -2
- data/bin/lib/Image/ExifTool/CBOR.pm +85 -31
- data/bin/lib/Image/ExifTool/Canon.pm +28 -3
- data/bin/lib/Image/ExifTool/Charset.pm +2 -0
- data/bin/lib/Image/ExifTool/Exif.pm +109 -3
- data/bin/lib/Image/ExifTool/FLIR.pm +33 -8
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +96 -4
- data/bin/lib/Image/ExifTool/JSON.pm +4 -2
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +111 -12
- data/bin/lib/Image/ExifTool/MacOS.pm +2 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +637 -16
- data/bin/lib/Image/ExifTool/NikonCustom.pm +5 -1
- data/bin/lib/Image/ExifTool/NikonSettings.pm +67 -11
- data/bin/lib/Image/ExifTool/Olympus.pm +5 -1
- data/bin/lib/Image/ExifTool/PDF.pm +5 -3
- data/bin/lib/Image/ExifTool/QuickTime.pm +21 -2
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +2 -2
- data/bin/lib/Image/ExifTool/README +6 -2
- data/bin/lib/Image/ExifTool/Sony.pm +31 -11
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +9 -4
- data/bin/lib/Image/ExifTool/TagLookup.pm +5054 -4455
- data/bin/lib/Image/ExifTool/TagNames.pod +1185 -23
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +10 -0
- data/bin/lib/Image/ExifTool/Writer.pl +45 -3
- data/bin/lib/Image/ExifTool/XMP.pm +111 -25
- data/bin/lib/Image/ExifTool/XMP2.pl +3 -1
- data/bin/lib/Image/ExifTool.pm +83 -19
- data/bin/lib/Image/ExifTool.pod +9 -1
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +2 -2
@@ -1067,6 +1067,9 @@ sub WriteQuickTime($$$)
|
|
1067
1067
|
# 3=optional base offset, 4=optional item ID)
|
1068
1068
|
ChunkOffset => \@chunkOffset,
|
1069
1069
|
);
|
1070
|
+
# set InPlace flag so XMP will be padded properly when
|
1071
|
+
# QuickTimePad is used if this is an XMP directory
|
1072
|
+
$subdirInfo{InPlace} = 2 if $et->Options('QuickTimePad');
|
1070
1073
|
# pass the header pointer if necessary (for EXIF IFD's
|
1071
1074
|
# where the Base offset is at the end of the header)
|
1072
1075
|
if ($hdrLen and $hdrLen < $size) {
|
@@ -1331,6 +1334,13 @@ sub WriteQuickTime($$$)
|
|
1331
1334
|
}
|
1332
1335
|
# write the new atom if it was modified
|
1333
1336
|
if (defined $newData) {
|
1337
|
+
my $sizeDiff = length($buff) - length($newData);
|
1338
|
+
if ($sizeDiff > 0 and $$tagInfo{PreservePadding} and $et->Options('QuickTimePad')) {
|
1339
|
+
$newData .= "\0" x $sizeDiff;
|
1340
|
+
$et->VPrint(1, " ($$tagInfo{Name} padded to original size)");
|
1341
|
+
} elsif ($sizeDiff) {
|
1342
|
+
$et->VPrint(1, " ($$tagInfo{Name} changed size)");
|
1343
|
+
}
|
1334
1344
|
my $len = length($newData) + 8;
|
1335
1345
|
$len > 0x7fffffff and $et->Error("$$tagInfo{Name} to large to write"), last;
|
1336
1346
|
# update size in ChunkOffset list for modified 'uuid' atom
|
@@ -154,7 +154,7 @@ my %delMore = (
|
|
154
154
|
);
|
155
155
|
|
156
156
|
# family 0 groups where directories should never be deleted
|
157
|
-
my %permanentDir = ( QuickTime => 1 );
|
157
|
+
my %permanentDir = ( QuickTime => 1, Jpeg2000 => 1 );
|
158
158
|
|
159
159
|
# lookup for all valid family 2 groups (lower case)
|
160
160
|
my %family2groups = map { lc $_ => 1 } @delGroup2, 'Unknown';
|
@@ -2074,6 +2074,46 @@ sub SetSystemTags($$)
|
|
2074
2074
|
last;
|
2075
2075
|
}
|
2076
2076
|
}
|
2077
|
+
# delete Windows Zone.Identifier if specified
|
2078
|
+
my $zhash = $self->GetNewValueHash($Image::ExifTool::Extra{ZoneIdentifier});
|
2079
|
+
if ($zhash) {
|
2080
|
+
my $res = -1;
|
2081
|
+
if ($^O ne 'MSWin32') {
|
2082
|
+
$self->Warn('ZoneIdentifer is a Windows-only tag');
|
2083
|
+
} elsif (ref $file) {
|
2084
|
+
$self->Warn('Writing ZoneIdentifer requires a file name');
|
2085
|
+
} elsif (defined $self->GetNewValue('ZoneIdentifier', \$zhash)) {
|
2086
|
+
$self->Warn('ZoneIndentifier may only be delted');
|
2087
|
+
} elsif (not eval { require Win32API::File }) {
|
2088
|
+
$self->Warn('Install Win32API::File to write ZoneIdentifier');
|
2089
|
+
} else {
|
2090
|
+
my ($wattr, $wide);
|
2091
|
+
my $zfile = "${file}:Zone.Identifier";
|
2092
|
+
if ($self->EncodeFileName($zfile)) {
|
2093
|
+
$wide = 1;
|
2094
|
+
$wattr = eval { Win32API::File::GetFileAttributesW($zfile) };
|
2095
|
+
} else {
|
2096
|
+
$wattr = eval { Win32API::File::GetFileAttributes($zfile) };
|
2097
|
+
}
|
2098
|
+
if ($wattr == Win32API::File::INVALID_FILE_ATTRIBUTES()) {
|
2099
|
+
$res = 0; # file doesn't exist, nothing to do
|
2100
|
+
} elsif ($wattr & Win32API::File::FILE_ATTRIBUTE_READONLY()) {
|
2101
|
+
$self->Warn('Zone.Identifier stream is read-only');
|
2102
|
+
} else {
|
2103
|
+
if ($wide) {
|
2104
|
+
$res = 1 if eval { Win32API::File::DeleteFileW($zfile) };
|
2105
|
+
} else {
|
2106
|
+
$res = 1 if eval { Win32API::File::DeleteFile($zfile) };
|
2107
|
+
}
|
2108
|
+
if ($res > 0) {
|
2109
|
+
$self->VPrint(0, " Deleting Zone.Identifier stream\n");
|
2110
|
+
} else {
|
2111
|
+
$self->Warn('Error deleting Zone.Identifier stream');
|
2112
|
+
}
|
2113
|
+
}
|
2114
|
+
}
|
2115
|
+
$result = $res if $res == 1 or not $result;
|
2116
|
+
}
|
2077
2117
|
return $result;
|
2078
2118
|
}
|
2079
2119
|
|
@@ -4758,6 +4798,8 @@ sub InverseDateTime($$;$$)
|
|
4758
4798
|
$strptimeLib = '';
|
4759
4799
|
}
|
4760
4800
|
}
|
4801
|
+
# handle factional seconds (%f), but only at the end of the string
|
4802
|
+
my $fs = ($fmt =~ s/%f$// and $val =~ s/(\.\d+)\s*$//) ? $1 : '';
|
4761
4803
|
my ($lib, $wrn, @a);
|
4762
4804
|
TryLib: for ($lib=$strptimeLib; ; $lib='') {
|
4763
4805
|
if (not $lib) {
|
@@ -4794,10 +4836,10 @@ TryLib: for ($lib=$strptimeLib; ; $lib='') {
|
|
4794
4836
|
next TryLib;
|
4795
4837
|
}
|
4796
4838
|
} elsif (length($a[$i]) < 2) {
|
4797
|
-
|
4839
|
+
$a[$i] = "0$a[$i]"; # pad to 2 digits if necessary
|
4798
4840
|
}
|
4799
4841
|
}
|
4800
|
-
$val = join(':', @a[5,4,3]) . ' ' . join(':', @a[2,1,0]);
|
4842
|
+
$val = join(':', @a[5,4,3]) . ' ' . join(':', @a[2,1,0]) . $fs;
|
4801
4843
|
last;
|
4802
4844
|
}
|
4803
4845
|
}
|
@@ -50,7 +50,7 @@ use Image::ExifTool::Exif;
|
|
50
50
|
use Image::ExifTool::GPS;
|
51
51
|
require Exporter;
|
52
52
|
|
53
|
-
$VERSION = '3.
|
53
|
+
$VERSION = '3.48';
|
54
54
|
@ISA = qw(Exporter);
|
55
55
|
@EXPORT_OK = qw(EscapeXML UnescapeXML);
|
56
56
|
|
@@ -436,9 +436,37 @@ my %sOECF = (
|
|
436
436
|
Names => { List => 'Seq' },
|
437
437
|
Values => { List => 'Seq', Writable => 'rational' },
|
438
438
|
);
|
439
|
-
|
439
|
+
my %sAreaModels = (
|
440
|
+
STRUCT_NAME => 'AreaModels',
|
441
|
+
NAMESPACE => 'crs',
|
442
|
+
ColorRangeMaskAreaSampleInfo => { },
|
443
|
+
AreaComponents => { List => 'Seq' },
|
444
|
+
);
|
445
|
+
my %sCorrectionRangeMask = (
|
446
|
+
STRUCT_NAME => 'CorrectionRangeMask',
|
447
|
+
NAMESPACE => 'crs',
|
448
|
+
Version => { },
|
449
|
+
Type => { },
|
450
|
+
ColorAmount => { Writable => 'real' },
|
451
|
+
LumMin => { Writable => 'real' },
|
452
|
+
LumMax => { Writable => 'real' },
|
453
|
+
LumFeather => { Writable => 'real' },
|
454
|
+
DepthMin => { Writable => 'real' },
|
455
|
+
DepthMax => { Writable => 'real' },
|
456
|
+
DepthFeather=> { Writable => 'real' },
|
457
|
+
# new in LR 11.0
|
458
|
+
Invert => { Writable => 'boolean' },
|
459
|
+
SampleType => { Writable => 'integer' },
|
460
|
+
AreaModels => {
|
461
|
+
List => 'Seq',
|
462
|
+
Struct => \%sAreaModels,
|
463
|
+
},
|
464
|
+
LumRange => { },
|
465
|
+
LuminanceDepthSampleInfo => { },
|
466
|
+
);
|
440
467
|
# new LR2 crs structures (PH)
|
441
|
-
my %sCorrectionMask
|
468
|
+
my %sCorrectionMask;
|
469
|
+
%sCorrectionMask = (
|
442
470
|
STRUCT_NAME => 'CorrectionMask',
|
443
471
|
NAMESPACE => 'crs',
|
444
472
|
# disable List behaviour of flattened Gradient/PaintBasedCorrections
|
@@ -473,19 +501,21 @@ my %sCorrectionMask = (
|
|
473
501
|
Alpha => { Writable => 'real', List => 0 },
|
474
502
|
CenterValue => { Writable => 'real', List => 0 },
|
475
503
|
PerimeterValue=>{ Writable => 'real', List => 0 },
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
504
|
+
# new in LR 11.0 MaskGroupBasedCorrections
|
505
|
+
MaskActive => { Writable => 'boolean', List => 0 },
|
506
|
+
MaskName => { List => 0 },
|
507
|
+
MaskBlendMode=> { Writable => 'integer', List => 0 },
|
508
|
+
MaskInverted => { Writable => 'boolean', List => 0 },
|
509
|
+
MaskSyncID => { List => 0 },
|
510
|
+
MaskVersion => { List => 0 },
|
511
|
+
MaskSubType => { List => 0 },
|
512
|
+
ReferencePoint => { List => 0 },
|
513
|
+
InputDigest => { List => 0 },
|
514
|
+
MaskDigest => { List => 0 },
|
515
|
+
WholeImageArea => { List => 0 },
|
516
|
+
Origin => { List => 0 },
|
517
|
+
Masks => { Struct => \%sCorrectionMask, NoSubStruct => 1 },
|
518
|
+
CorrectionRangeMask => { Struct => \%sCorrectionRangeMask },
|
489
519
|
);
|
490
520
|
my %sCorrection = (
|
491
521
|
STRUCT_NAME => 'Correction',
|
@@ -516,6 +546,7 @@ my %sCorrection = (
|
|
516
546
|
LocalBlacks2012 => { FlatName => 'Blacks2012', Writable => 'real', List => 0 },
|
517
547
|
LocalDehaze => { FlatName => 'Dehaze', Writable => 'real', List => 0 },
|
518
548
|
LocalTexture => { FlatName => 'Texture', Writable => 'real', List => 0 },
|
549
|
+
# new in LR 11.0
|
519
550
|
CorrectionRangeMask => {
|
520
551
|
FlatName => 'RangeMask',
|
521
552
|
Struct => \%sCorrectionRangeMask,
|
@@ -525,6 +556,8 @@ my %sCorrection = (
|
|
525
556
|
Struct => \%sCorrectionMask,
|
526
557
|
List => 'Seq',
|
527
558
|
},
|
559
|
+
CorrectionName => { },
|
560
|
+
CorrectionSyncID => { },
|
528
561
|
);
|
529
562
|
my %sRetouchArea = (
|
530
563
|
STRUCT_NAME => 'RetouchArea',
|
@@ -543,6 +576,30 @@ my %sRetouchArea = (
|
|
543
576
|
List => 'Seq',
|
544
577
|
},
|
545
578
|
);
|
579
|
+
my %sMapInfo = (
|
580
|
+
STRUCT_NAME => 'MapInfo',
|
581
|
+
NAMESPACE => 'crs',
|
582
|
+
NOTES => q{
|
583
|
+
Called RangeMaskMapInfo by the specification, the same as the containing
|
584
|
+
structure.
|
585
|
+
},
|
586
|
+
RGBMin => { },
|
587
|
+
RGBMax => { },
|
588
|
+
LabMin => { },
|
589
|
+
LabMax => { },
|
590
|
+
LumEq => { List => 'Seq' },
|
591
|
+
);
|
592
|
+
my %sRangeMask = (
|
593
|
+
STRUCT_NAME => 'RangeMask',
|
594
|
+
NAMESPACE => 'crs',
|
595
|
+
NOTES => q{
|
596
|
+
This structure is actually called RangeMaskMapInfo, but it only contains one
|
597
|
+
element which is a RangeMaskMapInfo structure (Yes, really!). So these are
|
598
|
+
renamed to RangeMask and MapInfo respectively to avoid confusion and
|
599
|
+
redundancy in the tag names.
|
600
|
+
},
|
601
|
+
RangeMaskMapInfo => { FlatName => 'MapInfo', Struct => \%sMapInfo },
|
602
|
+
);
|
546
603
|
|
547
604
|
# main XMP tag table (tag ID's are used for the family 1 group names)
|
548
605
|
%Image::ExifTool::XMP::Main = (
|
@@ -1533,6 +1590,9 @@ my %sPantryItem = (
|
|
1533
1590
|
CameraProfile => { },
|
1534
1591
|
LookTable => { },
|
1535
1592
|
ToneCurvePV2012 => { List => 'Seq' },
|
1593
|
+
ToneCurvePV2012Red => { List => 'Seq' },
|
1594
|
+
ToneCurvePV2012Green => { List => 'Seq' },
|
1595
|
+
ToneCurvePV2012Blue => { List => 'Seq' },
|
1536
1596
|
},
|
1537
1597
|
},
|
1538
1598
|
}
|
@@ -1578,6 +1638,14 @@ my %sPantryItem = (
|
|
1578
1638
|
AutoToneDigestNoSat => { },
|
1579
1639
|
ToggleStyleDigest => { },
|
1580
1640
|
ToggleStyleAmount => { Writable => 'integer' },
|
1641
|
+
# new for LightRoom 11.0
|
1642
|
+
CompatibleVersion => { },
|
1643
|
+
MaskGroupBasedCorrections => {
|
1644
|
+
FlatName => 'MaskGroupBasedCorr',
|
1645
|
+
Struct => \%sCorrection,
|
1646
|
+
List => 'Seq',
|
1647
|
+
},
|
1648
|
+
RangeMaskMapInfo => { Name => 'RangeMask', Struct => \%sRangeMask, FlatName => 'RangeMask' },
|
1581
1649
|
);
|
1582
1650
|
|
1583
1651
|
# Tiff namespace properties (tiff)
|
@@ -2139,8 +2207,8 @@ my %sPantryItem = (
|
|
2139
2207
|
NAMESPACE => 'exifEX',
|
2140
2208
|
PRIORITY => 0, # not as reliable as actual EXIF tags
|
2141
2209
|
NOTES => q{
|
2142
|
-
EXIF tags added by the EXIF 2.
|
2143
|
-
L<
|
2210
|
+
EXIF tags added by the EXIF 2.32 for XMP specification (see
|
2211
|
+
L<https://cipa.jp/std/documents/download_e.html?DC-010-2020_E>).
|
2144
2212
|
},
|
2145
2213
|
Gamma => { Writable => 'rational' },
|
2146
2214
|
PhotographicSensitivity => { Writable => 'integer' },
|
@@ -2304,6 +2372,7 @@ my %sPantryItem = (
|
|
2304
2372
|
VignetteCorrectionAlreadyApplied => { Writable => 'boolean' },
|
2305
2373
|
LateralChromaticAberrationCorrectionAlreadyApplied => { Writable => 'boolean' },
|
2306
2374
|
LensDistortInfo => { }, # (LR 7.5.1, 4 signed rational values)
|
2375
|
+
NeutralDensityFactor => { }, # (LR 11.0 - rational value, but denominator seems significant)
|
2307
2376
|
);
|
2308
2377
|
|
2309
2378
|
# IPTC Core namespace properties (Iptc4xmpCore) (ref 4)
|
@@ -2346,6 +2415,9 @@ my %sPantryItem = (
|
|
2346
2415
|
Scene => { Groups => { 2 => 'Other' }, List => 'Bag' },
|
2347
2416
|
SubjectCode => { Groups => { 2 => 'Other' }, List => 'Bag' },
|
2348
2417
|
# Copyright - have seen this in a sample (Jan 2021), but I think it is non-standard
|
2418
|
+
# new IPTC Core 1.3 properties
|
2419
|
+
AltTextAccessibility => { Groups => { 2 => 'Other' }, Writable => 'lang-alt' },
|
2420
|
+
ExtDescrAccessibility => { Groups => { 2 => 'Other' }, Writable => 'lang-alt' },
|
2349
2421
|
);
|
2350
2422
|
|
2351
2423
|
# Adobe Lightroom namespace properties (lr) (ref PH)
|
@@ -2357,6 +2429,7 @@ my %sPantryItem = (
|
|
2357
2429
|
NOTES => 'Adobe Lightroom "lr" namespace tags.',
|
2358
2430
|
privateRTKInfo => { },
|
2359
2431
|
hierarchicalSubject => { List => 'Bag' },
|
2432
|
+
weightedFlatSubject => { List => 'Bag' },
|
2360
2433
|
);
|
2361
2434
|
|
2362
2435
|
# Adobe Album namespace properties (album) (ref PH)
|
@@ -3499,6 +3572,17 @@ sub ParseXMPElement($$$;$$$$)
|
|
3499
3572
|
}
|
3500
3573
|
$start = pos($$dataPt); # start from here the next time around
|
3501
3574
|
|
3575
|
+
# ignore specified XMP namespaces/properties
|
3576
|
+
if ($$et{EXCL_XMP_LOOKUP} and not $isWriting and $prop =~ /^(.+):(.*)/) {
|
3577
|
+
my ($ns, $nm) = (lc($stdXlatNS{$1} || $1), lc($2));
|
3578
|
+
if ($$et{EXCL_XMP_LOOKUP}{"xmp-$ns:all"} or $$et{EXCL_XMP_LOOKUP}{"xmp-$ns:$nm"} or
|
3579
|
+
$$et{EXCL_XMP_LOOKUP}{"xmp-all:$nm"})
|
3580
|
+
{
|
3581
|
+
++$count; # (pretend we found something so we don't store as a tag value)
|
3582
|
+
next;
|
3583
|
+
}
|
3584
|
+
}
|
3585
|
+
|
3502
3586
|
# extract property attributes
|
3503
3587
|
my ($parseResource, %attrs, @attrs);
|
3504
3588
|
while ($attrs =~ m/(\S+?)\s*=\s*(['"])(.*?)\2/sg) {
|
@@ -3596,9 +3680,9 @@ sub ParseXMPElement($$$;$$$$)
|
|
3596
3680
|
if ($nItems == 1000) {
|
3597
3681
|
my ($tg,$ns) = GetXMPTagID($propList);
|
3598
3682
|
if ($isWriting) {
|
3599
|
-
$et->
|
3683
|
+
$et->WarnOnce("Excessive number of items for $ns:$tg. Processing may be slow", 1);
|
3600
3684
|
} elsif (not $$et{OPTIONS}{IgnoreMinorErrors}) {
|
3601
|
-
$et->
|
3685
|
+
$et->WarnOnce("Extracted only 1000 $ns:$tg items. Ignore minor errors to extract all", 2);
|
3602
3686
|
last;
|
3603
3687
|
}
|
3604
3688
|
}
|
@@ -3960,7 +4044,7 @@ sub ProcessXMP($$;$)
|
|
3960
4044
|
} elsif ($1 eq 'REDXIF') {
|
3961
4045
|
$type = 'RMD';
|
3962
4046
|
$mime = 'application/xml';
|
3963
|
-
}
|
4047
|
+
} elsif ($1 ne 'fcpxml') { # Final Cut Pro XML
|
3964
4048
|
return 0;
|
3965
4049
|
}
|
3966
4050
|
} elsif ($buf2 =~ /<svg[\s>]/) {
|
@@ -3970,14 +4054,16 @@ sub ProcessXMP($$;$)
|
|
3970
4054
|
} elsif ($buf2 =~ /<plist[\s>]/) {
|
3971
4055
|
$type = 'PLIST';
|
3972
4056
|
}
|
3973
|
-
if ($isSVG and $$et{XMP_CAPTURE}) {
|
3974
|
-
$et->Error("ExifTool does not yet support writing of SVG images");
|
3975
|
-
return 0;
|
3976
|
-
}
|
3977
4057
|
}
|
3978
4058
|
$isXML = 1;
|
3979
4059
|
} elsif ($2 eq '<rdf:RDF') {
|
3980
4060
|
$isRDF = 1; # recognize XMP without x:xmpmeta element
|
4061
|
+
} elsif ($2 eq '<svg') {
|
4062
|
+
$isSVG = $isXML = 1;
|
4063
|
+
}
|
4064
|
+
if ($isSVG and $$et{XMP_CAPTURE}) {
|
4065
|
+
$et->Error("ExifTool does not yet support writing of SVG images");
|
4066
|
+
return 0;
|
3981
4067
|
}
|
3982
4068
|
if ($buff =~ /^\0\0/) {
|
3983
4069
|
$fmt = 'N'; # UTF-32 MM with or without BOM
|
@@ -537,7 +537,7 @@ my %sImageRegion = ( # new in 1.5
|
|
537
537
|
NAMESPACE => 'Iptc4xmpExt',
|
538
538
|
TABLE_DESC => 'XMP IPTC Extension',
|
539
539
|
NOTES => q{
|
540
|
-
This table contains tags defined by the IPTC Extension schema version 1.
|
540
|
+
This table contains tags defined by the IPTC Extension schema version 1.6.
|
541
541
|
The actual namespace prefix is "Iptc4xmpExt", but ExifTool shortens this for
|
542
542
|
the family 1 group name. (see
|
543
543
|
L<http://www.iptc.org/standards/photo-metadata/iptc-standard/>)
|
@@ -797,6 +797,8 @@ my %sImageRegion = ( # new in 1.5
|
|
797
797
|
audioBitsPerSample => { Groups => { 2 => 'Audio' }, Writable => 'integer' },
|
798
798
|
# new IPTC Extension schema 1.5 property
|
799
799
|
ImageRegion => { Groups => { 2 => 'Image' }, List => 'Bag', Struct => \%sImageRegion },
|
800
|
+
# new Extension 1.6 property
|
801
|
+
EventId => { Name => 'EventID', List => 'Bag' },
|
800
802
|
);
|
801
803
|
|
802
804
|
#------------------------------------------------------------------------------
|
data/bin/lib/Image/ExifTool.pm
CHANGED
@@ -26,10 +26,10 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes
|
|
26
26
|
$psAPP13hdr $psAPP13old @loadAllTables %UserDefined $evalWarning
|
27
27
|
%noWriteFile %magicNumber @langs $defaultLang %langName %charsetName
|
28
28
|
%mimeType $swapBytes $swapWords $currentByteOrder %unpackStd
|
29
|
-
%jpegMarker %specialTags %fileTypeLookup $testLen $
|
29
|
+
%jpegMarker %specialTags %fileTypeLookup $testLen $exeDir
|
30
30
|
%static_vars);
|
31
31
|
|
32
|
-
$VERSION = '12.
|
32
|
+
$VERSION = '12.36';
|
33
33
|
$RELEASE = '';
|
34
34
|
@ISA = qw(Exporter);
|
35
35
|
%EXPORT_TAGS = (
|
@@ -808,6 +808,7 @@ my %moduleName = (
|
|
808
808
|
DEX => 0,
|
809
809
|
DOCX => 'OOXML',
|
810
810
|
DCX => 0,
|
811
|
+
DIR => 0,
|
811
812
|
DR4 => 'CanonVRD',
|
812
813
|
DSS => 'Olympus',
|
813
814
|
DWF => 0,
|
@@ -908,7 +909,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
|
|
908
909
|
GZIP => '\x1f\x8b\x08',
|
909
910
|
HDR => '#\?(RADIANCE|RGBE)\x0a',
|
910
911
|
HTML => '(\xef\xbb\xbf)?\s*(?i)<(!DOCTYPE\s+HTML|HTML|\?xml)', # (case insensitive)
|
911
|
-
ICC => '.{12}(scnr|mntr|prtr|link|spac|abst|nmcl|nkpf)(XYZ |Lab |Luv |YCbr|Yxy |RGB |GRAY|HSV |HLS |CMYK|CMY |[2-9A-F]CLR){2}',
|
912
|
+
ICC => '.{12}(scnr|mntr|prtr|link|spac|abst|nmcl|nkpf|cenc|mid |mlnk|mvis)(XYZ |Lab |Luv |YCbr|Yxy |RGB |GRAY|HSV |HLS |CMYK|CMY |[2-9A-F]CLR|nc..|\0{4}){2}',
|
912
913
|
IND => '\x06\x06\xed\xf5\xd8\x1d\x46\xe5\xbd\x31\xef\xe7\xfe\x74\xb7\x1d',
|
913
914
|
# ISO => signature is at byte 32768
|
914
915
|
ITC => '.{4}itch',
|
@@ -1155,14 +1156,14 @@ my %systemTagsNotes = (
|
|
1155
1156
|
Groups => { 1 => 'System', 2 => 'Other' },
|
1156
1157
|
Notes => q{
|
1157
1158
|
file name without extension. Not generated unless specifically requested or
|
1158
|
-
the L<RequestAll|../ExifTool.html#RequestAll>
|
1159
|
+
the API L<RequestAll|../ExifTool.html#RequestAll> option is set
|
1159
1160
|
},
|
1160
1161
|
},
|
1161
1162
|
FilePath => {
|
1162
1163
|
Groups => { 1 => 'System', 2 => 'Other' },
|
1163
1164
|
Notes => q{
|
1164
1165
|
absolute path of source file. Not generated unless specifically requested or
|
1165
|
-
the L<RequestAll|../ExifTool.html#RequestAll>
|
1166
|
+
the API L<RequestAll|../ExifTool.html#RequestAll> option is set. Does not support Windows Unicode file
|
1166
1167
|
names
|
1167
1168
|
},
|
1168
1169
|
},
|
@@ -1185,7 +1186,7 @@ my %systemTagsNotes = (
|
|
1185
1186
|
sequence number for each source file when extracting or copying information,
|
1186
1187
|
including files that fail the -if condition of the command-line application,
|
1187
1188
|
beginning at 0 for the first file. Not generated unless specifically
|
1188
|
-
requested or the L<RequestAll|../ExifTool.html#RequestAll>
|
1189
|
+
requested or the API L<RequestAll|../ExifTool.html#RequestAll> option is set
|
1189
1190
|
},
|
1190
1191
|
},
|
1191
1192
|
FileSize => {
|
@@ -1207,6 +1208,18 @@ my %systemTagsNotes = (
|
|
1207
1208
|
},
|
1208
1209
|
PrintConv => \&ConvertFileSize,
|
1209
1210
|
},
|
1211
|
+
ZoneIdentifier => {
|
1212
|
+
Groups => { 1 => 'System', 2 => 'Other' },
|
1213
|
+
Notes => q{
|
1214
|
+
Windows only. Used to indicate that a file has a Zone.Identifier alternate
|
1215
|
+
data stream, which is used by some Windows browsers to mark downloaded files
|
1216
|
+
as possibly unsafe to run. May be deleted to remove this stream. Requires
|
1217
|
+
Win32API::File
|
1218
|
+
},
|
1219
|
+
Writable => 1,
|
1220
|
+
WritePseudo => 1,
|
1221
|
+
Protected => 1,
|
1222
|
+
},
|
1210
1223
|
FileType => {
|
1211
1224
|
Groups => { 2 => 'Other' },
|
1212
1225
|
Notes => q{
|
@@ -1258,7 +1271,7 @@ my %systemTagsNotes = (
|
|
1258
1271
|
the filesystem creation date/time. Windows/Mac only. In Windows, the file
|
1259
1272
|
creation date/time is preserved by default when writing if Win32API::File
|
1260
1273
|
and Win32::API are available. On Mac, this tag is extracted only if it or
|
1261
|
-
the MacOS group is specifically requested or the L<RequestAll|../ExifTool.html#RequestAll>
|
1274
|
+
the MacOS group is specifically requested or the API L<RequestAll|../ExifTool.html#RequestAll> option is
|
1262
1275
|
set to 2 or higher. Requires "setfile" for writing on Mac, which may be
|
1263
1276
|
installed by typing C<xcode-select --install> in the Terminal
|
1264
1277
|
},
|
@@ -1649,7 +1662,7 @@ my %systemTagsNotes = (
|
|
1649
1662
|
sub-sampling values to generate the value of this tag. The result is
|
1650
1663
|
compared to known values in an attempt to deduce the originating software
|
1651
1664
|
based only on the JPEG image data. For performance reasons, this tag is
|
1652
|
-
generated only if specifically requested or the L<RequestAll|../ExifTool.html#RequestAll>
|
1665
|
+
generated only if specifically requested or the API L<RequestAll|../ExifTool.html#RequestAll> option is set
|
1653
1666
|
to 3 or higher
|
1654
1667
|
},
|
1655
1668
|
},
|
@@ -1657,14 +1670,14 @@ my %systemTagsNotes = (
|
|
1657
1670
|
Notes => q{
|
1658
1671
|
an estimate of the IJG JPEG quality setting for the image, calculated from
|
1659
1672
|
the quantization tables. For performance reasons, this tag is generated
|
1660
|
-
only if specifically requested or the L<RequestAll|../ExifTool.html#RequestAll>
|
1673
|
+
only if specifically requested or the API L<RequestAll|../ExifTool.html#RequestAll> option is set to 3 or
|
1661
1674
|
higher
|
1662
1675
|
},
|
1663
1676
|
},
|
1664
1677
|
JPEGImageLength => {
|
1665
1678
|
Notes => q{
|
1666
1679
|
byte length of JPEG image without metadata. For performance reasons, this
|
1667
|
-
tag is generated only if specifically requested or the L<RequestAll|../ExifTool.html#RequestAll>
|
1680
|
+
tag is generated only if specifically requested or the API L<RequestAll|../ExifTool.html#RequestAll> option
|
1668
1681
|
is set to 3 or higher
|
1669
1682
|
},
|
1670
1683
|
},
|
@@ -1674,7 +1687,7 @@ my %systemTagsNotes = (
|
|
1674
1687
|
Notes => q{
|
1675
1688
|
the current date/time. Useful when setting the tag values, eg.
|
1676
1689
|
C<"-modifydate<now">. Not generated unless specifically requested or the
|
1677
|
-
L<RequestAll|../ExifTool.html#RequestAll>
|
1690
|
+
API L<RequestAll|../ExifTool.html#RequestAll> option is set
|
1678
1691
|
},
|
1679
1692
|
PrintConv => '$self->ConvertDateTime($val)',
|
1680
1693
|
},
|
@@ -1685,7 +1698,7 @@ my %systemTagsNotes = (
|
|
1685
1698
|
YYYYmmdd-HHMM-SSNN-PPPP-RRRRRRRRRRRR, where Y=year, m=month, d=day, H=hour,
|
1686
1699
|
M=minute, S=second, N=file sequence number in hex, P=process ID in hex, and
|
1687
1700
|
R=random hex number; without dashes with the -n option. Not generated
|
1688
|
-
unless specifically requested or the L<RequestAll|../ExifTool.html#RequestAll>
|
1701
|
+
unless specifically requested or the API L<RequestAll|../ExifTool.html#RequestAll> option is set
|
1689
1702
|
},
|
1690
1703
|
PrintConv => '$val =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/; $val',
|
1691
1704
|
},
|
@@ -1778,7 +1791,7 @@ my %systemTagsNotes = (
|
|
1778
1791
|
Groups => { 0 => 'Trailer' },
|
1779
1792
|
Notes => q{
|
1780
1793
|
the full JPEG trailer data block. Extracted only if specifically requested
|
1781
|
-
or the RequestAll
|
1794
|
+
or the API RequestAll option is set to 3 or higher
|
1782
1795
|
},
|
1783
1796
|
Writable => 1,
|
1784
1797
|
Protected => 1,
|
@@ -2319,6 +2332,7 @@ sub ClearOptions($)
|
|
2319
2332
|
Password => undef, # password for password-protected PDF documents
|
2320
2333
|
PrintConv => 1, # flag to enable print conversion
|
2321
2334
|
QuickTimeHandler => 1, # flag to add mdir Handler to newly created Meta box
|
2335
|
+
QuickTimePad=> undef, # flag to preserve padding of QuickTime CR3 tags
|
2322
2336
|
QuickTimeUTC=> undef, # assume that QuickTime date/time tags are stored as UTC
|
2323
2337
|
RequestAll => undef, # extract all tags that must be specifically requested
|
2324
2338
|
RequestTags => undef, # extra tags to request (on top of those in the tag list)
|
@@ -2368,7 +2382,7 @@ sub ExtractInfo($;@)
|
|
2368
2382
|
my $fast = $$options{FastScan} || 0;
|
2369
2383
|
my $req = $$self{REQ_TAG_LOOKUP};
|
2370
2384
|
my $reqAll = $$options{RequestAll} || 0;
|
2371
|
-
my (%saveOptions, $reEntry, $rsize, $type, @startTime, $saveOrder, $isDir);
|
2385
|
+
my (%saveOptions, $reEntry, $rsize, $zid, $type, @startTime, $saveOrder, $isDir);
|
2372
2386
|
|
2373
2387
|
# check for internal ReEntry option to allow recursive calls to ExtractInfo
|
2374
2388
|
if (ref $_[1] eq 'HASH' and $_[1]{ReEntry} and
|
@@ -2460,6 +2474,17 @@ sub ExtractInfo($;@)
|
|
2460
2474
|
}
|
2461
2475
|
# get size of resource fork on Mac OS
|
2462
2476
|
$rsize = -s "$filename/..namedfork/rsrc" if $^O eq 'darwin' and not $$self{IN_RESOURCE};
|
2477
|
+
# check to see if Zone.Identifier file exists in Windows
|
2478
|
+
if ($^O eq 'MSWin32' and eval { require Win32API::File }) {
|
2479
|
+
my $wattr;
|
2480
|
+
my $zfile = "${filename}:Zone.Identifier";
|
2481
|
+
if ($self->EncodeFileName($zfile)) {
|
2482
|
+
$wattr = eval { Win32API::File::GetFileAttributesW($zfile) };
|
2483
|
+
} else {
|
2484
|
+
$wattr = eval { Win32API::File::GetFileAttributes($zfile) };
|
2485
|
+
}
|
2486
|
+
$zid = 1 unless $wattr == Win32API::File::INVALID_FILE_ATTRIBUTES();
|
2487
|
+
}
|
2463
2488
|
}
|
2464
2489
|
# open the file
|
2465
2490
|
if ($self->Open(\*EXIFTOOL_FILE, $filename)) {
|
@@ -2502,6 +2527,7 @@ sub ExtractInfo($;@)
|
|
2502
2527
|
my $fileSize = $stat[7];
|
2503
2528
|
$self->FoundTag('FileSize', $stat[7]) if defined $stat[7];
|
2504
2529
|
$self->FoundTag('ResourceForkSize', $rsize) if $rsize;
|
2530
|
+
$self->FoundTag('ZoneIdentifier', 'Exists') if $zid;
|
2505
2531
|
$self->FoundTag('FileModifyDate', $stat[9]) if defined $stat[9];
|
2506
2532
|
$self->FoundTag('FileAccessDate', $stat[8]) if defined $stat[8];
|
2507
2533
|
my $cTag = $^O eq 'MSWin32' ? 'FileCreateDate' : 'FileInodeChangeDate';
|
@@ -4226,6 +4252,7 @@ sub ParseArguments($;@)
|
|
4226
4252
|
$$self{REQ_TAG_LOOKUP} = { };
|
4227
4253
|
$$self{EXCL_TAG_LOOKUP} = { };
|
4228
4254
|
$$self{IO_TAG_LIST} = undef;
|
4255
|
+
delete $$self{EXCL_XMP_LOOKUP};
|
4229
4256
|
|
4230
4257
|
# handle our input arguments
|
4231
4258
|
while (@_) {
|
@@ -4309,7 +4336,11 @@ sub ParseArguments($;@)
|
|
4309
4336
|
# generate lookup for excluded tags
|
4310
4337
|
if ($$options{Exclude}) {
|
4311
4338
|
foreach (@{$$options{Exclude}}) {
|
4312
|
-
/([-\w]+)#?$/ and $$self{EXCL_TAG_LOOKUP}{lc
|
4339
|
+
/([-\w]+)#?$/ and $$self{EXCL_TAG_LOOKUP}{lc $1} = 1;
|
4340
|
+
if (/(xmp-.*:[-\w]+)#?/i) {
|
4341
|
+
$$self{EXCL_XMP_LOOKUP} or $$self{EXCL_XMP_LOOKUP} = { };
|
4342
|
+
$$self{EXCL_XMP_LOOKUP}{lc $1} = 1;
|
4343
|
+
}
|
4313
4344
|
}
|
4314
4345
|
# exclude list is used only for EXCL_TAG_LOOKUP when TAGS_FROM_FILE is set
|
4315
4346
|
undef $$options{Exclude} if $$self{TAGS_FROM_FILE};
|
@@ -5651,6 +5682,38 @@ sub ConvertDateTime($$)
|
|
5651
5682
|
unshift @a, 1 while @a < 3; # add month and day if necessary
|
5652
5683
|
unshift @a, 0 while @a < 6; # add h,m,s if necessary
|
5653
5684
|
$a[4] -= 1; # base month is 1
|
5685
|
+
# parse our %f fractional seconds first (and round up seconds if necessary)
|
5686
|
+
# - if there are multiple %f codes, they all get the same number of digits as the first
|
5687
|
+
if ($fmt =~ /%\.?(\d*)f/) {
|
5688
|
+
my $dig = $1;
|
5689
|
+
my $frac = $date =~ /(\.\d+)/ ? $1 : '';
|
5690
|
+
if (not $frac) {
|
5691
|
+
$frac = '.' . ('0' x $dig) if $dig;
|
5692
|
+
} elsif (length $dig) {
|
5693
|
+
if ($dig+1 > length($frac)) {
|
5694
|
+
$frac .= '0' x ($dig+1-length($frac));
|
5695
|
+
} elsif ($dig+1 < length($frac)) {
|
5696
|
+
$frac = sprintf("%.${dig}f", $frac);
|
5697
|
+
while ($frac =~ s/^(\d)// and $1 ne '0') {
|
5698
|
+
# this is a pain, but we must round up to the next second
|
5699
|
+
++$a[0] < 60 and last;
|
5700
|
+
$a[0] = 0;
|
5701
|
+
++$a[1] < 60 and last;
|
5702
|
+
$a[1] = 0;
|
5703
|
+
++$a[2] < 24 and last;
|
5704
|
+
$a[2] = 0;
|
5705
|
+
require 'Image/ExifTool/Shift.pl';
|
5706
|
+
++$a[3] <= DaysInMonth($a[4]+1, $a[5]) and last;
|
5707
|
+
$a[3] = 1;
|
5708
|
+
++$a[4] < 12 and last;
|
5709
|
+
$a[4] = 0;
|
5710
|
+
++$a[5];
|
5711
|
+
last; # (this was a goto)
|
5712
|
+
}
|
5713
|
+
}
|
5714
|
+
}
|
5715
|
+
$fmt =~ s/(^|[^%])((%%)*)%\.?\d*f/$1$2$frac/g;
|
5716
|
+
}
|
5654
5717
|
# parse %z and %s ourself (to handle time zones properly)
|
5655
5718
|
if ($fmt =~ /%[sz]/) {
|
5656
5719
|
# use system time zone unless otherwise specified
|
@@ -6251,7 +6314,7 @@ sub ProcessJPEG($$)
|
|
6251
6314
|
my $markerName = JpegMarkerName($marker);
|
6252
6315
|
$$path[$pn] = $markerName;
|
6253
6316
|
# issue warning if we skipped some garbage
|
6254
|
-
if ($skipped and not $foundSOS) {
|
6317
|
+
if ($skipped and not $foundSOS and $markerName ne 'SOS') {
|
6255
6318
|
$self->Warn("Skipped unknown $skipped bytes after JPEG $markerName segment", 1);
|
6256
6319
|
if ($htmlDump) {
|
6257
6320
|
$self->HDump($nextSegPos-4-$skipped, $skipped, "[unknown $skipped bytes]", undef, 0x08);
|
@@ -6469,7 +6532,7 @@ sub ProcessJPEG($$)
|
|
6469
6532
|
next;
|
6470
6533
|
} elsif ($marker == 0xdb and length($$segDataPt) and # DQT
|
6471
6534
|
# save the DQT data only if JPEGDigest has been requested
|
6472
|
-
# (Note: since we aren't checking the RequestAll
|
6535
|
+
# (Note: since we aren't checking the API RequestAll option here, the application
|
6473
6536
|
# must use the RequestTags option to generate these tags if they have not been
|
6474
6537
|
# specifically requested. The reason is that there is too much overhead involved
|
6475
6538
|
# in the calculation of this tag to make this worth the CPU time.)
|
@@ -8710,6 +8773,7 @@ sub ProcessBinaryData($$$)
|
|
8710
8773
|
# read value now if necessary
|
8711
8774
|
unless (defined $val and not $$tagInfo{SubDirectory}) {
|
8712
8775
|
$val = ReadValue($dataPt, $entry+$offset, $format, $count, $more, \$rational);
|
8776
|
+
next unless defined $val;
|
8713
8777
|
$mask = $$tagInfo{Mask};
|
8714
8778
|
$val = ($val & $mask) >> $$tagInfo{BitShift} if $mask;
|
8715
8779
|
}
|
@@ -8811,8 +8875,8 @@ until ($Image::ExifTool::noConfig) {
|
|
8811
8875
|
$file = $config;
|
8812
8876
|
}
|
8813
8877
|
# also check executable directory unless path is absolute
|
8814
|
-
$
|
8815
|
-
-r $file or $config =~ /^\// or $file =
|
8878
|
+
$exeDir = ($0 =~ /(.*)[\\\/]/) ? $1 : '.' unless defined $exeDir;
|
8879
|
+
-r $file or $config =~ /^\// or $file = "$exeDir/$config";
|
8816
8880
|
unless (-r $file) {
|
8817
8881
|
warn("Config file not found\n") if defined $Image::ExifTool::configFile;
|
8818
8882
|
last;
|
data/bin/lib/Image/ExifTool.pod
CHANGED
@@ -860,6 +860,14 @@ commonly found in samples from other software, and it has been reported that
|
|
860
860
|
Apple QuickTime Player and Photos.apps will ignore ItemList tags if this is
|
861
861
|
missing. Default is 1.
|
862
862
|
|
863
|
+
=item QuickTimePad
|
864
|
+
|
865
|
+
Flag to preserve the padding of some QuickTime atoms when writing.
|
866
|
+
QuickTime-based Canon CR3 files pad the values of container atoms with null
|
867
|
+
bytes. This padding is removed by default when the file is rewritten, but
|
868
|
+
setting this option to 1 adds padding to preserve the original atom size if
|
869
|
+
the new atom would be smaller than the original. Default is undef.
|
870
|
+
|
863
871
|
=item QuickTimeUTC
|
864
872
|
|
865
873
|
Flag set to assume that QuickTime date/time values are stored as UTC,
|
@@ -1236,7 +1244,7 @@ The following ExifTool options are effective in the call to L</WriteInfo>:
|
|
1236
1244
|
|
1237
1245
|
ByteOrder, Charset, CharsetEXIF, CharsetFileName, CharsetIPTC, Compact,
|
1238
1246
|
Compress, FixBase, IgnoreMinorErrors, NoMultiExif, NoPDFList, Password,
|
1239
|
-
QuickTimeHandler, Verbose and WriteMode.
|
1247
|
+
QuickTimeHandler, QuickTimePad, Verbose and WriteMode.
|
1240
1248
|
|
1241
1249
|
=head2 GetTagList
|
1242
1250
|
|