exiftool_vendored 11.96.0 → 12.08.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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +172 -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 +148 -69
  8. data/bin/lib/Image/ExifTool.pm +159 -110
  9. data/bin/lib/Image/ExifTool.pod +114 -87
  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 +13 -7
  13. data/bin/lib/Image/ExifTool/Canon.pm +37 -11
  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 +20 -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 +5 -0
  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 +56 -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/Lang/de.pm +3 -1
  29. data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
  30. data/bin/lib/Image/ExifTool/M2TS.pm +44 -24
  31. data/bin/lib/Image/ExifTool/MacOS.pm +152 -38
  32. data/bin/lib/Image/ExifTool/Minolta.pm +6 -2
  33. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +11 -10
  34. data/bin/lib/Image/ExifTool/Nikon.pm +162 -18
  35. data/bin/lib/Image/ExifTool/Olympus.pm +39 -17
  36. data/bin/lib/Image/ExifTool/PNG.pm +14 -3
  37. data/bin/lib/Image/ExifTool/PPM.pm +5 -5
  38. data/bin/lib/Image/ExifTool/Panasonic.pm +148 -14
  39. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +33 -0
  40. data/bin/lib/Image/ExifTool/Parrot.pm +2 -1
  41. data/bin/lib/Image/ExifTool/Pentax.pm +3 -1
  42. data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
  43. data/bin/lib/Image/ExifTool/QuickTime.pm +269 -29
  44. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +463 -75
  45. data/bin/lib/Image/ExifTool/README +21 -20
  46. data/bin/lib/Image/ExifTool/RIFF.pm +15 -3
  47. data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
  48. data/bin/lib/Image/ExifTool/RTF.pm +12 -7
  49. data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
  50. data/bin/lib/Image/ExifTool/Shift.pl +1 -0
  51. data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
  52. data/bin/lib/Image/ExifTool/Sony.pm +425 -34
  53. data/bin/lib/Image/ExifTool/TagLookup.pm +1961 -1874
  54. data/bin/lib/Image/ExifTool/TagNames.pod +394 -86
  55. data/bin/lib/Image/ExifTool/Validate.pm +4 -4
  56. data/bin/lib/Image/ExifTool/WriteExif.pl +3 -2
  57. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +23 -15
  58. data/bin/lib/Image/ExifTool/Writer.pl +44 -21
  59. data/bin/lib/Image/ExifTool/XMP.pm +42 -5
  60. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  61. data/bin/lib/Image/ExifTool/ZISRAW.pm +123 -0
  62. data/bin/perl-Image-ExifTool.spec +42 -41
  63. data/lib/exiftool_vendored/version.rb +1 -1
  64. 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.96';
31
+ $VERSION = '12.08';
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'],
@@ -515,6 +518,7 @@ my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
515
518
  WMV => ['ASF', 'Windows Media Video'],
516
519
  WV => ['RIFF', 'WavePack lossless audio'],
517
520
  X3F => ['X3F', 'Sigma RAW format'],
521
+ MACOS=> ['MacOS','MacOS ._ sidecar file'],
518
522
  XCF => ['XCF', 'GIMP native image format'],
519
523
  XHTML=> ['HTML', 'Extensible HyperText Markup Language'],
520
524
  XLA => ['FPX', 'Microsoft Excel Add-in'],
@@ -527,6 +531,8 @@ my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
527
531
  XLTM => [['ZIP','FPX'], 'Office Open XML Spreadsheet Template Macro-enabled'],
528
532
  XLTX => [['ZIP','FPX'], 'Office Open XML Spreadsheet Template'],
529
533
  XMP => ['XMP', 'Extensible Metadata Platform'],
534
+ WOFF => ['Font', 'Web Open Font Format'],
535
+ WOFF2=> ['Font', 'Web Open Font Format2'],
530
536
  WTV => ['WTV', 'Windows recorded TV show'],
531
537
  ZIP => ['ZIP', 'ZIP archive'],
532
538
  );
