exiftool_vendored 12.50.0 → 12.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@ meta information extracted from or written to a file.
12
12
  =head1 TAG TABLES
13
13
 
14
14
  The tables listed below give the names of all tags recognized by ExifTool.
15
- They contain a total of 26027 tags, with 16663 unique tag names.
15
+ They contain a total of 26197 tags, with 16717 unique tag names.
16
16
 
17
17
  B<Tag ID>, B<Index#> or B<Sequence> is given in the first column of each
18
18
  table. A B<Tag ID> is the computer-readable equivalent of a tag name, and
@@ -14436,6 +14436,8 @@ These tags are extracted from encrypted data in images from the Z9.
14436
14436
  60143 PitchAngle fixed32u
14437
14437
  60147 YawAngle fixed32u
14438
14438
  60491 MenuSettingsZ9 Nikon MenuSettingsZ9
14439
+ -
14440
+ Nikon MenuSettingsZ9Firmware3
14439
14441
 
14440
14442
  =head3 Nikon MenuSettingsZ9 Tags
14441
14443
 
@@ -14513,6 +14515,79 @@ These tags are used by the Z9.
14513
14515
  1636 USBPowerDelivery? int8u
14514
14516
  1645 SensorShield? int8u
14515
14517
 
14518
+ =head3 Nikon MenuSettingsZ9Firmware3 Tags
14519
+
14520
+ These tags are used by the Z9 firmware 3.00.
14521
+
14522
+ Index1 Tag Name Writable
14523
+ --------------- --------
14524
+ 154 MultipleExposureMode int8u
14525
+ 156 MultiExposureShots int8u
14526
+ 204 Intervals int32u
14527
+ 208 ShotsPerInterval int32u
14528
+ 248 FocusShiftNumberShots int8u
14529
+ 252 FocusShiftStepWidth int8u
14530
+ 256 FocusShiftInterval int8u~
14531
+ 260 FocusShiftExposureLock? int8u
14532
+ 290 PhotoShootingMenuBank int8u
14533
+ 292 ExtendedMenuBanks int8u
14534
+ 328 PhotoShootingMenuBankImageArea int8u
14535
+ 342 AutoISO int8u
14536
+ 344 ISOAutoHiLimit? int16u
14537
+ 346 ISOAutoFlashLimit? int16u
14538
+ 354 ISOAutoShutterTime no
14539
+ 436 MovieVignetteControl? int8u
14540
+ 438 DiffractionCompensation int8u
14541
+ 440 FlickerReductionShooting int8u
14542
+ 548 AFAreaMode int8u
14543
+ 550 VRMode int8u
14544
+ 554 BracketSet int8u
14545
+ 556 BracketProgram int8u
14546
+ 558 BracketIncrement int8u
14547
+ 576 SecondarySlotFunction int8u
14548
+ 592 DXCropAlert int8u
14549
+ 594 SubjectDetection int8u
14550
+ 636 HighFrequencyFlickerReductionShooting? int8u
14551
+ 646 MovieImageArea? int8u & 0x01
14552
+ 656 MovieType? int8u
14553
+ 658 MovieISOAutoHiLimit? int16u
14554
+ 660 MovieISOAutoControlManualMode? int8u
14555
+ 662 MovieISOAutoManualMode? int16u
14556
+ 736 MovieActiveD-Lighting? int8u
14557
+ 738 MovieHighISONoiseReduction? int8u
14558
+ 744 MovieFlickerReduction int8u
14559
+ 746 MovieMeteringMode? int8u
14560
+ 748 MovieFocusMode? int8u
14561
+ 750 MovieAFAreaMode int8u
14562
+ 752 MovieVRMode? int8u
14563
+ 756 MovieElectronicVR? int8u
14564
+ 758 MovieSoundRecording? int8u
14565
+ 760 MicrophoneSensitivity? int8u
14566
+ 762 MicrophoneAttenuator? int8u
14567
+ 764 MicrophoneFrequencyResponse? int8u
14568
+ 766 WindNoiseReduction? int8u
14569
+ 788 MovieToneMap? int8u
14570
+ 794 MovieFrameSize? int8u
14571
+ 796 MovieFrameRate? int8u
14572
+ 802 MicrophoneJackPower? int8u
14573
+ 803 MovieDXCropAlert? int8u
14574
+ 804 MovieSubjectDetection? int8u
14575
+ 812 MovieHighResZoom? int8u
14576
+ 847 CustomSettingsZ9 NikonCustom SettingsZ9
14577
+ 1474 Language? int8u
14578
+ 1476 TimeZone int8u
14579
+ 1482 MonitorBrightness? int8u
14580
+ 1504 AFFineTune? int8u
14581
+ 1600 HDMIOutputResolution int8u
14582
+ 1613 SetClockFromLocationData? int8u
14583
+ 1620 AirplaneMode? int8u
14584
+ 1621 EmptySlotRelease? int8u
14585
+ 1656 EnergySavingMode? int8u
14586
+ 1680 RecordLocationData? int8u
14587
+ 1684 USBPowerDelivery? int8u
14588
+ 1693 SensorShield? int8u
14589
+ 1754 FocusShiftAutoReset? int8u
14590
+
14516
14591
  =head3 Nikon ShotInfo Tags
