exiftool_vendored 11.97.0 → 12.09.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of exiftool_vendored might be problematic. Click here for more details.

Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +196 -2
  3. data/bin/MANIFEST +8 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +43 -42
  7. data/bin/exiftool +150 -102
  8. data/bin/lib/Image/ExifTool.pm +162 -111
  9. data/bin/lib/Image/ExifTool.pod +123 -90
  10. data/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  11. data/bin/lib/Image/ExifTool/APE.pm +2 -2
  12. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +21 -10
  13. data/bin/lib/Image/ExifTool/Canon.pm +201 -14
  14. data/bin/lib/Image/ExifTool/CanonCustom.pm +82 -16
  15. data/bin/lib/Image/ExifTool/DPX.pm +56 -2
  16. data/bin/lib/Image/ExifTool/DarwinCore.pm +22 -3
  17. data/bin/lib/Image/ExifTool/EXE.pm +8 -5
  18. data/bin/lib/Image/ExifTool/Exif.pm +15 -6
  19. data/bin/lib/Image/ExifTool/Font.pm +9 -2
  20. data/bin/lib/Image/ExifTool/GIF.pm +6 -1
  21. data/bin/lib/Image/ExifTool/GeoTiff.pm +2 -0
  22. data/bin/lib/Image/ExifTool/Geotag.pm +2 -2
  23. data/bin/lib/Image/ExifTool/GoPro.pm +48 -22
  24. data/bin/lib/Image/ExifTool/H264.pm +1 -1
  25. data/bin/lib/Image/ExifTool/HtmlDump.pm +2 -2
  26. data/bin/lib/Image/ExifTool/ID3.pm +91 -12
  27. data/bin/lib/Image/ExifTool/IPTC.pm +1 -0
  28. data/bin/lib/Image/ExifTool/JSON.pm +27 -4
  29. data/bin/lib/Image/ExifTool/Lang/de.pm +3 -1
  30. data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
  31. data/bin/lib/Image/ExifTool/M2TS.pm +44 -24
  32. data/bin/lib/Image/ExifTool/MacOS.pm +152 -38
  33. data/bin/lib/Image/ExifTool/Matroska.pm +3 -1
  34. data/bin/lib/Image/ExifTool/Minolta.pm +7 -2
  35. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +11 -10
  36. data/bin/lib/Image/ExifTool/Nikon.pm +163 -18
  37. data/bin/lib/Image/ExifTool/Olympus.pm +39 -17
  38. data/bin/lib/Image/ExifTool/PNG.pm +14 -3
  39. data/bin/lib/Image/ExifTool/PPM.pm +5 -5
  40. data/bin/lib/Image/ExifTool/Panasonic.pm +148 -14
  41. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +34 -0
  42. data/bin/lib/Image/ExifTool/Parrot.pm +2 -1
  43. data/bin/lib/Image/ExifTool/Pentax.pm +3 -1
  44. data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
  45. data/bin/lib/Image/ExifTool/QuickTime.pm +294 -34
  46. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +419 -60
  47. data/bin/lib/Image/ExifTool/README +26 -22
  48. data/bin/lib/Image/ExifTool/RIFF.pm +15 -3
  49. data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
  50. data/bin/lib/Image/ExifTool/RTF.pm +12 -7
  51. data/bin/lib/Image/ExifTool/Radiance.pm +7 -2
  52. data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
  53. data/bin/lib/Image/ExifTool/Shift.pl +1 -0
  54. data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
  55. data/bin/lib/Image/ExifTool/Sony.pm +420 -34
  56. data/bin/lib/Image/ExifTool/TagLookup.pm +5799 -5671
  57. data/bin/lib/Image/ExifTool/TagNames.pod +583 -95
  58. data/bin/lib/Image/ExifTool/Validate.pm +4 -4
  59. data/bin/lib/Image/ExifTool/WriteExif.pl +3 -2
  60. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +26 -18
  61. data/bin/lib/Image/ExifTool/Writer.pl +44 -21
  62. data/bin/lib/Image/ExifTool/XMP.pm +99 -17
  63. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  64. data/bin/lib/Image/ExifTool/ZISRAW.pm +123 -0
  65. data/bin/perl-Image-ExifTool.spec +42 -41
  66. data/lib/exiftool_vendored/version.rb +1 -1
  67. metadata +8 -7
@@ -28,7 +28,7 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes
28
28
  %mimeType $swapBytes $swapWords $currentByteOrder %unpackStd
