exiftool-vendored.exe 12.97.0 → 13.0.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.
Files changed (29) hide show
  1. package/bin/exiftool_files/exiftool.pl +221 -41
  2. package/bin/exiftool_files/lib/File/RandomAccess.pm +5 -2
  3. package/bin/exiftool_files/lib/Image/ExifTool/APP12.pm +3 -2
  4. package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +2 -1
  5. package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +1 -1
  6. package/bin/exiftool_files/lib/Image/ExifTool/Geolocation.dat +0 -0
  7. package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +4 -3
  8. package/bin/exiftool_files/lib/Image/ExifTool/Import.pm +7 -3
  9. package/bin/exiftool_files/lib/Image/ExifTool/InDesign.pm +4 -3
  10. package/bin/exiftool_files/lib/Image/ExifTool/JSON.pm +3 -4
  11. package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +2 -1
  12. package/bin/exiftool_files/lib/Image/ExifTool/Lytro.pm +2 -2
  13. package/bin/exiftool_files/lib/Image/ExifTool/M2TS.pm +10 -2
  14. package/bin/exiftool_files/lib/Image/ExifTool/PhaseOne.pm +2 -1
  15. package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +17 -6
  16. package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +88 -9
  17. package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +6 -1
  18. package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +14 -9
  19. package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +40 -23
  20. package/bin/exiftool_files/lib/Image/ExifTool/WritePDF.pl +47 -21
  21. package/bin/exiftool_files/lib/Image/ExifTool/WriteXMP.pl +16 -4
  22. package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +16 -6
  23. package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +19 -4
  24. package/bin/exiftool_files/lib/Image/ExifTool/XMPStruct.pl +15 -7
  25. package/bin/exiftool_files/lib/Image/ExifTool.pm +37 -12
  26. package/bin/exiftool_files/lib/Image/ExifTool.pod +31 -8
  27. package/bin/exiftool_files/readme_windows.txt +8 -13
  28. package/bin/exiftool_files/windows_exiftool.txt +32 -10
  29. package/package.json +7 -7