14517
14592
 
14518
14593
  This information is encrypted for ShotInfoVersion 02xx, and some tags are
@@ -16306,7 +16381,9 @@ Custom settings for the Z9.
16306
16381
  191 UseDialWithoutHold? int8u
16307
16382
  193 ReverseIndicators? int8u
16308
16383
  195 MovieFunc1Button int8u
16384
+ 199 MovieFunc2Button int8u
16309
16385
  203 MovieAF-OnButton int8u
16386
+ 215 MovieLensControlRing int8u
16310
16387
  217 MovieMultiSelector? int8u
16311
16388
  221 MovieAFSpeed int8u
16312
16389
  223 MovieAFSpeedApply int8u
@@ -23588,6 +23665,7 @@ writes only EXIF, IPTC and XMP tags in Jpeg2000 images.
23588
23665
  'bfil' BinaryFilter no
23589
23666
  'bidb' BinaryData no
23590
23667
  'bpcc' BitsPerComponent no
23668
+ 'c2sh' C2PASaltHash no
23591
23669
  'cbor' CBORData CBOR
23592
23670
  'cdef' ComponentDefinition no
23593
23671
  'cgrp' ColorGroup no
@@ -25710,6 +25788,7 @@ check if speed is more of a concern.
25710
25788
  'acTL' AnimationControl PNG AnimationControl
25711
25789
  'bKGD' BackgroundColor no
25712
25790
  'cHRM' PrimaryChromaticities PNG PrimaryChromaticities
25791
+ 'caBX' JUMBF Jpeg2000
25713
25792
  'dSIG' DigitalSignature no
25714
25793
  'eXIf' eXIf EXIF
25715
25794
  'fRAc' FractalParameters no
@@ -27543,64 +27622,64 @@ View Camera Motion Metadata of MP4 videos. See
27543
27622
  L<https://developers.google.com/streetview/publish/camm-spec> for the
27544
27623
  specification.
27545
27624
 
27546
- Index1 Tag Name Writable
27625
+ Tag ID Tag Name Writable
27547
27626
  ------ -------- --------
27548
- 4 AngleAxis no
27627
+ 0x0004 AngleAxis no
27549
27628
 
27550
27629
  =head3 QuickTime camm1 Tags
27551
27630
 
27552
- Index1 Tag Name Writable
27631
+ Tag ID Tag Name Writable
27553
27632
  ------ -------- --------
27554
- 4 PixelExposureTime no
27555
- 8 RollingShutterSkewTime no
27633
+ 0x0004 PixelExposureTime no
27634
+ 0x0008 RollingShutterSkewTime no
27556
27635
 
27557
27636
  =head3 QuickTime camm2 Tags
27558
27637
 
27559
- Index1 Tag Name Writable
27638
+ Tag ID Tag Name Writable
27560
27639
  ------ -------- --------
27561
- 4 AngularVelocity no
27640
+ 0x0004 AngularVelocity no
27562
27641
 
27563
27642
  =head3 QuickTime camm3 Tags
27564
27643
 
27565
- Index1 Tag Name Writable
27644
+ Tag ID Tag Name Writable
27566
27645
  ------ -------- --------
27567
- 4 Acceleration no
27646
+ 0x0004 Acceleration no
27568
27647
 
27569
27648
  =head3 QuickTime camm4 Tags
27570
27649
 
27571
- Index1 Tag Name Writable
27650
+ Tag ID Tag Name Writable
27572
27651
  ------ -------- --------
27573
- 4 Position no
27652
+ 0x0004 Position no
27574
27653
 
27575
27654
  =head3 QuickTime camm5 Tags
27576
27655
 
27577
- Index1 Tag Name Writable
27656
+ Tag ID Tag Name Writable
27578
27657
  ------ -------- --------
27579
- 4 GPSLatitude no
27580
- 12 GPSLongitude no
27581
- 20 GPSAltitude no
27658
+ 0x0004 GPSLatitude no
27659
+ 0x000c GPSLongitude no
27660
+ 0x0014 GPSAltitude no
27582
27661
 