29
29
  %jpegMarker %specialTags %fileTypeLookup $testLen $exePath);
30
30
 
31
- $VERSION = '11.97';
31
+ $VERSION = '12.09';
32
32
  $RELEASE = '';
33
33
  @ISA = qw(Exporter);
34
34
  %EXPORT_TAGS = (
@@ -91,7 +91,7 @@ sub GetExtended($$);
91
91
  sub Set64u(@);
92
92
  sub DecodeBits($$;$);
93
93
  sub EncodeBits($$;$$);
94
- sub Filter($$@);
94
+ sub Filter($$$);
95
95
  sub HexDump($;$%);
96
96
  sub DumpTrailer($$);
97
97
  sub DumpUnknownTrailer($$);
@@ -137,17 +137,18 @@ sub ReadValue($$$;$$$);
137
137
  @loadAllTables = qw(
138
138
  PhotoMechanic Exif GeoTiff CanonRaw KyoceraRaw Lytro MinoltaRaw PanasonicRaw
139
139
  SigmaRaw JPEG GIMP Jpeg2000 GIF BMP BMP::OS2 BMP::Extra BPG BPG::Extensions
140
- PICT PNG MNG FLIF DjVu DPX OpenEXR MIFF PCX PGF PSP PhotoCD Radiance PDF
141
- PostScript Photoshop::Header Photoshop::Layers Photoshop::ImageData
140
+ PICT PNG MNG FLIF DjVu DPX OpenEXR ZISRAW MIFF PCX PGF PSP PhotoCD Radiance
141
+ PDF PostScript Photoshop::Header Photoshop::Layers Photoshop::ImageData
142
142
  FujiFilm::RAF FujiFilm::IFD Samsung::Trailer Sony::SRF2 Sony::SR2SubIFD
143
- Sony::PMP ITC ID3 FLAC Ogg Vorbis APE APE::NewHeader APE::OldHeader Audible
144
- MPC MPEG::Audio MPEG::Video MPEG::Xing M2TS QuickTime QuickTime::ImageFile
145
- QuickTime::Stream Matroska MOI MXF DV Flash Flash::FLV Real::Media
146
- Real::Audio Real::Metafile Red RIFF AIFF ASF WTV DICOM FITS MIE JSON HTML
147
- XMP::SVG Palm Palm::MOBI Palm::EXTH Torrent EXE EXE::PEVersion EXE::PEString
148
- EXE::MachO EXE::PEF EXE::ELF EXE::AR EXE::CHM LNK Font VCard Text
149
- VCard::VCalendar RSRC Rawzor ZIP ZIP::GZIP ZIP::RAR RTF OOXML iWork ISO
150
- FLIR::AFF FLIR::FPF MacOS::MDItem MacOS::XAttr FlashPix::DocTable
143
+ Sony::PMP ITC ID3 ID3::Lyrics3 FLAC Ogg Vorbis APE APE::NewHeader
144
+ APE::OldHeader Audible MPC MPEG::Audio MPEG::Video MPEG::Xing M2TS QuickTime
145
+ QuickTime::ImageFile QuickTime::Stream QuickTime::Tags360Fly Matroska MOI
146
+ MXF DV Flash Flash::FLV Real::Media Real::Audio Real::Metafile Red RIFF AIFF
147
+ ASF WTV DICOM FITS MIE JSON HTML XMP::SVG Palm Palm::MOBI Palm::EXTH Torrent
148
+ EXE EXE::PEVersion EXE::PEString EXE::MachO EXE::PEF EXE::ELF EXE::AR
149
+ EXE::CHM LNK Font VCard Text VCard::VCalendar RSRC Rawzor ZIP ZIP::GZIP
150
+ ZIP::RAR RTF OOXML iWork ISO FLIR::AFF FLIR::FPF MacOS MacOS::MDItem
151
+ FlashPix::DocTable
151
152
  );
152
153
 
153
154
  # alphabetical list of current Lang modules
@@ -186,9 +187,9 @@ $defaultLang = 'en'; # default language
186
187
  PSD XMP BMP BPG PPM RIFF AIFF ASF MOV MPEG Real SWF PSP FLV OGG
187
188
  FLAC APE MPC MKV MXF DV PMP IND PGF ICC ITC FLIR FLIF FPF LFP
188
189
  HTML VRD RTF FITS XCF DSS QTIF FPX PICT ZIP GZIP PLIST RAR BZ2
189
- TAR EXE EXR HDR CHM LNK WMF AVC DEX DPX RAW Font RSRC M2TS PHP
190
- PCX DCX DWF DWG WTV Torrent VCard LRI R3D AA PDB MOI ISO ALIAS
191
- JSON MP3 DICOM PCD TXT);
190
+ CZI TAR EXE EXR HDR CHM LNK WMF AVC DEX DPX RAW Font RSRC M2TS
191
+ MacOS PHP PCX DCX DWF DWG WTV Torrent VCard LRI R3D AA PDB MOI
192
+ ISO ALIAS JSON MP3 DICOM PCD TXT);
192
193
 