@@ -581,6 +587,7 @@ my %fileDescription = (
581
587
  CRM => 'video/x-canon-crm',
582
588
  CRW => 'image/x-canon-crw',
583
589
  CSV => 'text/csv',
590
+ CZI => 'image/x-zeiss-czi', #PH (NC)
584
591
  DCP => 'application/octet-stream', #PH (NC)
585
592
  DCR => 'image/x-kodak-dcr',
586
593
  DCX => 'image/dcx',
@@ -781,6 +788,7 @@ my %moduleName = (
781
788
  CRW => 'CanonRaw',
782
789
  CHM => 'EXE',
783
790
  COS => 'CaptureOne',
791
+ CZI => 'ZISRAW',
784
792
  DEX => 0,
785
793
  DOCX => 'OOXML',
786
794
  DCX => 0,
@@ -851,6 +859,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
851
859
  BZ2 => 'BZh[1-9]\x31\x41\x59\x26\x53\x59',
852
860
  CHM => 'ITSF.{20}\x10\xfd\x01\x7c\xaa\x7b\xd0\x11\x9e\x0c\0\xa0\xc9\x22\xe6\xec',
853
861
  CRW => '(II|MM).{4}HEAP(CCDR|JPGM)',
862
+ CZI => 'ZISRAWFILE\0{6}',
854
863
  DCX => '\xb1\x68\xde\x3a',
855
864
  DEX => "dex\n035\0",
856
865
  DICOM=> '(.{128}DICM|\0[\x02\x04\x06\x08]\0[\0-\x20]|[\x02\x04\x06\x08]\0[\0-\x20]\0)',
@@ -872,7 +881,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
872
881
  FLIR => '[AF]FF\0',
873
882
  FLV => 'FLV\x01',
874
883
  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)',
884
+ '(.{6})?%!(PS-(AdobeFont-|Bitstream )|FontType1-)|Start(Comp|Master)?FontMetrics|wOF[F2])',
876
885
  FPF => 'FPF Public Image Format\0',
877
886
  FPX => '\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1',
878
887
  GIF => 'GIF8[79]a',
@@ -935,6 +944,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
935
944
  WMF => '(\xd7\xcd\xc6\x9a\0\0|\x01\0\x09\0\0\x03)',
936
945
  WTV => '\xb7\xd8\x00\x20\x37\x49\xda\x11\xa6\x4e\x00\x07\xe9\x5e\xad\x8d',
937
946
  X3F => 'FOVb',
947
+ MacOS=> '\0\x05\x16\x07\0.\0\0Mac OS X ',
938
948
  XCF => 'gimp xcf ',
939
949
  XMP => '\0{0,3}(\xfe\xff|\xff\xfe|\xef\xbb\xbf)?\0{0,3}\s*<',
940
950
  ZIP => 'PK\x03\x04',
@@ -1445,6 +1455,11 @@ my %systemTagsNotes = (
1445
1455
  return Image::ExifTool::XMP::CheckXMP($self, $tagInfo, \$val);
1446
1456
  },
1447
1457
  },