27583
27662
  =head3 QuickTime camm6 Tags
27584
27663
 
27585
- Index1 Tag Name Writable
27664
+ Tag ID Tag Name Writable
27586
27665
  ------ -------- --------
27587
- 4 GPSDateTime no
27588
- 12 GPSMeasureMode no
27589
- 16 GPSLatitude no
27590
- 24 GPSLongitude no
27591
- 32 GPSAltitude no
27592
- 36 GPSHorizontalAccuracy no
27593
- 40 GPSVerticalAccuracy no
27594
- 44 GPSVelocityEast no
27595
- 48 GPSVelocityNorth no
27596
- 52 GPSVelocityUp no
27597
- 56 GPSSpeedAccuracy no
27666
+ 0x0004 GPSDateTime no
27667
+ 0x000c GPSMeasureMode no
27668
+ 0x0010 GPSLatitude no
27669
+ 0x0018 GPSLongitude no
27670
+ 0x0020 GPSAltitude no
27671
+ 0x0024 GPSHorizontalAccuracy no
27672
+ 0x0028 GPSVerticalAccuracy no
27673
+ 0x002c GPSVelocityEast no
27674
+ 0x0030 GPSVelocityNorth no
27675
+ 0x0034 GPSVelocityUp no
27676
+ 0x0038 GPSSpeedAccuracy no
27598
27677
 
27599
27678
  =head3 QuickTime camm7 Tags
27600
27679
 
27601
- Index1 Tag Name Writable
27680
+ Tag ID Tag Name Writable
27602
27681
  ------ -------- --------
27603
- 4 MagneticField no
27682
+ 0x0004 MagneticField no
27604
27683
 
27605
27684
  =head3 QuickTime marl Tags
27606
27685
 
@@ -27880,7 +27959,7 @@ QuickTimeHandler option may be set to 0 to avoid this.
27880
27959
  'pcst' Podcast int8s
27881
27960
  'perf' Performer string
27882
27961
  'pgap' PlayGap int8s
27883
- 'plID' PlayListID int32s[0.25]
27962
+ 'plID' PlayListID int32s[2]
27884
27963
  'prID' ProductID string
27885
27964
  'purd' PurchaseDate string
27886
27965
  'purl' PodcastURL string
@@ -30319,7 +30398,7 @@ Matroska specification.
30319
30398
  0x037e ChapterCountry no
30320
30399
  0x0444 SegmentFamily? no
30321
30400
  0x0461 DateTimeOriginal no
30322
- 0x047a TagLanguage no
30401
+ 0x047a TagLanguageBCP47 no
30323
30402
  0x0484 TagDefault no
30324
30403
  0x0485 TagBinary no
30325
30404
  0x0487 TagString no
@@ -30377,10 +30456,10 @@ Matroska specification.
30377
30456
  0x23a2 CodecPrivate? no
30378
30457
  0x23c0 Targets Matroska
30379
30458
  0x23c3 ChapterPhysicalEquivalent no
30380
- 0x23c4 TagChapterUID? no
30381
- 0x23c5 TagTrackUID? no
30382
- 0x23c6 TagAttachmentUID? no
30383
- 0x23c9 TagEditionUID? no
30459
+ 0x23c4 TagChapterUID no
30460
+ 0x23c5 TagTrackUID no
30461
+ 0x23c6 TagAttachmentUID no
30462
+ 0x23c9 TagEditionUID no
30384
30463
  0x23ca TargetType no
30385
30464
  0x2532 SignedElement? no
30386
30465
  0x2624 TrackTranslate Matroska
@@ -30408,7 +30487,7 @@ Matroska specification.
30408
30487
  0x3384 SegmentFileName no
30409
30488
  0x33a4 SegmentUID? no
30410
30489
  0x33c4 ChapterUID? no
30411
- 0x33c5 TrackUID? no
30490
+ 0x33c5 TrackUID no
30412
30491
  0x3446 TrackAttachmentUID no
30413
30492
  0x35a1 BlockAdditions Matroska
30414
30493
  0x38b5 OutputAudioSampleRate no
@@ -30468,6 +30547,116 @@ for the specification.
30468
30547
  0x7674 ProjectionPosePitch no
30469
30548
  0x7675 ProjectionPoseRoll no
30470
30549
 