193
194
  # file types that we can write (edit)
194
195
  my @writeTypes = qw(JPEG TIFF GIF CRW MRW ORF RAF RAW PNG MIE PSD XMP PPM EPS
@@ -207,10 +208,11 @@ my %writeTypes; # lookup for writable file types (hash filled if required)
207
208
  # - must update CanCreate() documentation if this list is changed!
208
209
  my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
209
210
 
210
- # file type lookup for all recognized file extensions
211
+ # file type lookup for all recognized file extensions (upper case)
211
212
  # (if extension may be more than one type, the type is a list where
212
213
  # the writable type should come first if it exists)
213
214
  %fileTypeLookup = (
215
+ '360' => ['MOV', 'GoPro 360 video'],
214
216
  '3FR' => ['TIFF', 'Hasselblad RAW format'],
215
217
  '3G2' => ['MOV', '3rd Gen. Partnership Project 2 audio/video'],
216
218
  '3GP' => ['MOV', '3rd Gen. Partnership Project audio/video'],
@@ -253,6 +255,7 @@ my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
253
255
  CRW => ['CRW', 'Canon RAW format'],
254
256
  CS1 => ['PSD', 'Sinar CaptureShop 1-Shot RAW'],
255
257
  CSV => ['TXT', 'Comma-Separated Values'],
258
+ CZI => ['CZI', 'Zeiss Integrated Software RAW'],
256
259
  DC3 => 'DICM',
257
260
  DCM => 'DICM',
258
261
  DCP => ['TIFF', 'DNG Camera Profile'],
@@ -410,6 +413,7 @@ my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
410
413
  OFR => ['RIFF', 'OptimFROG audio'],
411
414
  OGG => ['OGG', 'Ogg Vorbis audio file'],
412
415
  OGV => ['OGG', 'Ogg Video file'],
416
+ ONP => ['JSON', 'ON1 Presets'],
413
417
  OPUS => ['OGG', 'Ogg Opus audio file'],
414
418
  ORF => ['ORF', 'Olympus RAW format'],
415
419
  OTF => ['Font', 'Open Type Font'],
@@ -515,6 +519,7 @@ my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
515
519
  WMV => ['ASF', 'Windows Media Video'],
516
520
  WV => ['RIFF', 'WavePack lossless audio'],
517
521
  X3F => ['X3F', 'Sigma RAW format'],
522
+ MACOS=> ['MacOS','MacOS ._ sidecar file'],
518
523
  XCF => ['XCF', 'GIMP native image format'],
519
524
  XHTML=> ['HTML', 'Extensible HyperText Markup Language'],
520
525
  XLA => ['FPX', 'Microsoft Excel Add-in'],
@@ -527,6 +532,8 @@ my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
527
532
  XLTM => [['ZIP','FPX'], 'Office Open XML Spreadsheet Template Macro-enabled'],
528
533
  XLTX => [['ZIP','FPX'], 'Office Open XML Spreadsheet Template'],
529
534
  XMP => ['XMP', 'Extensible Metadata Platform'],
535
+ WOFF => ['Font', 'Web Open Font Format'],
536
+ WOFF2=> ['Font', 'Web Open Font Format2'],
530
537
  WTV => ['WTV', 'Windows recorded TV show'],
531
538
  ZIP => ['ZIP', 'ZIP archive'],
532
539
  );
@@ -581,6 +588,7 @@ my %fileDescription = (
581
588
  CRM => 'video/x-canon-crm',
582
589
  CRW => 'image/x-canon-crw',
583
590
  CSV => 'text/csv',
591
+ CZI => 'image/x-zeiss-czi', #PH (NC)
584
592
  DCP => 'application/octet-stream', #PH (NC)
585
593
  DCR => 'image/x-kodak-dcr',
586
594
  DCX => 'image/dcx',
@@ -681,6 +689,7 @@ my %fileDescription = (
681
689
  ODT => 'application/vnd.oasis.opendocument.text',
682
690
  OGG => 'audio/ogg',
683
691
  OGV => 'video/ogg',
692
+ ONP => 'application/on1',
684
693
  ORF => 'image/x-olympus-orf',
685
694
  OTF => 'application/x-font-otf',
686
695
  PAGES=> 'application/x-iwork-pages-sffpages',
@@ -781,6 +790,7 @@ my %moduleName = (
781
790
  CRW => 'CanonRaw',
782
791
  CHM => 'EXE',
783
792
  COS => 'CaptureOne',
793
+ CZI => 'ZISRAW',
784
794
  DEX => 0,
785
795
  DOCX => 'OOXML',
786
796
  DCX => 0,
@@ -851,6 +861,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
851
861
  BZ2 => 'BZh[1-9]\x31\x41\x59\x26\x53\x59',
852
862
  CHM => 'ITSF.{20}\x10\xfd\x01\x7c\xaa\x7b\xd0\x11\x9e\x0c\0\xa0\xc9\x22\xe6\xec',
853
863
  CRW => '(II|MM).{4}HEAP(CCDR|JPGM)',
864
+ CZI => 'ZISRAWFILE\0{6}',
854
865
  DCX => '\xb1\x68\xde\x3a',
855
866
  DEX => "dex\n035\0",
856
867
  DICOM=> '(.{128}DICM|\0[\x02\x04\x06\x08]\0[\0-\x20]|[\x02\x04\x06\x08]\0[\0-\x20]\0)',
@@ -872,7 +883,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
872
883
  FLIR => '[AF]FF\0',
873
884
  FLV => 'FLV\x01',
874
885
  Font => '((\0\x01\0\0|OTTO|true|typ1)[\0\x01]|ttcf\0[\x01\x02]\0\0|\0[\x01\x02]|' .
875
- '(.{6})?%!(PS-(AdobeFont-|Bitstream )|FontType1-)|Start(Comp|Master)?FontMetrics)',
886
+ '(.{6})?%!(PS-(AdobeFont-|Bitstream )|FontType1-)|Start(Comp|Master)?FontMetrics|wOF[F2])',
876
887
  FPF => 'FPF Public Image Format\0',
877
888
  FPX => '\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1',
878
889
  GIF => 'GIF8[79]a',
@@ -935,6 +946,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
935
946
  WMF => '(\xd7\xcd\xc6\x9a\0\0|\x01\0\x09\0\0\x03)',
936
947
  WTV => '\xb7\xd8\x00\x20\x37\x49\xda\x11\xa6\x4e\x00\x07\xe9\x5e\xad\x8d',
937
948
  X3F => 'FOVb',
949
+ MacOS=> '\0\x05\x16\x07\0.\0\0Mac OS X ',
938
950
  XCF => 'gimp xcf ',
939
951
  XMP => '\0{0,3}(\xfe\xff|\xff\xfe|\xef\xbb\xbf)?\0{0,3}\s*<',
940
952
  ZIP => 'PK\x03\x04',
@@ -1445,6 +1457,11 @@ my %systemTagsNotes = (
1445
1457
  return Image::ExifTool::XMP::CheckXMP($self, $tagInfo, \$val);
1446
1458
  },
1447
1459
  },
1460
+ XML => {
1461
+ Notes => 'the XML data block, extracted for some file types',
1462
+ Groups => { 0 => 'XML', 1 => 'XML' },
1463
+ Binary => 1,
1464
+ },
1448
1465
  ICC_Profile => {
1449
1466
  Notes => q{
1450
1467
  the full ICC_Profile data block. This tag is generated only if specifically
@@ -2236,6 +2253,7 @@ sub ClearOptions($)
2236
2253
  GeoSpeedRef => undef, # geotag GPSSpeedRef
2237
2254
  GlobalTimeShift => undef, # apply time shift to all extracted date/time values
2238
2255
  # Group# => undef, # return tags for specified groups in family #
2256
+ HexTagIDs => 0, # use hex tag ID's in family 7 group names
2239
2257
  HtmlDump => 0, # HTML dump (0-3, higher # = bigger limit)
2240
2258
  HtmlDumpBase => undef, # base address for HTML dump
2241
2259
  IgnoreMinorErrors => undef, # ignore minor errors when reading/writing
@@ -2249,6 +2267,7 @@ sub ClearOptions($)
2249
2267
  MakerNotes => undef, # extract maker notes as a block
2250
2268
  MDItemTags => undef, # extract MacOS metadata item tags
2251
2269
  MissingTagValue =>undef,# value for missing tags when expanded in expressions
2270
+ NoMultiExif => undef, # raise error when writing multi-segment EXIF
2252
2271
  NoPDFList => undef, # flag to avoid splitting PDF List-type tag values
2253
2272
  Password => undef, # password for password-protected PDF documents
2254
2273
  PrintConv => 1, # flag to enable print conversion
@@ -3095,30 +3114,9 @@ sub GetValue($$;$)
3095
3114
  }
3096
3115
  if (ref $conv eq 'HASH') {
3097
3116
  # look up converted value in hash
3098
- my $lc;
3099
- if (defined($value = $$conv{$val})) {
3100
- # override with our localized language PrintConv if available
3101
- if ($$self{CUR_LANG} and $convType eq 'PrintConv' and
3102
- # (no need to check for lang-alt tag names -- they won't have a PrintConv)
3103
- ref($lc = $$self{CUR_LANG}{$$tagInfo{Name}}) eq 'HASH' and
3104
- ($lc = $$lc{PrintConv}) and ($lc = $$lc{$value}))
3105
- {
3106
- $value = $self->Decode($lc, 'UTF8');
3107
- }
3108
- } else {
3117
+ if (not defined($value = $$conv{$val})) {
3109
3118
  if ($$conv{BITMASK}) {
3110
3119
  $value = DecodeBits($val, $$conv{BITMASK}, $$tagInfo{BitsPerWord});
3111
- # override with localized language strings
3112
- if (defined $value and $$self{CUR_LANG} and $convType eq 'PrintConv' and
3113
- ref($lc = $$self{CUR_LANG}{$$tagInfo{Name}}) eq 'HASH' and
3114
- ($lc = $$lc{PrintConv}))
3115
- {
3116
- my @vals = split ', ', $value;
3117
- foreach (@vals) {
3118
- $_ = $$lc{$_} if defined $$lc{$_};
3119
- }
3120
- $value = join ', ', @vals;
3121
- }
3122
3120
  } else {
3123
3121
  # use alternate conversion routine if available
3124
3122
  if ($$conv{OTHER}) {
@@ -3131,12 +3129,30 @@ sub GetValue($$;$)
3131
3129
  if ($$tagInfo{PrintHex} and $val and IsInt($val) and
3132
3130
  $convType eq 'PrintConv')
3133
3131
  {
3134
- $val = sprintf('0x%x',$val);
3132
+ $value = sprintf('Unknown (0x%x)',$val);
3133
+ } else {
3134
+ $value = "Unknown ($val)";
3135
3135
  }
3136
- $value = "Unknown ($val)";
3137
3136
  }
3138
3137
  }
3139
3138
  }
3139
+ # override with our localized language PrintConv if available
3140
+ my $tmp;
3141
+ if ($$self{CUR_LANG} and $convType eq 'PrintConv' and
3142
+ # (no need to check for lang-alt tag names -- they won't have a PrintConv)
3143
+ ref($tmp = $$self{CUR_LANG}{$$tagInfo{Name}}) eq 'HASH' and
3144
+ ($tmp = $$tmp{PrintConv}))
3145
+ {
3146
+ if ($$conv{BITMASK} and not defined $$conv{$val}) {
3147
+ my @vals = split ', ', $value;
3148
+ foreach (@vals) {
3149
+ $_ = $$tmp{$_} if defined $$tmp{$_};
3150
+ }
3151
+ $value = join ', ', @vals;
3152
+ } elsif (defined($tmp = $$tmp{$value})) {
3153
+ $value = $self->Decode($tmp, 'UTF8');
3154
+ }
3155
+ }
3140
3156
  } else {
3141
3157
  # call subroutine or do eval to convert value
3142
3158
  local $SIG{'__WARN__'} = \&SetWarning;
@@ -3294,7 +3310,7 @@ sub GetGroup($$;$)
3294
3310
  {
3295
3311
  local $_;
3296
3312
  my ($self, $tag, $family) = @_;
3297
- my ($tagInfo, @groups, @families, $simplify, $byTagInfo, $ex);
3313
+ my ($tagInfo, @groups, @families, $simplify, $byTagInfo, $ex, $noID);
3298
3314
  if (ref $tag eq 'HASH') {
3299
3315
  $tagInfo = $tag;
3300
3316
  $tag = $$tagInfo{Name};
@@ -3325,6 +3341,7 @@ sub GetGroup($$;$)
3325
3341
  $simplify = 1 unless $family =~ /^:/;
3326
3342
  undef $family;
3327
3343
  foreach (0..2) { $groups[$_] = $$groups{$_}; }
3344
+ $noID = 1 if @families == 1 and $families[0] != 7;
3328
3345
  } else {
3329
3346
  return(($ex && $$ex{"G$family"}) || $$groups{$family}) if $family == 0 or $family == 2;
3330
3347
  $groups[1] = $$groups{1};
@@ -3336,14 +3353,29 @@ sub GetGroup($$;$)
3336
3353
  $groups[3] = 'Main';
3337
3354
  $groups[4] = ($tag =~ /\((\d+)\)$/) ? "Copy$1" : '';
3338
3355
  # handle dynamic group names if necessary
3339
- if ($ex and not $byTagInfo) {
3340
- $groups[0] = $$ex{G0} if $$ex{G0};
3341
- $groups[1] = $$ex{G1} =~ /^\+(.*)/ ? "$groups[1]$1" : $$ex{G1} if $$ex{G1};
3342
- $groups[3] = 'Doc' . $$ex{G3} if $$ex{G3};
3343
- $groups[5] = $$ex{G5} || $groups[1] if defined $$ex{G5};
3344
- if (defined $$ex{G6}) {
3345
- $groups[5] = '' unless defined $groups[5]; # (can't leave a hole in the array)
3346
- $groups[6] = $$ex{G6};
3356
+ unless ($byTagInfo) {
3357
+ if ($ex) {
3358
+ $groups[0] = $$ex{G0} if $$ex{G0};
3359
+ $groups[1] = $$ex{G1} =~ /^\+(.*)/ ? "$groups[1]$1" : $$ex{G1} if $$ex{G1};
3360
+ $groups[3] = 'Doc' . $$ex{G3} if $$ex{G3};
3361
+ $groups[5] = $$ex{G5} || $groups[1] if defined $$ex{G5};
3362
+ if (defined $$ex{G6}) {
3363
+ $groups[5] = '' unless defined $groups[5]; # (can't leave a hole in the array)
3364
+ $groups[6] = $$ex{G6};
3365
+ }
3366
+ }
3367
+ # generate tag ID group names unless obviously not needed
3368
+ unless ($noID) {
3369
+ my $id = $$tagInfo{TagID};
3370
+ if (not defined $id) {
3371
+ $id = ''; # (just to be safe)
3372
+ } elsif ($id =~ /^\d+$/) {
3373
+ $id = sprintf('0x%x', $id) if $$self{OPTIONS}{HexTagIDs};
3374
+ } else {
3375
+ $id =~ s/([^-_A-Za-z0-9])/sprintf('%.2x',ord $1)/ge;
3376
+ }
3377
+ $groups[7] = 'ID-' . $id;
3378
+ defined $groups[$_] or $groups[$_] = '' foreach (5,6);
3347
3379
  }
3348
3380
  }
3349
3381
  if ($family) {
@@ -4191,6 +4223,22 @@ sub ParseArguments($;@)
4191
4223
  }
4192
4224
  }
4193
4225
 
4226
+ #------------------------------------------------------------------------------
4227
+ # Does group name match the tag ID?
4228
+ # Inputs: 0) tag ID, 1) group name (with "ID-" removed)
4229
+ # Returns: true on success
4230
+ sub IsSameID($$)
4231
+ {
4232
+ my ($id, $grp) = @_;
4233
+ return 1 if $grp eq $id; # decimal ID's or raw ID's
4234
+ if ($id =~ /^\d+$/) { # numerical numerical ID's may be in hex
4235
+ return 1 if $grp =~ s/^0x0*// and $grp eq sprintf('%x', $id);
4236
+ } else { # other ID's may conform to ExifTool group name conventions
4237
+ return 1 if $id =~ s/([^-_A-Za-z0-9])/sprintf('%.2x',ord $1)/ge and $grp eq $id;
4238
+ }
4239
+ return 0;
4240
+ }
4241
+
4194
4242
  #------------------------------------------------------------------------------
4195
4243
  # Get list of tags in specified group
4196
4244
  # Inputs: 0) ExifTool ref, 1) group spec, 2) tag key or reference to list of tag keys
@@ -4202,40 +4250,41 @@ sub GroupMatches($$$)
4202
4250
  my ($self, $group, $tagList) = @_;
4203
4251
  $tagList = [ $tagList ] unless ref $tagList;
4204
4252
  my ($tag, @matches);
4205
- if ($group =~ /:/) {
4206
- # check each group name individually (eg. "Author:1IPTC")
4207
- my @grps = split ':', lc $group;
4208
- my (@fmys, $g);
4253
+ # check each group name individually (eg. "Author:1IPTC")
4254
+ my @grps = split ':', $group;
4255
+ my (@fmys, $g);
4256
+ for ($g=0; $g<@grps; ++$g) {
4257
+ if ($grps[$g] =~ s/^(\d*)(id-)?//i) {
4258
+ $fmys[$g] = $1 if length $1;
4259
+ if ($2) {
4260
+ $fmys[$g] = 7;
4261
+ next; # (don't convert tag ID's to lower case)
4262
+ }
4263
+ }
4264
+ $grps[$g] = lc $grps[$g];
4265
+ $grps[$g] = '' if $grps[$g] eq 'copy0'; # accept 'Copy0' for primary tag
4266
+ }
4267
+ foreach $tag (@$tagList) {
4268
+ my @groups = $self->GetGroup($tag, -1);
4209
4269
  for ($g=0; $g<@grps; ++$g) {
4210
- $fmys[$g] = $1 if $grps[$g] =~ s/^(\d+)//;
4211
- $grps[$g] = '' if $grps[$g] eq 'copy0'; # accept 'Copy0' for primary tag
4212
- }
4213
- foreach $tag (@$tagList) {
4214
- my @groups = $self->GetGroup($tag, -1);
4215
- for ($g=0; $g<@grps; ++$g) {
4216
- my $grp = $grps[$g];
4217
- next if $grp eq '*' or $grp eq 'all';
4218
- if (defined $fmys[$g]) {
4219
- my $f = $fmys[$g];
4220
- last unless defined $groups[$f] and $grp eq lc $groups[$f];
4270
+ my $grp = $grps[$g];
4271
+ next if $grp eq '*' or $grp eq 'all';
4272
+ my $f;
4273
+ if (defined($f = $fmys[$g])) {
4274
+ last unless defined $groups[$f];
4275
+ if ($f == 7) {
4276
+ next if IsSameID($self->GetTagID($tag), $grp);
4221
4277
  } else {
4222
- last unless grep /^$grp$/i, @groups;
4278
+ next if $grp eq lc $groups[$f];
4223
4279
  }
4224
- }
4225
- if ($g == @grps) {
4226
- return $tag unless wantarray;
4227
- push @matches, $tag;
4280
+ last;
4281
+ } else {
4282
+ last unless grep /^$grp$/i, @groups;
4228
4283
  }
4229
4284
  }
4230
- } else {
4231
- my $family = ($group =~ s/^(\d+)//) ? $1 : -1;
4232
- $group = '' if lc $group eq 'copy0'; # accept 'Copy0' for primary tag
4233
- foreach $tag (@$tagList) {
4234
- my @groups = $self->GetGroup($tag, $family);
4235
- if (grep(/^$group$/i, @groups)) {
4236
- return $tag unless wantarray;
4237
- push @matches, $tag;
4238
- }
4285
+ if ($g == @grps) {
4286
+ return $tag unless wantarray;
4287
+ push @matches, $tag;
4239
4288
  }
4240
4289
  }
4241
4290
  return wantarray ? @matches : $matches[0];
@@ -4694,13 +4743,13 @@ sub AddCompositeTags($;$)
4694
4743
  my ($module, $prefix, $tagID);
4695
4744
  unless (ref $add) {
4696
4745
  ($prefix = $add) =~ s/.*:://;
4697
- $prefix .= '::';
4698
4746
  $module = $add;
4699
4747
  $add .= '::Composite';
4700
4748
  no strict 'refs';
4701
4749
  $add = \%$add;
4750
+ $prefix .= '-';
4702
4751
  } else {
4703
- $prefix = 'UserDefined::';
4752
+ $prefix = 'UserDefined-';
4704
4753
  }
4705
4754
  my $defaultGroups = $$add{GROUPS};
4706
4755
  my $compTable = GetTagTable('Image::ExifTool::Composite');
@@ -5415,36 +5464,38 @@ sub GetDescriptions($$)
5415
5464
 
5416
5465
  #------------------------------------------------------------------------------
5417
5466
  # Apply filter to value(s) if necessary
5418
- # Inputs: 0) ExifTool ref, 1) filter expression, 2-N) references to value(s) to filter
5419
- # Returns: nothing, but changes values if necessary
5420
- sub Filter($$@)
5467
+ # Inputs: 0) ExifTool ref, 1) filter expression, 2) reference to value to filter
5468
+ # Returns: true unless a filter returned undef; changes value if necessary
5469
+ sub Filter($$$)
5421
5470
  {
5422
5471
  local $_;
5423
- my $self = shift;
5424
- my $filter = shift;
5425
- return unless defined $filter;
5426
- while (@_) {
5427
- my $valPt = shift;
5428
- next unless defined $$valPt;
5429
- if (not ref $$valPt) {
5430
- $_ = $$valPt;
5431
- #### eval Filter ($_, $self)
5432
- eval $filter;
5433
- $$valPt = $_ if defined $_;
5434
- } elsif (ref $$valPt eq 'SCALAR') {
5435
- my $val = $$$valPt; # make a copy to avoid filtering twice
5436
- $self->Filter($filter, \$val);
5437
- $$valPt = \$val;
5438
- } elsif (ref $$valPt eq 'ARRAY') {
5439
- my @val = @{$$valPt}; # make a copy to avoid filtering twice
5440
- $self->Filter($filter, \$_) foreach @val;
5441
- $$valPt = \@val;
5442
- } elsif (ref $$valPt eq 'HASH') {
5443
- my %val = %{$$valPt}; # make a copy to avoid filtering twice
5444
- $self->Filter($filter, \$val{$_}) foreach keys %val;
5445
- $$valPt = \%val;
5446
- }
5472
+ my ($self, $filter, $valPt) = @_;
5473
+ return 1 unless defined $filter and defined $$valPt;
5474
+ my $rtnVal;
5475
+ if (not ref $$valPt) {
5476
+ $_ = $$valPt;
5477
+ #### eval Filter ($_, $self)
5478
+ eval $filter;
5479
+ if (defined $_) {
5480
+ $$valPt = $_;
5481
+ $rtnVal = 1;
5482
+ }
5483
+ } elsif (ref $$valPt eq 'SCALAR') {
5484
+ my $val = $$$valPt; # make a copy to avoid filtering twice
5485
+ $rtnVal = $self->Filter($filter, \$val);
5486
+ $$valPt = \$val;
5487
+ } elsif (ref $$valPt eq 'ARRAY') {
5488
+ my @val = @{$$valPt}; # make a copy to avoid filtering twice
5489
+ $self->Filter($filter, \$_) and $rtnVal = 1 foreach @val;
5490
+ $$valPt = \@val;
5491
+ } elsif (ref $$valPt eq 'HASH') {
5492
+ my %val = %{$$valPt}; # make a copy to avoid filtering twice
5493
+ $self->Filter($filter, \$val{$_}) and $rtnVal = 1 foreach keys %val;
5494
+ $$valPt = \%val;
5495
+ } else {
5496
+ $rtnVal = 1;
5447
5497
  }
5498
+ return $rtnVal;
5448
5499
  }
5449
5500
 
5450
5501
  #------------------------------------------------------------------------------
@@ -7555,7 +7606,7 @@ sub ProcessDirectory($$$;$)
7555
7606
 
7556
7607
  #------------------------------------------------------------------------------
7557
7608
  # Get Metadata path
7558
- # Inputs: 0) Exiftool object ref
7609
+ # Inputs: 0) ExifTool object ref
7559
7610
  # Return: Metadata path string
7560
7611
  sub MetadataPath($)
7561
7612
  {
@@ -7747,7 +7798,7 @@ sub HandleTag($$$$;%)
7747
7798
  my ($subdir, $format, $noTagInfo, $rational);
7748
7799
 
7749
7800
  if ($tagInfo) {
7750
- $subdir = $$tagInfo{SubDirectory}
7801
+ $subdir = $$tagInfo{SubDirectory};
7751
7802
  } else {
7752
7803
  return undef unless $verbose;
7753
7804
  $tagInfo = { Name => "tag $tag" }; # create temporary tagInfo hash
@@ -8197,7 +8248,7 @@ sub VerboseDir($$;$$)
8197
8248
  }
8198
8249
  my $indent = substr($$self{INDENT}, 0, -2);
8199
8250
  my $out = $$self{OPTIONS}{TextOut};
8200
- my $str = $entries ? " with $entries entries" : '';
8251
+ my $str = ($entries or defined $entries and not $size) ? " with $entries entries" : '';
8201
8252
  $str .= ", $size bytes" if $size;
8202
8253
  print $out "$indent+ [$name directory$str]\n";
8203
8254
  }