@@ -184,11 +184,19 @@ sub GetFreeEntries($)
184
184
  {
185
185
  my $dict = shift;
186
186
  my %xrefFree;
187
- # from the start we have only written xref stream entries in 'CNn' format,
188
- # so we can simplify things for now and only support this type of entry
187
+ # we write xref stream entries in 'CNn' or 'CNNn' format (with 8-byte 'NN' offset),
189
188
  my $w = $$dict{W};
190
- if (ref $w eq 'ARRAY' and "@$w" eq '1 4 2') {
191
- my $size = $$dict{_entry_size}; # this will be 7 for 'CNn'
189
+ if (ref $w eq 'ARRAY') {
190
+ my $bytes = "@$w";
191
+ my $fmt;
192
+ if ($bytes eq '1 4 2') {
193
+ $fmt = 'CNn';
194
+ } elsif ($bytes eq '1 8 2') {
195
+ $fmt = 'CNNn';
196
+ } else {
197
+ return \%xrefFree;
198
+ }
199
+ my $size = $$dict{_entry_size}; # this will be 7 for 'CNn' or 11 for 'CNNn'
192
200
  my $index = $$dict{Index};
193
201
  my $len = length $$dict{_stream};
194
202
  # scan the table for free objects
@@ -200,7 +208,12 @@ sub GetFreeEntries($)
200
208
  my $count = $$index[$i*2+1];
201
209
  for ($j=0; $j<$count; ++$j) {
202
210
  last if $pos + $size > $len;
203
- my @t = unpack("x$pos CNn", $$dict{_stream});
211
+ my @t = unpack("x$pos $fmt", $$dict{_stream});
212
+ if (@t == 4) {
213
+ $t[1] = $t[1] * 4294967296 + $t[2];
214
+ $t[2] = $t[3];
215
+ @t = 3;
216
+ }
204
217
  # add entry if object was free
205
218
  $xrefFree{$start+$j} = [ $t[1], $t[2], 'f' ] if $t[0] == 0;
206
219
  $pos += $size; # step to next entry
@@ -657,24 +670,37 @@ sub WritePDF($$)
657
670
  $newXRef{$nextObject++} = [ Tell($outfile) - $$et{PDFBase} + length($/), 0, 'n' ];
658
671
  $$mainDict{Size} = $nextObject;
659
672
  # create xref stream and Index entry
660
- $$mainDict{W} = [ 1, 4, 2 ]; # int8u, int32u, int16u ('CNn')
661
- $$mainDict{Index} = [ ];
662
- $$mainDict{_stream} = '';
663
- my @ids = sort { $a <=> $b } keys %newXRef;
664
- while (@ids) {
665
- my $startID = $ids[0];
666
- for (;;) {
667
- $id = shift @ids;
668
- my ($pos, $gen, $type) = @{$newXRef{$id}};
669
- if ($pos > 0xffffffff) {
670
- $et->Error('Huge files not yet supported');
671
- last;
673
+ my $bits = 4;
674
+ Restart: for (;;) {
675
+ $$mainDict{W} = [ 1, $bits, 2 ]; # int8u, int32u/int64u, int16u ('CNn' or 'CNNn')
676
+ $$mainDict{Index} = [ ];
677
+ $$mainDict{_stream} = '';
678
+ my @ids = sort { $a <=> $b } keys %newXRef;
679
+ while (@ids) {
680
+ my $startID = $ids[0];
681
+ for (;;) {
682
+ $id = shift @ids;
683
+ my ($pos, $gen, $type) = @{$newXRef{$id}};
684
+ if ($pos > 0xffffffff) {
685
+ if ($bits == 4) {
686
+ # switch to 64-bit integer offsets
687
+ $bits = 8;
688
+ next Restart;
689
+ }
690
+ }
691
+ if ($bits == 4) {
692
+ $$mainDict{_stream} .= pack('CNn', $type eq 'f' ? 0 : 1, $pos, $gen);
693
+ } else {
694
+ my $hi = int($pos / 4294967296);
695
+ my $lo = $pos - $hi * 4294967296;
696
+ $$mainDict{_stream} .= pack('CNNn', $type eq 'f' ? 0 : 1, $hi, $lo, $gen);
697
+ }
698
+ last if not @ids or $ids[0] != $id + 1;
672
699
  }
673
- $$mainDict{_stream} .= pack('CNn', $type eq 'f' ? 0 : 1, $pos, $gen);
674
- last if not @ids or $ids[0] != $id + 1;
700
+ # add Index entries for this section of the xref stream
701
+ push @{$$mainDict{Index}}, $startID, $id - $startID + 1;
675
702
  }
676
- # add Index entries for this section of the xref stream
677
- push @{$$mainDict{Index}}, $startID, $id - $startID + 1;
703
+ last;
678
704
  }
679
705
  # write the xref stream object
680
706
  $keyExt = "$id 0 obj"; # (set anyway, but xref stream should NOT be encrypted)
@@ -925,19 +925,31 @@ sub WriteXMP($$;$)
925
925
  # get hash of all information we want to change
926
926
  # (sorted by tag name so alternate languages come last, but with structures
927
927
  # first so flattened tags may be used to override individual structure elements)
928
- my (@tagInfoList, $delLangPath, %delLangPaths, %delAllLang, $firstNewPath);
928
+ my (@tagInfoList, @structList, $delLangPath, %delLangPaths, %delAllLang, $firstNewPath, @langTags);
929
929
  my $writeGroup = $$dirInfo{WriteGroup};
930
930
  foreach $tagInfo (sort ByTagName $et->GetNewTagInfoList()) {
931
931
  next unless $et->GetGroup($tagInfo, 0) eq 'XMP';
932
932
  next if $$tagInfo{Name} eq 'XMP'; # (ignore full XMP block if we didn't write it already)
933
933
  next if $writeGroup and $writeGroup ne $$et{NEW_VALUE}{$tagInfo}{WriteGroup};
934
- if ($$tagInfo{Struct}) {
935
- unshift @tagInfoList, $tagInfo;
934
+ if ($$tagInfo{LangCode}) {
935
+ push @langTags, $tagInfo
936
+ } elsif ($$tagInfo{Struct}) {
937
+ push @structList, $tagInfo;
936
938
  } else {
937
939
  push @tagInfoList, $tagInfo;
938
940
  }
939
941
  }
940
- foreach $tagInfo (@tagInfoList) {
942
+ if (@langTags) {
943
+ # keep original order in which lang-alt entries were added
944
+ foreach $tagInfo (sort { $$et{NEW_VALUE}{$a}{Order} <=> $$et{NEW_VALUE}{$b}{Order} } @langTags) {
945
+ if ($$tagInfo{Struct}) {
946
+ push @structList, $tagInfo;
947
+ } else {
948
+ push @tagInfoList, $tagInfo;
949
+ }
950
+ }
951
+ }
952
+ foreach $tagInfo (@structList, @tagInfoList) {
941
953
  my @delPaths; # list of deleted paths
942
954
  my $tag = $$tagInfo{TagID};
943
955
  my $path = GetPropertyPath($tagInfo);
@@ -295,10 +295,11 @@ my %ignorePrintConv = map { $_ => 1 } qw(OTHER BITMASK Notes);
295
295
  # CreateGroups - hash of all family 0 group names where tag may be created
296
296
  # WriteGroup - group name where information is being written (correct case)
297
297
  # WantGroup - group name as specified in call to function (case insensitive)
298
- # Next - pointer to next new value hash (if more than one)
298
+ # Next - pointer to next new value hash (if more than one for this tag)
299
299
  # NoReplace - set if value was created with Replace=0
300
300
  # AddBefore - number of list items added by a subsequent Replace=0 call
301
- # IsNVH - Flag indicating this is a new value hash
301
+ # IsNVH - flag indicating this is a new value hash
302
+ # Order - counter to indicate the order that new value hashes were created
302
303
  # Shift - shift value
303
304
  # Save - counter used by SaveNewValues()/RestoreNewValues()
304
305
  # MAKER_NOTE_FIXUP - pointer to fixup if necessary for a maker note value
@@ -317,7 +318,7 @@ sub SetNewValue($;$$%)
317
318
 
318
319
  unless (defined $tag) {
319
320
  delete $$self{NEW_VALUE};
320
- $$self{SAVE_COUNT} = 0;
321
+ $$self{SAVE_COUNT} = $$self{NV_COUNT} = 0;
321
322
  $$self{DEL_GROUP} = { };
322
323
  return 1;
323
324
  }
@@ -1389,8 +1390,16 @@ sub SetNewValuesFromFile($$;@)
1389
1390
  return $info if $$info{Error} and $$info{Error} eq 'Error opening file';
1390
1391
  delete $$srcExifTool{VALUE}{Error}; # delete so we can check this later
1391
1392
 
1392
- # sort tags in reverse order so we get priority tag last
1393
- my @tags = reverse sort keys %$info;
1393
+ # sort tags in file order with priority tags last
1394
+ my (@tags, @prio);
1395
+ foreach (sort { $$srcExifTool{FILE_ORDER}{$a} <=> $$srcExifTool{FILE_ORDER}{$b} } keys %$info) {
1396
+ if (/ /) {
1397
+ push @tags, $_;
1398
+ } else {
1399
+ push @prio, $_;
1400
+ }
1401
+ }
1402
+ push @tags, @prio;
1394
1403
  #
1395
1404
  # simply transfer all tags from source image if no tags specified
1396
1405
  #
@@ -3896,6 +3905,7 @@ sub GetNewValueHash($$;$$$$)
3896
3905
  TagInfo => $tagInfo,
3897
3906
  WriteGroup => $writeGroup,
3898
3907
  IsNVH => 1, # set flag so we can recognize a new value hash
3908
+ Order => $$self{NV_COUNT}++,
3899
3909
  };
3900
3910
  # add entry to our NEW_VALUE hash
3901
3911
  if ($$self{NEW_VALUE}{$tagInfo}) {
@@ -4023,7 +4033,7 @@ sub RemoveNewValuesForGroup($$)
4023
4033
  #------------------------------------------------------------------------------
4024
4034
  # Get list of tagInfo hashes for all new data
4025
4035
  # Inputs: 0) ExifTool object reference, 1) optional tag table pointer
4026
- # Returns: list of tagInfo hashes
4036
+ # Returns: list of tagInfo hashes in no particular order
4027
4037
  sub GetNewTagInfoList($;$)
4028
4038
  {
4029
4039
  my ($self, $tagTablePtr) = @_;
@@ -50,7 +50,7 @@ use Image::ExifTool::Exif;
50
50
  use Image::ExifTool::GPS;
51
51
  require Exporter;
52
52
 
53
- $VERSION = '3.66';
53
+ $VERSION = '3.67';
54
54
  @ISA = qw(Exporter);
55
55
  @EXPORT_OK = qw(EscapeXML UnescapeXML);
56
56
 
@@ -2016,6 +2016,7 @@ my %sPantryItem = (
2016
2016
  Writable => 'integer',
2017
2017
  List => 'Seq',
2018
2018
  AutoSplit => 1,
2019
+ Notes => 'deprecated',
2019
2020
  },
2020
2021
  OECF => {
2021
2022
  Name => 'Opto-ElectricConvFactor',
@@ -2267,7 +2268,7 @@ my %sPantryItem = (
2267
2268
  3 => 'Distant',
2268
2269
  },
2269
2270
  },
2270
- ImageUniqueID => { },
2271
+ ImageUniqueID => { Avoid => 1, Notes => 'moved to exifEX namespace in 2024 spec' },
2271
2272
  GPSVersionID => { Groups => { 2 => 'Location' } },
2272
2273
  GPSLatitude => { Groups => { 2 => 'Location' }, %latConv },
2273
2274
  GPSLongitude => { Groups => { 2 => 'Location' }, %longConv },
@@ -2509,6 +2510,15 @@ my %sPantryItem = (
2509
2510
  Values => { List => 'Seq', Writable => 'rational' },
2510
2511
  },
2511
2512
  },
2513
+ # new in Exif 3.0
2514
+ ImageUniqueID => { },
2515
+ ImageTitle => { },
2516
+ ImageEditor => { },
2517
+ Photographer => { Groups => { 2 => 'Author' } },
2518
+ CameraFirmware => { Groups => { 2 => 'Camera' } },
2519
+ RAWDevelopingSoftware => { },
2520
+ ImageEditingSoftware => { },
2521
+ MetadataEditingSoftware => { },
2512
2522
  );
2513
2523
 
2514
2524
  # Auxiliary namespace properties (aux) - not fully documented (ref PH)
@@ -3777,8 +3787,13 @@ sub ParseXMPElement($$$;$$$$)
3777
3787
 
3778
3788
  # extract property attributes
3779
3789
  my ($parseResource, %attrs, @attrs);
3780
- while ($attrs =~ m/(\S+?)\s*=\s*(['"])(.*?)\2/sg) {
3781
- my ($attr, $val) = ($1, $3);
3790
+ # this hangs Perl (v5.18.4) for a specific capture string [patched in ExifTool 12.98]
3791
+ # while ($attrs =~ m/(\S+?)\s*=\s*(['"])(.*?)\2/sg) {
3792
+ while ($attrs =~ /(\S+?)\s*=\s*(['"])/g) {
3793
+ my ($attr, $quote) = ($1, $2);
3794
+ my $p0 = pos($attrs);
3795
+ last unless $attrs =~ /$quote/g;
3796
+ my $val = substr($attrs, $p0, pos($attrs)-$p0-1);
3782
3797
  # handle namespace prefixes (defined by xmlns:PREFIX, or used with PREFIX:tag)
3783
3798
  if ($attr =~ /(.*?):/) {
3784
3799
  if ($1 eq 'xmlns') {
@@ -39,8 +39,7 @@ sub SerializeStruct($$;$)
39
39
 
40
40
  if (ref $obj eq 'HASH') {
41
41
  # support hashes with ordered keys
42
- my @keys = $$obj{_ordered_keys_} ? @{$$obj{_ordered_keys_}} : sort keys %$obj;
43
- foreach $key (@keys) {
42
+ foreach $key (Image::ExifTool::OrderedKeys($obj)) {
44
43
  my $hdr = $sfmt ? EscapeJSON($key) . ':' : $key . '=';
45
44
  push @vals, $hdr . SerializeStruct($et, $$obj{$key}, '}');
46
45
  }
@@ -218,7 +217,7 @@ sub DumpStruct($;$)
218
217
  $indent or $indent = '';
219
218
  if (ref $obj eq 'HASH') {
220
219
  print "{\n";
221
- foreach (sort keys %$obj) {
220
+ foreach (Image::ExifTool::OrderedKeys($obj)) {
222
221
  print "$indent $_ = ";
223
222
  DumpStruct($$obj{$_}, "$indent ");
224
223
  }
@@ -253,8 +252,10 @@ sub CheckStruct($$$)
253
252
  ref $struct eq 'HASH' or return wantarray ? (undef, "Expecting $strName structure") : undef;
254
253
 
255
254
  my ($key, $err, $warn, %copy, $rtnVal, $val);
255
+ # copy the ordered keys if they exist
256
+ $copy{_ordered_keys_} = [ ] if $$struct{_ordered_keys_};
256
257
  Key:
257
- foreach $key (keys %$struct) {
258
+ foreach $key (Image::ExifTool::OrderedKeys($struct)) {
258
259
  my $tag = $key;
259
260
  # allow trailing '#' to disable print conversion on a per-field basis
260
261
  my ($type, $fieldInfo);
@@ -377,6 +378,7 @@ Key:
377
378
  $copy{$tag} = \@copy;
378
379
  } elsif ($$fieldInfo{Struct}) {
379
380
  $warn = "Improperly formed structure in $strName $tag";
381
+ next;
380
382
  } else {
381
383
  $et->Sanitize(\$$struct{$key});
382
384
  ($val,$err) = $et->ConvInv($$struct{$key},$fieldInfo,$tag,$strName,$type,'');
@@ -387,6 +389,7 @@ Key:
387
389
  # turn this into a list if necessary
388
390
  $copy{$tag} = $$fieldInfo{List} ? [ $val ] : $val;
389
391
  }
392
+ push @{$copy{_ordered_keys_}}, $tag if $copy{_ordered_keys_}; # save ordered keys
390
393
  }
391
394
  if (%copy or not $warn) {
392
395
  $rtnVal = \%copy;
@@ -562,7 +565,7 @@ sub AddNewStruct($$$$$$)
562
565
  # after all valid structure fields, which is necessary when serializing the XMP later)
563
566
  %$struct or $$struct{'~dummy~'} = '';
564
567
 
565
- foreach $tag (sort keys %$struct) {
568
+ foreach $tag (Image::ExifTool::OrderedKeys($struct)) {
566
569
  my $fieldInfo = $$strTable{$tag};
567
570
  unless ($fieldInfo) {
568
571
  next unless $tag eq '~dummy~'; # check for dummy field
@@ -652,7 +655,8 @@ sub ConvertStruct($$$$;$)
652
655
  my (%struct, $key);
653
656
  my $table = $$tagInfo{Table};
654
657
  $parentID = $$tagInfo{TagID} unless $parentID;
655
- foreach $key (keys %$value) {
658
+ $struct{_ordered_keys_} = [ ] if $$value{_ordered_keys_};
659
+ foreach $key (Image::ExifTool::OrderedKeys($value)) {
656
660
  my $tagID = $parentID . ucfirst($key);
657
661
  my $flatInfo = $$table{$tagID};
658
662
  unless ($flatInfo) {
@@ -669,7 +673,11 @@ sub ConvertStruct($$$$;$)
669
673
  } else {
670
674
  $v = $et->GetValue($flatInfo, $type, $v);
671
675
  }
672
- $struct{$key} = $v if defined $v; # save the converted value
676
+ if (defined $v) {
677
+ $struct{$key} = $v; # save the converted value
678
+ # maintain ordered keys if necessary
679
+ push @{$struct{_ordered_keys_}}, $key if $struct{_ordered_keys_};
680
+ }
673
681
  }
674
682
  return \%struct;
675
683
  } elsif (ref $value eq 'ARRAY') {
@@ -29,7 +29,7 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes
29
29
  %jpegMarker %specialTags %fileTypeLookup $testLen $exeDir
30
30
  %static_vars $advFmtSelf);
31
31
 
32
- $VERSION = '12.97';
32
+ $VERSION = '13.00';
33
33
  $RELEASE = '';
34
34
  @ISA = qw(Exporter);
35
35
  %EXPORT_TAGS = (
@@ -37,7 +37,7 @@ $RELEASE = '';
37
37
  Public => [qw(
38
38
  ImageInfo AvailableOptions GetTagName GetShortcuts GetAllTags
39
39
  GetWritableTags GetAllGroups GetDeleteGroups GetFileType CanWrite
40
- CanCreate AddUserDefinedTags
40
+ CanCreate AddUserDefinedTags OrderedKeys
41
41
  )],
42
42
  # exports not part of the public API, but used by ExifTool modules:
43
43
  DataAccess => [qw(
@@ -740,7 +740,7 @@ my %fileDescription = (
740
740
  OGV => 'video/ogg',
741
741
  ONP => 'application/on1',
742
742
  ORF => 'image/x-olympus-orf',
743
- OTF => 'application/x-font-otf',
743
+ OTF => 'application/font-otf',
744
744
  PAGES=> 'application/x-iwork-pages-sffpages',
745
745
  PBM => 'image/x-portable-bitmap',
746
746
  PCD => 'image/x-photo-cd',
@@ -798,8 +798,8 @@ my %fileDescription = (
798
798
  THMX => 'application/vnd.ms-officetheme',
799
799
  TIFF => 'image/tiff',
800
800
  Torrent => 'application/x-bittorrent',
801
- TTC => 'application/x-font-ttf',
802
- TTF => 'application/x-font-ttf',
801
+ TTC => 'application/font-ttf',
802
+ TTF => 'application/font-ttf',
803
803
  TXT => 'text/plain',
804
804
  VCard=> 'text/vcard',
805
805
  VRD => 'application/octet-stream', #PH (NC)
@@ -1466,12 +1466,12 @@ my %systemTagsNotes = (
1466
1466
  PrintConv => sub {
1467
1467
  my ($mask, $val) = (0400, oct(shift));
1468
1468
  my %types = (
1469
- 0010000 => 'p',
1470
- 0020000 => 'c',
1471
- 0040000 => 'd',
1472
- 0060000 => 'b',
1473
- 0120000 => 'l',
1474
- 0140000 => 's',
1469
+ 0010000 => 'p', # FIFO
1470
+ 0020000 => 'c', # character special file
1471
+ 0040000 => 'd', # directory
1472
+ 0060000 => 'b', # block special file
1473
+ 0120000 => 'l', # sym link
1474
+ 0140000 => 's', # socket link
1475
1475
  );
1476
1476
  my $str = $types{$val & 0170000} || '-';
1477
1477
  while ($mask) {
@@ -2292,6 +2292,7 @@ sub new
2292
2292
  $$self{PATH} = [ ]; # (this too)
2293
2293
  $$self{DEL_GROUP} = { }; # lookup for groups to delete when writing
2294
2294
  $$self{SAVE_COUNT} = 0; # count calls to SaveNewValues()
2295
+ $$self{NV_COUNT} = 0; # count of NEW_VALUE entries
2295
2296
  $$self{FILE_SEQUENCE} = 0; # sequence number for files when reading
2296
2297
  $$self{FILES_WRITTEN} = 0; # count of files successfully written
2297
2298
  $$self{INDENT2} = ''; # indentation of verbose messages from SetNewValue
@@ -2517,6 +2518,8 @@ sub Options($$;@)
2517
2518
  # set Compact and XMPShorthand options, preserving backward compatibility
2518
2519
  my ($p, %compact);
2519
2520
  foreach $p ('Compact','XMPShorthand') {
2521
+ # (allow setting from a HASH (undocumented)
2522
+ ref $newVal eq 'HASH' and %compact = %{$newVal}, next;
2520
2523
  my $val = $param eq $p ? $newVal : $$options{Compact}{$p};
2521
2524
  if (defined $val) {
2522
2525
  my @v = ($val =~ /\w+/g);
@@ -4195,6 +4198,16 @@ sub CanCreate($)
4195
4198
  return 0;
4196
4199
  }
4197
4200
 
4201
+ #------------------------------------------------------------------------------
4202
+ # Return list of ordered keys if available, otherwise just sort alphabetically
4203
+ # Inputs: 0) hash ref
4204
+ # Returns: List of ordered/sorted keys
4205
+ sub OrderedKeys($)
4206
+ {
4207
+ my $hash = shift;
4208
+ return $$hash{_ordered_keys_} ? @{$$hash{_ordered_keys_}} : sort keys %$hash;
4209
+ }
4210
+
4198
4211
  #==============================================================================
4199
4212
  # Functions below this are not part of the public API
4200
4213
 
@@ -7290,7 +7303,10 @@ sub ProcessJPEG($$;$)
7290
7303
  last; # all done parsing file
7291
7304
  } elsif (defined $markerLenBytes{$marker}) {
7292
7305
  # handle other stand-alone markers and segments we skipped over
7293
- $verbose and $marker and print $out "${indent}JPEG $markerName\n";
7306
+ if ($verbose and $marker) {
7307
+ next if $verbose < 4 and ($marker & 0xf8) == 0xd0;
7308
+ print $out "${indent}JPEG $markerName\n";
7309
+ }
7294
7310
  next;
7295
7311
  } elsif ($marker == 0xdb and length($$segDataPt) and # DQT
7296
7312
  # save the DQT data only if JPEGDigest has been requested
@@ -7901,8 +7917,17 @@ sub ProcessJPEG($$;$)
7901
7917
  my $seq = Get32u($segDataPt, 4);
7902
7918
  my $len = Get32u($segDataPt, 8);
7903
7919
  my $type = substr($$segDataPt, 12, 4);
7920
+ # a Microsoft bug writes $len and $type incorrectly as little-endian
7921
+ if ($type eq 'bmuj') {
7922
+ $self->WarnOnce('Wrong byte order in C2PA APP11 JUMBF header');
7923
+ $type = 'jumb';
7924
+ $len = unpack('x8V', $$segDataPt);
7925
+ # fix the header
7926
+ substr($$segDataPt, 8, 8) = Set32u($len) . $type;
7927
+ }
7904
7928
  my $hdrLen;
7905
7929
  if ($len == 1 and length($$segDataPt) >= 24) {
7930
+ # (haven't seen this with the Microsoft bug)
7906
7931
  $len = Get64u($$segDataPt, 16);
7907
7932
  $hdrLen = 16;
7908
7933
  } else {
@@ -332,13 +332,14 @@ L</ImageInfo>:
332
332
 
333
333
  Values of the returned hash are usually simple scalars, but a scalar
334
334
  reference is used to indicate binary data and an array reference may be used
335
- to indicate a list. Also, a hash reference may be returned if the L</Struct>
336
- option is used. Lists of values are joined by commas into a single
337
- string only if the PrintConv option is enabled and the ListJoin option is
338
- enabled (which are the defaults). Note that binary values are not
339
- necessarily extracted unless specifically requested, or the Binary option is
340
- enabled and the tag is not specifically excluded. If not extracted the
341
- value is a reference to a string of the form "Binary data ##### bytes".
335
+ to indicate a list. Also, a hash reference may be returned if the
336
+ L</Struct> option is used (see the L</OrderedKeys> option to obtain the hash
337
+ keys). Lists of values are joined by commas into a single string only if
338
+ the PrintConv option is enabled and the ListJoin option is enabled (which
339
+ are the defaults). Note that binary values are not necessarily extracted
340
+ unless specifically requested, or the Binary option is enabled and the tag
341
+ is not specifically excluded. If not extracted the value is a reference to
342
+ a string of the form "Binary data ##### bytes".
342
343
 
343
344
  The code below gives an example of how to handle these return values, as
344
345
  well as illustrating the use of other ExifTool functions:
@@ -1089,7 +1090,9 @@ values in standard format).
1089
1090
 
1090
1091
  Flag to return XMP structures as hash references instead of flattening into
1091
1092
  individual tags. Has no effect when writing since both flattened and
1092
- structured tags may always be written. Possible values are:
1093
+ structured tags may always be written. A special "_ordered_keys_" element
1094
+ containing a list of ordered keys may exist if the structure elements are
1095
+ ordered (see the L<OrderedKeys> method). Possible values are:
1093
1096
 
1094
1097
  undef - (default) Same as 0 for reading, 2 for copying
1095
1098
  0 - Read/copy flattened tags
@@ -2749,6 +2752,26 @@ details on the elements of the tag information hash.
2749
2752
 
2750
2753
  =back
2751
2754
 
2755
+ =head2 OrderedKeys [static]
2756
+
2757
+ Return a list of ordered keys from a tag value that is a HASH reference
2758
+ when the Struct option is used.
2759
+
2760
+ use Image::ExifTool ':Public';
2761
+ my @keys = OrderedKeys($structRef);
2762
+
2763
+ =over 4
2764
+
2765
+ =item Inputs:
2766
+
2767
+ 0) Structure HASH reference
2768
+
2769
+ =item Return Value:
2770
+
2771
+ List of ordered keys, or sorted alphabetically if not ordered.
2772
+
2773
+ =back
2774
+
2752
2775
  =head1 CHARACTER ENCODINGS
2753
2776
 
2754
2777
  Certain meta information formats allow coded character sets other than plain
@@ -1,21 +1,16 @@
1
- This ExifTool package is intended to avoid problems of the PAR packed original ExifTool for Windows.
1
+ This readme is for the Windows ExifTool package by Oliver Betz.
2
+
3
+ This package is intended to avoid problems of the PAR packed original ExifTool for Windows.
2
4
 
3
5
  It consists of:
4
6
 
5
7
  * ExifTool by Phil Harvey https://exiftool.org/ resp. https://github.com/exiftool/exiftool
6
- * Strawberry Perl http://strawberryperl.com/
7
- * My tiny launcher https://oliverbetz.de/pages/Artikel/ExifTool-for-Windows
8
-
9
- Please note that there can be up to three exiftool scripts in the "exiftool_files" directory:
10
- * exiftool.pl - only this one is called by the launcher
11
- * exiftool - this is from the original ExifTool distribution
12
- * windows_exiftool - this is from the original ExifTool distribution
8
+ * Strawberry Perl https://strawberryperl.com/
9
+ * Tiny launcher by Oliver Betz https://oliverbetz.de/pages/Artikel/ExifTool-for-Windows
13
10
 
14
- The small proportion of my own content is licensed under the https://creativecommons.org/publicdomain/zero/1.0/legalcode CC0 license
15
- See https://exiftool.org/ and http://strawberryperl.com/ for the license of ExifTool and Strawberry Perl.
11
+ See https://exiftool.org/ and https://strawberryperl.com/ for the license of ExifTool and Strawberry Perl.
12
+ The launcher is licensed under the https://creativecommons.org/publicdomain/zero/1.0/legalcode CC0 license
16
13
 
17
14
  I make no warranties about the package, and disclaim liability for all uses of the package, to the fullest extent permitted by applicable law.
18
15
 
19
- Please send useful comments to mailto:ppl@oliverbetz.de - especially if you found bugs or improved something.
20
-
21
- Oliver Betz
16
+ Oliver Betz
@@ -222,6 +222,7 @@ OPTIONS
222
222
 
223
223
  Special features
224
224
 
225
+ -diff FILE2 Compare metadata with another file
225
226
  -geotag TRKFILE Geotag images from specified GPS log
226
227
  -globalTimeShift SHIFT Shift all formatted date/time values
227
228
  -use MODULE Add features from plug-in module
@@ -311,8 +312,8 @@ OPTIONS
311
312
  Write a new value for the specified tag (eg. "-comment=wow"), or
312
313
  delete the tag if no *VALUE* is given (eg. "-comment="). "+=" and
313
314
  "-=" are used to add or remove existing entries from a list, or to
314
- shift date/time values (see Image::ExifTool::Shift.pl and note 6
315
- below for more details). "+=" may also be used to increment
315
+ shift date/time values (see Image::ExifTool::Shift.pl and notes 6
316
+ and 7 below for more details). "+=" may also be used to increment
316
317
  numerical values (or decrement if *VALUE* is negative), and "-="
317
318
  may be used to conditionally delete or replace a tag (see "WRITING
318
319
  EXAMPLES" for examples). "^=" is used to write an empty string
@@ -398,6 +399,10 @@ OPTIONS
398
399
  copy it to another tag in the same operation, use the
399
400
  -globalTimeShift option.
400
401
 
402
+ 7) The "+=" operator may not be used to shift a List-type date/time
403
+ tag (eg. XMP-dc:Date) because "+=" is used to add elements to the
404
+ list. Instead, the -globalTimeShift option should be used.
405
+
401
406
  Special feature: Integer values may be specified in hexadecimal
402
407
  with a leading "0x", and simple rational values may be specified as
403
408
  fractions.
@@ -1034,7 +1039,7 @@ OPTIONS
1034
1039
 
1035
1040
  produces output like this:
1036
1041
 
1037
- -- Generated by ExifTool 12.97 --
1042
+ -- Generated by ExifTool 13.00 --
1038
1043
  File: a.jpg - 2003:10:31 15:44:19
1039
1044
  (f/5.6, 1/60s, ISO 100)
1040
1045
  File: b.jpg - 2006:05:23 11:57:38
@@ -1584,10 +1589,10 @@ OPTIONS
1584
1589
  the corresponding family 8 group name is specified for the tag. See
1585
1590
  the -fileNUM option details for more information.
1586
1591
 
1587
- 5) The -a option has no effect on the evaluation of the expression,
1588
- and the values of duplicate tags are accessible only by specifying
1589
- a group name (such as a family 4 instance number, eg. $Copy1:TAG,
1590
- $Copy2:TAG, etc).
1592
+ 5) The -a (Duplicates) option is implied when -if is used without a
1593
+ fast *NUM*, and the values of duplicate tags are accessible by
1594
+ specifying a group name in the expression (such as a family 4
1595
+ instance number, eg. $Copy1:TAG, $Copy2:TAG, etc).
1591
1596
 
1592
1597
  6) A special "OK" UserParam is available to test the success of the
1593
1598
  previous command when -execute was used, and may be used like any
@@ -1849,9 +1854,9 @@ OPTIONS
1849
1854
  The flags are formatted as a comma-separated list of the following
1850
1855
  possible values: Avoid, Binary, List, Mandatory, Permanent,
1851
1856
  Protected, Unknown and Unsafe (see the Tag Name documentation). For
1852
- XMP List tags, the list type (Alt, Bag or Seq) is added to the
1853
- flags, and flattened structure tags are indicated by a Flattened
1854
- flag with 'struct' giving the ID of the parent structure.
1857
+ XMP List tags, the list type (Alt, Bag or Seq) is also given, and
1858
+ flattened structure tags are indicated by a Flattened flag with
1859
+ 'struct' giving the ID of the parent structure.
1855
1860
 
1856
1861
  Note that none of the -list options require an input *FILE*.
1857
1862
 
@@ -1864,6 +1869,23 @@ OPTIONS
1864
1869
  as file names, even if they begin with a dash ("-").
1865
1870
 
1866
1871
  Special features
1872
+ -diff *FILE2*
1873
+ Compare metadata in *FILE* with *FILE2*. The *FILE2* name may
1874
+ include filename formatting codes (see the -w option). All
1875
+ extracted tags from the files are compared, but the extracted tags
1876
+ may be controlled by adding -TAG or --TAG options. For example,
1877
+ below is a command to compare all the same-named files in two
1878
+ different directories, ignoring the System tags:
1879
+
1880
+ exiftool DIR1 -diff DIR2/%f.%e --system:all
1881
+
1882
+ The -g and -G options may be used to organize the output by the
1883
+ specified family of groups, with -G1 being the default. The -a
1884
+ option is implied. Adding -v includes a count of the number of tags
1885
+ that are the same in each group. The following text formatting
1886
+ options are valid when -diff is used: -c, -charset, -d, -E, -ec,
1887
+ -ex, -L, -lang, -n, -s, -sep, -struct and -w.
1888
+
1867
1889
  -geotag *TRKFILE*
1868
1890
  Geotag images from the specified GPS track log file. Using the
1869
1891
  -geotag option is equivalent to writing a value to the "Geotag"
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "exiftool-vendored.exe",
3
- "version": "12.97.0",
3
+ "version": "13.0.0",
4
4
  "description": "Vendored win32 ExifTool for Node.js",
5
5
  "main": "./index.js",
6
- "homepage": "https://github.com/mceachen/exiftool-vendored.exe#readme",
6
+ "homepage": "https://github.com/photostructure/exiftool-vendored.exe#readme",
7
7
  "bugs": {
8
- "url": "https://github.com/mceachen/exiftool-vendored.js/issues"
8
+ "url": "https://github.com/photostructure/exiftool-vendored.js/issues"
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": "https://github.com/mceachen/exiftool-vendored.exe.git"
12
+ "url": "git+ssh://git@github.com/photostructure/exiftool-vendored.exe.git"
13
13
  },
14
14
  "os": [
15
15
  "win32"
@@ -43,10 +43,10 @@
43
43
  },
44
44
  "devDependencies": {
45
45
  "axios": "^1.7.7",
46
- "mocha": "^10.7.3",
47
- "npm-check-updates": "^17.1.3",
46
+ "mocha": "^10.8.0",
47
+ "npm-check-updates": "^17.1.9",
48
48
  "prettier": "^3.3.3",
49
- "release-it": "^17.7.0",
49
+ "release-it": "^17.10.0",
50
50
  "unzipper": "^0.12.3",
51
51
  "xml2js": "^0.6.2"
52
52
  }