30550
+ =head3 Matroska Tags
30551
+
30552
+ Standardized Matroska tags (see
30553
+ L<https://www.matroska.org/technical/tagging.html>).
30554
+
30555
+ Tag ID Tag Name Writable
30556
+ ------ -------- --------
30557
+ 'ACCOMPANIMENT' Accompaniment no
30558
+ 'ACTOR' Actor no
30559
+ 'ADDRESS' Address no
30560
+ 'ARRANGER' Arranger no
30561
+ 'ARTIST' Artist no
30562
+ 'ART_DIRECTOR' ArtDirector no
30563
+ 'ASSISTANT_DIRECTOR' AssistantDirector no
30564
+ 'BARCODE' Barcode no
30565
+ 'BPM' BPM no
30566
+ 'BPS' BPS no
30567
+ 'CATALOG_NUMBER' CatalogNumber no
30568
+ 'CHARACTER' Character no
30569
+ 'CHOREGRAPHER' Choregrapher no
30570
+ 'COMMENT' Comment no
30571
+ 'COMPOSER' Composer no
30572
+ 'COMPOSER_NATIONALITY' ComposerNationality no
30573
+ 'COMPOSITION_LOCATION' CompositionLocation no
30574
+ 'CONDUCTOR' Conductor no
30575
+ 'CONTENT_TYPE' ContentType no
30576
+ 'COPRODUCER' Coproducer no
30577
+ 'COPYRIGHT' Copyright no
30578
+ 'COSTUME_DESIGNER' CostumeDesigner no
30579
+ 'COUNTRY' Country no
30580
+ 'DATE_DIGITIZED' CreateDate no
30581
+ 'DATE_ENCODED' DateEncoded no
30582
+ 'DATE_PURCHASED' DatePurchased no
30583
+ 'DATE_RECORDED' DateTimeOriginal no
30584
+ 'DATE_RELEASED' DateReleased no
30585
+ 'DATE_TAGGED' DateTagged no
30586
+ 'DATE_WRITTEN' DateWritten no
30587
+ 'DESCRIPTION' Description no
30588
+ 'DIRECTOR' Director no
30589
+ 'DIRECTOR_OF_PHOTOGRAPHY'
30590
+ DirectorOfPhotography no
30591
+ 'DISTRIBUTED_BY' DistributedBy no
30592
+ 'EDITED_BY' EditedBy no
30593
+ 'EMAIL' Email no
30594
+ 'ENCODED_BY' EncodedBy no
30595
+ 'ENCODER' Encoder no
30596
+ 'ENCODER_SETTINGS' EncoderSettings no
30597
+ 'EXECUTIVE_PRODUCER' ExecutiveProducer no
30598
+ 'FAX' FAX no
30599
+ 'FPS' FPS no
30600
+ 'GENRE' Genre no
30601
+ 'IMDB' IMDB no
30602
+ 'INITIAL_KEY' InitialKey no
30603
+ 'INSTRUMENTS' Instruments no
30604
+ 'ISBN' ISBN no
30605
+ 'ISRC' ISRC no
30606
+ 'KEYWORDS' Keywords no
30607
+ 'LABEL' Label no
30608
+ 'LABEL_CODE' LabelCode no
30609
+ 'LAW_RATING' LawRating no
30610
+ 'LCCN' Lccn no
30611
+ 'LEAD_PERFORMER' LeadPerformer no
30612
+ 'LICENSE' License no
30613
+ 'LYRICIST' Lyricist no
30614
+ 'LYRICS' Lyrics no
30615
+ 'MASTERED_BY' MasteredBy no
30616
+ 'MCDI' MCDI no
30617
+ 'MEASURE' Measure no
30618
+ 'MIXED_BY' MixedBy no
30619
+ 'MOOD' Mood no
30620
+ 'ORIGINAL' Original no
30621
+ 'ORIGINAL_MEDIA_TYPE' OriginalMediaType no
30622
+ 'PART_NUMBER' PartNumber no
30623
+ 'PART_OFFSET' PartOffset no
30624
+ 'PERIOD' Period no
30625
+ 'PHONE' Phone no
30626
+ 'PLAY_COUNTER' PlayCounter no
30627
+ 'PRODUCER' Producer no
30628
+ 'PRODUCTION_COPYRIGHT' ProductionCopyright no
30629
+ 'PRODUCTION_DESIGNER' ProductionDesigner no
30630
+ 'PRODUCTION_STUDIO' ProductionStudio no
30631
+ 'PUBLISHER' Publisher no
30632
+ 'PURCHASE_CURRENCY' PurchaseCurrency no
30633
+ 'PURCHASE_INFO' PurchaseInfo no
30634
+ 'PURCHASE_ITEM' PurchaseItem no
30635
+ 'PURCHASE_OWNER' PurchaseOwner no
30636
+ 'PURCHASE_PRICE' PurchasePrice no
30637
+ 'RATING' Rating no
30638
+ 'RECORDING_LOCATION' RecordingLocation no
30639
+ 'REMIXED_BY' RemixedBy no
30640
+ 'REPLAYGAIN_GAIN' ReplaygainGain no
30641
+ 'REPLAYGAIN_PEAK' ReplaygainPeak no
30642
+ 'SAMPLE' Sample no
30643
+ 'SCREENPLAY_BY' ScreenplayBy no
30644
+ 'SORT_WITH' SortWith no
30645
+ 'SOUND_ENGINEER' SoundEngineer no
30646
+ 'SUBJECT' Subject no
30647
+ 'SUBTITLE' Subtitle no
30648
+ 'SUMMARY' Summary no
30649
+ 'SYNOPSIS' Synopsis no
30650
+ 'TERMS_OF_USE' TermsOfUse no
30651
+ 'THANKS_TO' ThanksTo no
30652
+ 'TITLE' Title no
30653
+ 'TMDB' TMDB no
30654
+ 'TOTAL_PARTS' TotalParts no
30655
+ 'TUNING' Tuning no
30656
+ 'TVDB' TVDB no
30657
+ 'URL' URL no
30658
+ 'WRITTEN_BY' WrittenBy no
30659
+
30471
30660
  =head2 MOI Tags
30472
30661
 
30473
30662
  MOI files store information about associated MOD or TOD files, and are
@@ -37487,6 +37676,7 @@ FileName.
37487
37676
  ProcessingTime ExifTool no
37488
37677
  RAFVersion File no
37489
37678
  ResourceForkSize System no
37679
+ SphericalVideoXML GSpherical yes!
37490
37680
  SymLink - yes!
37491
37681
  TestName - yes!
37492
37682
  ThumbnailImage File no
@@ -306,14 +306,17 @@ sub CheckQTValue($$$)
306
306
 
307
307
  #------------------------------------------------------------------------------
308
308
  # Format QuickTime value for writing
309
- # Inputs: 0) ExifTool ref, 1) value ref, 2) Format (or undef), 3) Writable (or undef)
310
- # Returns: Flags for QT data type, and reformats value as required
309
+ # Inputs: 0) ExifTool ref, 1) value ref, 2) tagInfo ref, 3) Format (or undef)
310
+ # Returns: Flags for QT data type, and reformats value as required (sets to undef on error)
311
311
  sub FormatQTValue($$;$$)
312
312
  {
313
- my ($et, $valPt, $format, $writable) = @_;
313
+ my ($et, $valPt, $tagInfo, $format) = @_;
314
+ my $writable = $$tagInfo{Writable};
315
+ my $count = $$tagInfo{Count};
314
316
  my $flags;
317
+ $format or $format = $$tagInfo{Format};
315
318
  if ($format and $format ne 'string' or not $format and $writable and $writable ne 'string') {
316
- $$valPt = WriteValue($$valPt, $format || $writable);
319
+ $$valPt = WriteValue($$valPt, $format || $writable, $count);
317
320
  if ($writable and $qtFormat{$writable}) {
318
321
  $flags = $qtFormat{$writable};
319
322
  } else {
@@ -329,6 +332,7 @@ sub FormatQTValue($$;$$)
329
332
  $flags = 0x01; # UTF8
330
333
  $$valPt = $et->Encode($$valPt, 'UTF8');
331
334
  }
335
+ defined $$valPt or $et->WarnOnce("Error converting value for $$tagInfo{Name}");
332
336
  return $flags;
333
337
  }
334
338
 
@@ -1139,7 +1143,7 @@ sub WriteQuickTime($$$)
1139
1143
  my $newVal = $et->GetNewValue($nvHash);
1140
1144
  next unless defined $newVal;
1141
1145
  my $prVal = $newVal;
1142
- my $flags = FormatQTValue($et, \$newVal, $format, $$tagInfo{Writable});
1146
+ my $flags = FormatQTValue($et, \$newVal, $tagInfo, $format);
1143
1147
  next unless defined $newVal;
1144
1148
  my ($ctry, $lang) = (0, 0);
1145
1149
  if ($$ti{LangCode}) {
@@ -1220,7 +1224,8 @@ sub WriteQuickTime($$$)
1220
1224
  }
1221
1225
  my $prVal = $newVal;
1222
1226
  # format new value for writing (and get new flags)
1223
- $flags = FormatQTValue($et, \$newVal, $format, $$tagInfo{Writable});
1227
+ $flags = FormatQTValue($et, \$newVal, $tagInfo, $format);
1228
+ next unless defined $newVal;
1224
1229
  my $grp = $et->GetGroup($langInfo, 1);
1225
1230
  $et->VerboseValue("- $grp:$$langInfo{Name}", $val);
1226
1231
  $et->VerboseValue("+ $grp:$$langInfo{Name}", $prVal);
@@ -1463,7 +1468,7 @@ sub WriteQuickTime($$$)
1463
1468
  my $newVal = $et->GetNewValue($nvHash);
1464
1469
  next unless defined $newVal;
1465
1470
  my $prVal = $newVal;
1466
- my $flags = FormatQTValue($et, \$newVal, $$tagInfo{Format}, $$tagInfo{Writable});
1471
+ my $flags = FormatQTValue($et, \$newVal, $tagInfo);
1467
1472
  next unless defined $newVal;
1468
1473
  my ($ctry, $lang) = (0, 0);
1469
1474
  # handle alternate languages
@@ -561,7 +561,21 @@ sub AddStructType($$$$;$)
561
561
  }
562
562
 
563
563
  #------------------------------------------------------------------------------
564
- # Hack to use XMP writer for SphericalVideoXML
564
+ # Process SphericalVideoXML (see XMP-GSpherical tags documentation)
565
+ # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
566
+ # Returns: SphericalVideoXML data
567
+ sub ProcessGSpherical($$$)
568
+ {
569
+ my ($et, $dirInfo, $tagTablePtr) = @_;
570
+ # extract SphericalVideoXML as a block if requested
571
+ if ($$et{REQ_TAG_LOOKUP}{sphericalvideoxml}) {
572
+ $et->FoundTag(SphericalVideoXML => substr(${$$dirInfo{DataPt}}, 16));
573
+ }
574
+ return Image::ExifTool::XMP::ProcessXMP($et, $dirInfo, $tagTablePtr);
575
+ }
576
+
577
+ #------------------------------------------------------------------------------
578
+ # Hack to use XMP writer for SphericalVideoXML (see XMP-GSpherical tags documentation)
565
579
  # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
566
580
  # Returns: SphericalVideoXML data
567
581
  sub WriteGSpherical($$$)
@@ -707,9 +707,13 @@ TAG: foreach $tagInfo (@matchingTags) {
707
707
  $writeGroup or $writeGroup = $group0;
708
708
  # get priority for this group
709
709
  unless ($priority) {
710
- $priority = $$self{WRITE_PRIORITY}{lc($writeGroup)};
711
- unless ($priority) {
712
- $priority = $$self{WRITE_PRIORITY}{lc($group0)} || 0;
710
+ if ($$tagInfo{Avoid} and $$tagInfo{WriteAlso}) {
711
+ $priority = 0;
712
+ } else {
713
+ $priority = $$self{WRITE_PRIORITY}{lc($writeGroup)};
714
+ unless ($priority) {
715
+ $priority = $$self{WRITE_PRIORITY}{lc($group0)} || 0;
716
+ }
713
717
  }
714
718
  }
715
719
  # adjust priority based on Preferred level for this tag
@@ -830,6 +834,8 @@ TAG: foreach $tagInfo (@matchingTags) {
830
834
  $tag = $$tagInfo{Name}; # get tag name for warnings
831
835
  my $lcTag = lc $tag;
832
836
  my $pref = $preferred{$lcTag} || { };
837
+ # don't write Avoid-ed tags with side effect unless preferred
838
+ next if not $$pref{$tagInfo} and $$tagInfo{Avoid} and $$tagInfo{WriteAlso};
833
839
  my $shift = $options{Shift};
834
840
  my $addValue = $options{AddValue};
835
841
  if (defined $shift) {
@@ -971,6 +977,7 @@ TAG: foreach $tagInfo (@matchingTags) {
971
977
  $self->GetNewValueHash($tagInfo, $writeGroup, 'delete', $options{ProtectSaved});
972
978
  # also delete related tag previous new values
973
979
  if ($$tagInfo{WriteAlso}) {
980
+ $$self{INDENT2} = '+';
974
981
  my ($wgrp, $wtag);
975
982
  if ($$tagInfo{WriteGroup} and $$tagInfo{WriteGroup} eq 'All' and $writeGroup) {
976
983
  $wgrp = $writeGroup . ':';
@@ -981,6 +988,7 @@ TAG: foreach $tagInfo (@matchingTags) {
981
988
  my ($n,$e) = $self->SetNewValue($wgrp . $wtag, undef, Replace=>2);
982
989
  $numSet += $n;
983
990
  }
991
+ $$self{INDENT2} = '';
984
992
  }
985
993
  $options{Replace} == 2 and ++$numSet, next;
986
994
  }
@@ -1022,7 +1030,7 @@ TAG: foreach $tagInfo (@matchingTags) {
1022
1030
  require 'Image/ExifTool/XMPStruct.pl';
1023
1031
  $_ = Image::ExifTool::XMP::SerializeStruct($_);
1024
1032
  }
1025
- print $out "$verb $wgrp1:$tag$fromList if value is '${_}'\n";
1033
+ print $out "$$self{INDENT2}$verb $wgrp1:$tag$fromList if value is '${_}'\n";
1026
1034
  }
1027
1035
  }
1028
1036
  }
@@ -1086,15 +1094,25 @@ TAG: foreach $tagInfo (@matchingTags) {
1086
1094
  push @{$$nvHash{Value}}, ref $val eq 'ARRAY' ? @$val : $val;
1087
1095
  }
1088
1096
  if ($verbose > 1) {
1089
- my $ifExists = $$nvHash{IsCreating} ? ( $createOnly ?
1090
- ($$nvHash{IsCreating} == 2 ?
1091
- " if $writeGroup exists and tag doesn't" :
1092
- " if tag doesn't exist") :
1093
- ($$nvHash{IsCreating} == 2 ? " if $writeGroup exists" : '')) :
1097
+ my $ifExists;
1098
+ if ($$tagInfo{IsComposite}) {
1099
+ # (composite tags don't technically exist in the file)
1100
+ if ($$tagInfo{WriteAlso}) {
1101
+ $ifExists = ' (+' . join(',+',sort keys %{$$tagInfo{WriteAlso}}) . '):';
1102
+ } else {
1103
+ $ifExists = '';
1104
+ }
1105
+ } else {
1106
+ $ifExists = $$nvHash{IsCreating} ? ( $createOnly ?
1107
+ ($$nvHash{IsCreating} == 2 ?
1108
+ " if $writeGroup exists and tag doesn't" :
1109
+ " if tag doesn't exist") :
1110
+ ($$nvHash{IsCreating} == 2 ? " if $writeGroup exists" : '')) :
1094
1111
  (($$nvHash{DelValue} and @{$$nvHash{DelValue}}) ?
1095
- ' if tag was deleted' : ' if tag exists');
1112
+ ' if tag was deleted' : ' if tag exists');
1113
+ }
1096
1114
  my $verb = ($shift ? 'Shifting' : ($addValue ? 'Adding' : 'Writing'));
1097
- print $out "$verb $wgrp1:$tag$ifExists\n";
1115
+ print $out "$$self{INDENT2}$verb $wgrp1:$tag$ifExists\n";
1098
1116
  }
1099
1117
  }
1100
1118
  } elsif ($permanent) {
@@ -1109,7 +1127,7 @@ TAG: foreach $tagInfo (@matchingTags) {
1109
1127
  $self->GetNewValueHash($tagInfo, $writeGroup, 'delete');
1110
1128
  my $nvHash = $self->GetNewValueHash($tagInfo, $writeGroup, 'create');
1111
1129
  $$nvHash{WantGroup} = $wantGroup;
1112
- $verbose > 1 and print $out "Deleting $wgrp1:$tag\n";
1130
+ $verbose > 1 and print $out "$$self{INDENT2}Deleting $wgrp1:$tag\n";
1113
1131
  }
1114
1132
  $$setTags{$tagInfo} = 1 if $setTags;
1115
1133
  $prioritySet = 1 if $$pref{$tagInfo};
@@ -1118,6 +1136,7 @@ WriteAlso:
1118
1136
  # also write related tags
1119
1137
  my $writeAlso = $$tagInfo{WriteAlso};
1120
1138
  if ($writeAlso) {
1139
+ $$self{INDENT2} = '+'; # indicate related tag with a leading "+"
1121
1140
  my ($wgrp, $wtag, $n);
1122
1141
  if ($$tagInfo{WriteGroup} and $$tagInfo{WriteGroup} eq 'All' and $writeGroup) {
1123
1142
  $wgrp = $writeGroup . ':';
@@ -1137,7 +1156,7 @@ WriteAlso:
1137
1156
  SetTags => \%alsoWrote, # remember tags already written
1138
1157
  );
1139
1158
  undef $evalWarning;
1140
- #### eval WriteAlso ($val)
1159
+ #### eval WriteAlso ($val,%opts)
1141
1160
  my $v = eval $$writeAlso{$wtag};
1142
1161
  # we wanted to do the eval in case there are side effect, but we
1143
1162
  # don't want to write a value for a tag that is being deleted:
@@ -1159,6 +1178,7 @@ WriteAlso:
1159
1178
  }
1160
1179
  }