1458
+ XML => {
1459
+ Notes => 'the XML data block, extracted for some file types',
1460
+ Groups => { 0 => 'XML', 1 => 'XML' },
1461
+ Binary => 1,
1462
+ },
1448
1463
  ICC_Profile => {
1449
1464
  Notes => q{
1450
1465
  the full ICC_Profile data block. This tag is generated only if specifically
@@ -2236,6 +2251,7 @@ sub ClearOptions($)
2236
2251
  GeoSpeedRef => undef, # geotag GPSSpeedRef
2237
2252
  GlobalTimeShift => undef, # apply time shift to all extracted date/time values
2238
2253
  # Group# => undef, # return tags for specified groups in family #
2254
+ HexTagIDs => 0, # use hex tag ID's in family 7 group names
2239
2255
  HtmlDump => 0, # HTML dump (0-3, higher # = bigger limit)
2240
2256
  HtmlDumpBase => undef, # base address for HTML dump
2241
2257
  IgnoreMinorErrors => undef, # ignore minor errors when reading/writing
@@ -2249,6 +2265,7 @@ sub ClearOptions($)
2249
2265
  MakerNotes => undef, # extract maker notes as a block
2250
2266
  MDItemTags => undef, # extract MacOS metadata item tags
2251
2267
  MissingTagValue =>undef,# value for missing tags when expanded in expressions
2268
+ NoMultiExif => undef, # raise error when writing multi-segment EXIF
2252
2269
  NoPDFList => undef, # flag to avoid splitting PDF List-type tag values
2253
2270
  Password => undef, # password for password-protected PDF documents
2254
2271
  PrintConv => 1, # flag to enable print conversion
@@ -3095,30 +3112,9 @@ sub GetValue($$;$)
3095
3112
  }
3096
3113
  if (ref $conv eq 'HASH') {
3097
3114
  # 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 {
3115
+ if (not defined($value = $$conv{$val})) {
3109
3116
  if ($$conv{BITMASK}) {
3110
3117
  $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
3118
  } else {
3123
3119
  # use alternate conversion routine if available
3124
3120
  if ($$conv{OTHER}) {
@@ -3131,12 +3127,30 @@ sub GetValue($$;$)
3131
3127
  if ($$tagInfo{PrintHex} and $val and IsInt($val) and
3132
3128
  $convType eq 'PrintConv')
3133
3129
  {
3134
- $val = sprintf('0x%x',$val);
3130
+ $value = sprintf('Unknown (0x%x)',$val);
3131
+ } else {
3132
+ $value = "Unknown ($val)";
3135
3133
  }
3136
- $value = "Unknown ($val)";
3137
3134
  }
3138
3135
  }
3139
3136
  }
3137
+ # override with our localized language PrintConv if available
3138
+ my $tmp;
3139
+ if ($$self{CUR_LANG} and $convType eq 'PrintConv' and
3140
+ # (no need to check for lang-alt tag names -- they won't have a PrintConv)
3141
+ ref($tmp = $$self{CUR_LANG}{$$tagInfo{Name}}) eq 'HASH' and
3142
+ ($tmp = $$tmp{PrintConv}))
3143
+ {
3144
+ if ($$conv{BITMASK} and not defined $$conv{$val}) {
3145
+ my @vals = split ', ', $value;
3146
+ foreach (@vals) {
3147
+ $_ = $$tmp{$_} if defined $$tmp{$_};
3148
+ }
3149
+ $value = join ', ', @vals;
3150
+ } elsif (defined($tmp = $$tmp{$value})) {
3151
+ $value = $self->Decode($tmp, 'UTF8');
3152
+ }
3153
+ }
3140
3154
  } else {
3141
3155
  # call subroutine or do eval to convert value
3142
3156
  local $SIG{'__WARN__'} = \&SetWarning;
@@ -3294,7 +3308,7 @@ sub GetGroup($$;$)
3294
3308
  {
3295
3309
  local $_;
3296
3310
  my ($self, $tag, $family) = @_;
3297
- my ($tagInfo, @groups, @families, $simplify, $byTagInfo, $ex);
3311
+ my ($tagInfo, @groups, @families, $simplify, $byTagInfo, $ex, $noID);
3298
3312
  if (ref $tag eq 'HASH') {
3299
3313
  $tagInfo = $tag;
3300
3314
  $tag = $$tagInfo{Name};
@@ -3325,6 +3339,7 @@ sub GetGroup($$;$)
3325
3339
  $simplify = 1 unless $family =~ /^:/;
3326
3340
  undef $family;
3327
3341
  foreach (0..2) { $groups[$_] = $$groups{$_}; }
3342
+ $noID = 1 if @families == 1 and $families[0] != 7;
3328
3343
  } else {
3329
3344
  return(($ex && $$ex{"G$family"}) || $$groups{$family}) if $family == 0 or $family == 2;
3330
3345
  $groups[1] = $$groups{1};
@@ -3336,14 +3351,29 @@ sub GetGroup($$;$)
3336
3351
  $groups[3] = 'Main';
3337
3352
  $groups[4] = ($tag =~ /\((\d+)\)$/) ? "Copy$1" : '';
3338
3353
  # 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};
3354
+ unless ($byTagInfo) {
3355
+ if ($ex) {
3356
+ $groups[0] = $$ex{G0} if $$ex{G0};
3357
+ $groups[1] = $$ex{G1} =~ /^\+(.*)/ ? "$groups[1]$1" : $$ex{G1} if $$ex{G1};
3358
+ $groups[3] = 'Doc' . $$ex{G3} if $$ex{G3};
3359
+ $groups[5] = $$ex{G5} || $groups[1] if defined $$ex{G5};
3360
+ if (defined $$ex{G6}) {
3361
+ $groups[5] = '' unless defined $groups[5]; # (can't leave a hole in the array)
3362
+ $groups[6] = $$ex{G6};
3363
+ }
3364
+ }
3365
+ # generate tag ID group names unless obviously not needed
3366
+ unless ($noID) {
3367
+ my $id = $$tagInfo{TagID};
3368
+ if (not defined $id) {
3369
+ $id = ''; # (just to be safe)
3370
+ } elsif ($id =~ /^\d+$/) {
3371
+ $id = sprintf('0x%x', $id) if $$self{OPTIONS}{HexTagIDs};
3372
+ } else {
3373
+ $id =~ s/([^-_A-Za-z0-9])/sprintf('%.2x',ord $1)/ge;
3374
+ }
3375
+ $groups[7] = 'ID-' . $id;
3376
+ defined $groups[$_] or $groups[$_] = '' foreach (5,6);
3347
3377
  }
3348
3378
  }
3349
3379
  if ($family) {
@@ -4191,6 +4221,22 @@ sub ParseArguments($;@)
4191
4221
  }
4192
4222
  }
4193
4223
 
4224
+ #------------------------------------------------------------------------------
4225
+ # Does group name match the tag ID?
4226
+ # Inputs: 0) tag ID, 1) group name (with "ID-" removed)
4227
+ # Returns: true on success
4228
+ sub IsSameID($$)
4229
+ {
4230
+ my ($id, $grp) = @_;
4231
+ return 1 if $grp eq $id; # decimal ID's or raw ID's
4232
+ if ($id =~ /^\d+$/) { # numerical numerical ID's may be in hex
4233
+ return 1 if $grp =~ s/^0x0*// and $grp eq sprintf('%x', $id);
4234
+ } else { # other ID's may conform to ExifTool group name conventions
4235
+ return 1 if $id =~ s/([^-_A-Za-z0-9])/sprintf('%.2x',ord $1)/ge and $grp eq $id;
4236
+ }
4237
+ return 0;
4238
+ }
4239
+
4194
4240
  #------------------------------------------------------------------------------
4195
4241
  # Get list of tags in specified group
4196
4242
  # Inputs: 0) ExifTool ref, 1) group spec, 2) tag key or reference to list of tag keys
@@ -4202,40 +4248,41 @@ sub GroupMatches($$$)
4202
4248
  my ($self, $group, $tagList) = @_;
4203
4249
  $tagList = [ $tagList ] unless ref $tagList;
4204
4250
  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);
4251
+ # check each group name individually (eg. "Author:1IPTC")
4252
+ my @grps = split ':', $group;
4253
+ my (@fmys, $g);
4254
+ for ($g=0; $g<@grps; ++$g) {
4255
+ if ($grps[$g] =~ s/^(\d*)(id-)?//i) {
4256
+ $fmys[$g] = $1 if length $1;
4257
+ if ($2) {
4258
+ $fmys[$g] = 7;
4259
+ next; # (don't convert tag ID's to lower case)
4260
+ }
4261
+ }
4262
+ $grps[$g] = lc $grps[$g];
4263
+ $grps[$g] = '' if $grps[$g] eq 'copy0'; # accept 'Copy0' for primary tag
4264
+ }
4265
+ foreach $tag (@$tagList) {
4266
+ my @groups = $self->GetGroup($tag, -1);
4209
4267
  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];
4268
+ my $grp = $grps[$g];
4269
+ next if $grp eq '*' or $grp eq 'all';
4270
+ my $f;
4271
+ if (defined($f = $fmys[$g])) {
4272
+ last unless defined $groups[$f];
4273
+ if ($f == 7) {
4274
+ next if IsSameID($self->GetTagID($tag), $grp);
4221
4275
  } else {
4222
- last unless grep /^$grp$/i, @groups;
4276
+ next if $grp eq lc $groups[$f];
4223
4277
  }
4224
- }
4225
- if ($g == @grps) {
4226
- return $tag unless wantarray;
4227
- push @matches, $tag;
4278
+ last;
4279
+ } else {
4280
+ last unless grep /^$grp$/i, @groups;
4228
4281
  }
4229
4282
  }
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
- }
4283
+ if ($g == @grps) {
4284
+ return $tag unless wantarray;
4285
+ push @matches, $tag;
4239
4286
  }
