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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +77 -3
  3. data/bin/META.json +1 -1
  4. data/bin/META.yml +1 -1
  5. data/bin/README +2 -2
  6. data/bin/exiftool +57 -39
  7. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +7 -2
  8. data/bin/lib/Image/ExifTool/CBOR.pm +85 -31
  9. data/bin/lib/Image/ExifTool/Canon.pm +28 -3
  10. data/bin/lib/Image/ExifTool/Charset.pm +2 -0
  11. data/bin/lib/Image/ExifTool/Exif.pm +109 -3
  12. data/bin/lib/Image/ExifTool/FLIR.pm +33 -8
  13. data/bin/lib/Image/ExifTool/ICC_Profile.pm +96 -4
  14. data/bin/lib/Image/ExifTool/JSON.pm +4 -2
  15. data/bin/lib/Image/ExifTool/Jpeg2000.pm +111 -12
  16. data/bin/lib/Image/ExifTool/MacOS.pm +2 -2
  17. data/bin/lib/Image/ExifTool/Nikon.pm +637 -16
  18. data/bin/lib/Image/ExifTool/NikonCustom.pm +5 -1
  19. data/bin/lib/Image/ExifTool/NikonSettings.pm +67 -11
  20. data/bin/lib/Image/ExifTool/Olympus.pm +5 -1
  21. data/bin/lib/Image/ExifTool/PDF.pm +5 -3
  22. data/bin/lib/Image/ExifTool/QuickTime.pm +21 -2
  23. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +2 -2
  24. data/bin/lib/Image/ExifTool/README +6 -2
  25. data/bin/lib/Image/ExifTool/Sony.pm +31 -11
  26. data/bin/lib/Image/ExifTool/TagInfoXML.pm +9 -4
  27. data/bin/lib/Image/ExifTool/TagLookup.pm +5054 -4455
  28. data/bin/lib/Image/ExifTool/TagNames.pod +1185 -23
  29. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +10 -0
  30. data/bin/lib/Image/ExifTool/Writer.pl +45 -3
  31. data/bin/lib/Image/ExifTool/XMP.pm +111 -25
  32. data/bin/lib/Image/ExifTool/XMP2.pl +3 -1
  33. data/bin/lib/Image/ExifTool.pm +83 -19
  34. data/bin/lib/Image/ExifTool.pod +9 -1
  35. data/bin/perl-Image-ExifTool.spec +1 -1
  36. data/lib/exiftool_vendored/version.rb +1 -1
  37. 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
- $$a[$i] = "0$a[$i]";# pad to 2 digits if necessary
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.44';
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
- my %sCorrectionRangeMask = (
478
- STRUCT_NAME => 'CorrectionRangeMask',
479
- NAMESPACE => 'crs',
480
- Version => { },
481
- Type => { },
482
- ColorAmount => { Writable => 'real' },
483
- LumMin => { Writable => 'real' },
484
- LumMax => { Writable => 'real' },
485
- LumFeather => { Writable => 'real' },
486
- DepthMin => { Writable => 'real' },
487
- DepthMax => { Writable => 'real' },
488
- DepthFeather=> { Writable => 'real' },
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.31 for XMP specification (see
2143
- L<http://www.cipa.jp/std/documents/e/DC-X010-2017.pdf>).
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->Warn("Excessive number of items for $ns:$tg. Processing may be slow", 1);
3683
+ $et->WarnOnce("Excessive number of items for $ns:$tg. Processing may be slow", 1);
3600
3684
  } elsif (not $$et{OPTIONS}{IgnoreMinorErrors}) {
3601
- $et->Warn("Extracted only 1000 $ns:$tg items. Ignore minor errors to extract all", 2);
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
- } else {
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.5.
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
  #------------------------------------------------------------------------------
@@ -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 $exePath
29
+ %jpegMarker %specialTags %fileTypeLookup $testLen $exeDir
30
30
  %static_vars);
31
31
 
32
- $VERSION = '12.32';
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> API option is set
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> API option is set. Does not support Windows Unicode file
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> API option is set
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> API option is
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> API option is set
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> API option is set to 3 or
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> API option
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> API option is set
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> API option is set
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 API option is set to 3 or higher
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($1)} = 1;
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 API option here, the application
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
- $exePath = $0 unless defined $exePath; # (undocumented $exePath setting)
8815
- -r $file or $config =~ /^\// or $file = ($exePath =~ /(.*[\\\/])/ ? $1 : './') . $config;
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;
@@ -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