1161
1180
  }
1181
+ $$self{INDENT2} = '';
1162
1182
  }
1163
1183
  }
1164
1184
  # print warning if we couldn't set our priority tag
@@ -19,7 +19,7 @@ use strict;
19
19
  use vars qw($VERSION $warnString);
20
20
  use Image::ExifTool qw(:DataAccess :Utils);
21
21
 
22
- $VERSION = '1.27';
22
+ $VERSION = '1.28';
23
23
 
24
24
  sub WarnProc($) { $warnString = $_[0]; }
25
25
 
@@ -385,6 +385,18 @@ sub HandleMember($$;$)
385
385
  $et->HandleTag($tagTablePtr, '_com', $com) if defined $com and length $com;
386
386
  }
387
387
 
388
+ #------------------------------------------------------------------------------
389
+ # Extract file from ZIP archive
390
+ # Inputs: 0) ExifTool ref, 1) Zip object ref, 2) file name
391
+ # Returns: zip member or undef it it didn't exist
392
+ sub ExtractFile($$$)
393
+ {
394
+ my ($et, $zip, $file) = @_;
395
+ my $result = $zip->memberNamed($file);
396
+ $et->VPrint(1, " (Extracting '${file}' from zip archive)\n");
397
+ return $result;
398
+ }
399
+
388
400
  #------------------------------------------------------------------------------