4240
4287
  }
4241
4288
  return wantarray ? @matches : $matches[0];
@@ -4694,13 +4741,13 @@ sub AddCompositeTags($;$)
4694
4741
  my ($module, $prefix, $tagID);
4695
4742
  unless (ref $add) {
4696
4743
  ($prefix = $add) =~ s/.*:://;
4697
- $prefix .= '::';
4698
4744
  $module = $add;
4699
4745
  $add .= '::Composite';
4700
4746
  no strict 'refs';
4701
4747
  $add = \%$add;
4748
+ $prefix .= '-';
4702
4749
  } else {
4703
- $prefix = 'UserDefined::';
4750
+ $prefix = 'UserDefined-';
4704
4751
  }
4705
4752
  my $defaultGroups = $$add{GROUPS};
4706
4753
  my $compTable = GetTagTable('Image::ExifTool::Composite');
@@ -5415,36 +5462,38 @@ sub GetDescriptions($$)
5415
5462
 
5416
5463
  #------------------------------------------------------------------------------
5417
5464
  # 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($$@)
5465
+ # Inputs: 0) ExifTool ref, 1) filter expression, 2) reference to value to filter
5466
+ # Returns: true unless a filter returned undef; changes value if necessary
5467
+ sub Filter($$$)
5421
5468
  {
5422
5469
  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
- }
5470
+ my ($self, $filter, $valPt) = @_;
5471
+ return 1 unless defined $filter and defined $$valPt;
5472
+ my $rtnVal;
5473
+ if (not ref $$valPt) {
5474
+ $_ = $$valPt;
5475
+ #### eval Filter ($_, $self)
5476
+ eval $filter;
5477
+ if (defined $_) {
5478
+ $$valPt = $_;
5479
+ $rtnVal = 1;
5480
+ }
5481
+ } elsif (ref $$valPt eq 'SCALAR') {
5482
+ my $val = $$$valPt; # make a copy to avoid filtering twice
5483
+ $rtnVal = $self->Filter($filter, \$val);
5484
+ $$valPt = \$val;
5485
+ } elsif (ref $$valPt eq 'ARRAY') {
5486
+ my @val = @{$$valPt}; # make a copy to avoid filtering twice
5487
+ $self->Filter($filter, \$_) and $rtnVal = 1 foreach @val;
5488
+ $$valPt = \@val;
5489
+ } elsif (ref $$valPt eq 'HASH') {
5490
+ my %val = %{$$valPt}; # make a copy to avoid filtering twice
5491
+ $self->Filter($filter, \$val{$_}) and $rtnVal = 1 foreach keys %val;
5492
+ $$valPt = \%val;
5493
+ } else {
5494
+ $rtnVal = 1;
5447
5495
  }
5496
+ return $rtnVal;
5448
5497
  }
5449
5498
 
5450
5499
  #------------------------------------------------------------------------------
@@ -7555,7 +7604,7 @@ sub ProcessDirectory($$$;$)
7555
7604
 
7556
7605
  #------------------------------------------------------------------------------
7557
7606
  # Get Metadata path
7558
- # Inputs: 0) Exiftool object ref
7607
+ # Inputs: 0) ExifTool object ref
7559
7608
  # Return: Metadata path string
7560
7609
  sub MetadataPath($)
7561
7610
  {
@@ -8197,7 +8246,7 @@ sub VerboseDir($$;$$)
8197
8246
  }
8198
8247
  my $indent = substr($$self{INDENT}, 0, -2);
8199
8248
  my $out = $$self{OPTIONS}{TextOut};
8200
- my $str = $entries ? " with $entries entries" : '';
8249
+ my $str = ($entries or defined $entries and not $size) ? " with $entries entries" : '';
8201
8250
  $str .= ", $size bytes" if $size;
8202
8251
  print $out "$indent+ [$name directory$str]\n";
8203
8252
  }