389
401
  # Extract information from a ZIP file
390
402
  # Inputs: 0) ExifTool object reference, 1) dirInfo reference
@@ -460,7 +472,7 @@ sub ProcessZIP($$)
460
472
  # check for an Office Open file (DOCX, etc)
461
473
  # --> read '[Content_Types].xml' to determine the file type
462
474
  my ($mime, @members);
463
- my $cType = $zip->memberNamed('[Content_Types].xml');
475
+ my $cType = ExtractFile($et, $zip, '[Content_Types].xml');
464
476
  if ($cType) {
465
477
  ($buff, $status) = $zip->contents($cType);
466
478
  if (not $status and (
@@ -501,7 +513,7 @@ sub ProcessZIP($$)
501
513
  }
502
514
 
503
515
  # check for an Open Document, IDML or EPUB file
504
- my $mType = $zip->memberNamed('mimetype');
516
+ my $mType = ExtractFile($et, $zip, 'mimetype');
505
517
  if ($mType) {
506
518
  ($mime, $status) = $zip->contents($mType);
507
519
  if (not $status and $mime =~ /([\x21-\xfe]+)/s) {
@@ -510,9 +522,9 @@ sub ProcessZIP($$)
510
522
  $et->SetFileType($openDocType{$mime} || 'ZIP', $mime);
511
523
  $et->Warn("Unrecognized MIMEType $mime") unless $openDocType{$mime};
512
524
  # extract Open Document metadata from "meta.xml"
513
- my $meta = $zip->memberNamed('meta.xml');
525
+ my $meta = ExtractFile($et, $zip, 'meta.xml');
514
526
  # IDML files have metadata in a different place (ref 6)
515
- $meta or $meta = $zip->memberNamed('META-INF/metadata.xml');
527
+ $meta or $meta = ExtractFile($et, $zip, 'META-INF/metadata.xml');
516
528
  if ($meta) {
517
529
  ($buff, $status) = $zip->contents($meta);
518
530
  unless ($status) {
@@ -532,7 +544,7 @@ sub ProcessZIP($$)
532
544
  # process rootfile of EPUB container if applicable
533
545
  for (;;) {
534
546
  last if $meta and $mime ne 'application/epub+zip';
535
- my $container = $zip->memberNamed('META-INF/container.xml');
547
+ my $container = ExtractFile($et, $zip, 'META-INF/container.xml');
536
548
  ($buff, $status) = $zip->contents($container);
537
549
  last if $status;
538
550
  $buff =~ /<rootfile\s+[^>]*?\bfull-path=(['"])(.*?)\1/s or last;
@@ -570,7 +582,7 @@ sub ProcessZIP($$)
570
582
  my $type;
571
583
  my %tag = ( jpg => 'PreviewImage', png => 'PreviewPNG' );
572
584
  foreach $type ('jpg', 'png') {
573
- my $thumb = $zip->memberNamed("Thumbnails/thumbnail.$type");
585
+ my $thumb = ExtractFile($et, $zip, "Thumbnails/thumbnail.$type");
574
586
  next unless $thumb;
575
587
  ($buff, $status) = $zip->contents($thumb);
576
588
  $et->FoundTag($tag{$type}, $buff) unless $status;