exiftool_vendored 11.99.0 → 12.11.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 +201 -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 +172 -99
  8. data/bin/lib/Image/ExifTool.pm +170 -117
  9. data/bin/lib/Image/ExifTool.pod +132 -97
  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 +202 -13
  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/ID3.pm +86 -12
  26. data/bin/lib/Image/ExifTool/IPTC.pm +1 -0
  27. data/bin/lib/Image/ExifTool/Import.pm +12 -9
  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 +1 -1
  32. data/bin/lib/Image/ExifTool/MPF.pm +2 -2
  33. data/bin/lib/Image/ExifTool/MacOS.pm +154 -38
  34. data/bin/lib/Image/ExifTool/Matroska.pm +3 -1
  35. data/bin/lib/Image/ExifTool/Minolta.pm +7 -2
  36. data/bin/lib/Image/ExifTool/Nikon.pm +143 -17
  37. data/bin/lib/Image/ExifTool/Olympus.pm +40 -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 +11 -3
  44. data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
  45. data/bin/lib/Image/ExifTool/QuickTime.pm +240 -37
  46. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +419 -60
  47. data/bin/lib/Image/ExifTool/README +25 -21
  48. data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
  49. data/bin/lib/Image/ExifTool/Radiance.pm +7 -2
  50. data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
  51. data/bin/lib/Image/ExifTool/Shift.pl +1 -0
  52. data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
  53. data/bin/lib/Image/ExifTool/Sony.pm +423 -39
  54. data/bin/lib/Image/ExifTool/Stim.pm +2 -2
  55. data/bin/lib/Image/ExifTool/TagLookup.pm +5798 -5675
  56. data/bin/lib/Image/ExifTool/TagNames.pod +575 -100
  57. data/bin/lib/Image/ExifTool/Validate.pm +4 -4
  58. data/bin/lib/Image/ExifTool/WriteExif.pl +1 -0
  59. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +30 -21
  60. data/bin/lib/Image/ExifTool/Writer.pl +49 -24
  61. data/bin/lib/Image/ExifTool/XMP.pm +99 -17
  62. data/bin/lib/Image/ExifTool/XMP2.pl +1 -0
  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 +9 -8
@@ -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.99';
31
+ $VERSION = '12.11';
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
@@ -2486,6 +2505,7 @@ sub ExtractInfo($;@)
2486
2505
  } else {
2487
2506
  $self->Error('Unknown file type');
2488
2507
  }
2508
+ $self->BuildCompositeTags() if $fast == 4 and $$options{Composite};
2489
2509
  last; # don't read the file
2490
2510
  }
2491
2511
  if (@fileTypeList) {
@@ -3095,30 +3115,9 @@ sub GetValue($$;$)
3095
3115
  }
3096
3116
  if (ref $conv eq 'HASH') {
3097
3117
  # 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 {
3118
+ if (not defined($value = $$conv{$val})) {
3109
3119
  if ($$conv{BITMASK}) {
3110
3120
  $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
3121
  } else {
3123
3122
  # use alternate conversion routine if available
3124
3123
  if ($$conv{OTHER}) {
@@ -3131,12 +3130,30 @@ sub GetValue($$;$)
3131
3130
  if ($$tagInfo{PrintHex} and $val and IsInt($val) and
3132
3131
  $convType eq 'PrintConv')
3133
3132
  {
3134
- $val = sprintf('0x%x',$val);
3133
+ $value = sprintf('Unknown (0x%x)',$val);
3134
+ } else {
3135
+ $value = "Unknown ($val)";
3135
3136
  }
3136
- $value = "Unknown ($val)";
3137
3137
  }
3138
3138
  }
3139
3139
  }
3140
+ # override with our localized language PrintConv if available
3141
+ my $tmp;
3142
+ if ($$self{CUR_LANG} and $convType eq 'PrintConv' and
3143
+ # (no need to check for lang-alt tag names -- they won't have a PrintConv)
3144
+ ref($tmp = $$self{CUR_LANG}{$$tagInfo{Name}}) eq 'HASH' and
3145
+ ($tmp = $$tmp{PrintConv}))
3146
+ {
3147
+ if ($$conv{BITMASK} and not defined $$conv{$val}) {
3148
+ my @vals = split ', ', $value;
3149
+ foreach (@vals) {
3150
+ $_ = $$tmp{$_} if defined $$tmp{$_};
3151
+ }
3152
+ $value = join ', ', @vals;
3153
+ } elsif (defined($tmp = $$tmp{$value})) {
3154
+ $value = $self->Decode($tmp, 'UTF8');
3155
+ }
3156
+ }
3140
3157
  } else {
3141
3158
  # call subroutine or do eval to convert value
3142
3159
  local $SIG{'__WARN__'} = \&SetWarning;
@@ -3294,7 +3311,7 @@ sub GetGroup($$;$)
3294
3311
  {
3295
3312
  local $_;
3296
3313
  my ($self, $tag, $family) = @_;
3297
- my ($tagInfo, @groups, @families, $simplify, $byTagInfo, $ex);
3314
+ my ($tagInfo, @groups, @families, $simplify, $byTagInfo, $ex, $noID);
3298
3315
  if (ref $tag eq 'HASH') {
3299
3316
  $tagInfo = $tag;
3300
3317
  $tag = $$tagInfo{Name};
@@ -3325,6 +3342,7 @@ sub GetGroup($$;$)
3325
3342
  $simplify = 1 unless $family =~ /^:/;
3326
3343
  undef $family;
3327
3344
  foreach (0..2) { $groups[$_] = $$groups{$_}; }
3345
+ $noID = 1 if @families == 1 and $families[0] != 7;
3328
3346
  } else {
3329
3347
  return(($ex && $$ex{"G$family"}) || $$groups{$family}) if $family == 0 or $family == 2;
3330
3348
  $groups[1] = $$groups{1};
@@ -3336,14 +3354,29 @@ sub GetGroup($$;$)
3336
3354
  $groups[3] = 'Main';
3337
3355
  $groups[4] = ($tag =~ /\((\d+)\)$/) ? "Copy$1" : '';
3338
3356
  # 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};
3357
+ unless ($byTagInfo) {
3358
+ if ($ex) {
3359
+ $groups[0] = $$ex{G0} if $$ex{G0};
3360
+ $groups[1] = $$ex{G1} =~ /^\+(.*)/ ? "$groups[1]$1" : $$ex{G1} if $$ex{G1};
3361
+ $groups[3] = 'Doc' . $$ex{G3} if $$ex{G3};
3362
+ $groups[5] = $$ex{G5} || $groups[1] if defined $$ex{G5};
3363
+ if (defined $$ex{G6}) {
3364
+ $groups[5] = '' unless defined $groups[5]; # (can't leave a hole in the array)
3365
+ $groups[6] = $$ex{G6};
3366
+ }
3367
+ }
3368
+ # generate tag ID group names unless obviously not needed
3369
+ unless ($noID) {
3370
+ my $id = $$tagInfo{TagID};
3371
+ if (not defined $id) {
3372
+ $id = ''; # (just to be safe)
3373
+ } elsif ($id =~ /^\d+$/) {
3374
+ $id = sprintf('0x%x', $id) if $$self{OPTIONS}{HexTagIDs};
3375
+ } else {
3376
+ $id =~ s/([^-_A-Za-z0-9])/sprintf('%.2x',ord $1)/ge;
3377
+ }
3378
+ $groups[7] = 'ID-' . $id;
3379
+ defined $groups[$_] or $groups[$_] = '' foreach (5,6);
3347
3380
  }
3348
3381
  }
3349
3382
  if ($family) {
@@ -4191,6 +4224,22 @@ sub ParseArguments($;@)
4191
4224
  }
4192
4225
  }
4193
4226
 
4227
+ #------------------------------------------------------------------------------
4228
+ # Does group name match the tag ID?
4229
+ # Inputs: 0) tag ID, 1) group name (with "ID-" removed)
4230
+ # Returns: true on success
4231
+ sub IsSameID($$)
4232
+ {
4233
+ my ($id, $grp) = @_;
4234
+ return 1 if $grp eq $id; # decimal ID's or raw ID's
4235
+ if ($id =~ /^\d+$/) { # numerical numerical ID's may be in hex
4236
+ return 1 if $grp =~ s/^0x0*// and $grp eq sprintf('%x', $id);
4237
+ } else { # other ID's may conform to ExifTool group name conventions
4238
+ return 1 if $id =~ s/([^-_A-Za-z0-9])/sprintf('%.2x',ord $1)/ge and $grp eq $id;
4239
+ }
4240
+ return 0;
4241
+ }
4242
+
4194
4243
  #------------------------------------------------------------------------------
4195
4244
  # Get list of tags in specified group
4196
4245
  # Inputs: 0) ExifTool ref, 1) group spec, 2) tag key or reference to list of tag keys
@@ -4202,40 +4251,41 @@ sub GroupMatches($$$)
4202
4251
  my ($self, $group, $tagList) = @_;
4203
4252
  $tagList = [ $tagList ] unless ref $tagList;
4204
4253
  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);
4254
+ # check each group name individually (eg. "Author:1IPTC")
4255
+ my @grps = split ':', $group;
4256
+ my (@fmys, $g);
4257
+ for ($g=0; $g<@grps; ++$g) {
4258
+ if ($grps[$g] =~ s/^(\d*)(id-)?//i) {
4259
+ $fmys[$g] = $1 if length $1;
4260
+ if ($2) {
4261
+ $fmys[$g] = 7;
4262
+ next; # (don't convert tag ID's to lower case)
4263
+ }
4264
+ }
4265
+ $grps[$g] = lc $grps[$g];
4266
+ $grps[$g] = '' if $grps[$g] eq 'copy0'; # accept 'Copy0' for primary tag
4267
+ }
4268
+ foreach $tag (@$tagList) {
4269
+ my @groups = $self->GetGroup($tag, -1);
4209
4270
  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];
4271
+ my $grp = $grps[$g];
4272
+ next if $grp eq '*' or $grp eq 'all';
4273
+ my $f;
4274
+ if (defined($f = $fmys[$g])) {
4275
+ last unless defined $groups[$f];
4276
+ if ($f == 7) {
4277
+ next if IsSameID($self->GetTagID($tag), $grp);
4221
4278
  } else {
4222
- last unless grep /^$grp$/i, @groups;
4279
+ next if $grp eq lc $groups[$f];
4223
4280
  }
4224
- }
4225
- if ($g == @grps) {
4226
- return $tag unless wantarray;
4227
- push @matches, $tag;
4281
+ last;
4282
+ } else {
4283
+ last unless grep /^$grp$/i, @groups;
4228
4284
  }
4229
4285
  }
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
- }
4286
+ if ($g == @grps) {
4287
+ return $tag unless wantarray;
4288
+ push @matches, $tag;
4239
4289
  }
4240
4290
  }
4241
4291
  return wantarray ? @matches : $matches[0];
@@ -4694,13 +4744,13 @@ sub AddCompositeTags($;$)
4694
4744
  my ($module, $prefix, $tagID);
4695
4745
  unless (ref $add) {
4696
4746
  ($prefix = $add) =~ s/.*:://;
4697
- $prefix .= '::';
4698
4747
  $module = $add;
4699
4748
  $add .= '::Composite';
4700
4749
  no strict 'refs';
4701
4750
  $add = \%$add;
4751
+ $prefix .= '-';
4702
4752
  } else {
4703
- $prefix = 'UserDefined::';
4753
+ $prefix = 'UserDefined-';
4704
4754
  }
4705
4755
  my $defaultGroups = $$add{GROUPS};
4706
4756
  my $compTable = GetTagTable('Image::ExifTool::Composite');
@@ -5415,36 +5465,38 @@ sub GetDescriptions($$)
5415
5465
 
5416
5466
  #------------------------------------------------------------------------------
5417
5467
  # 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($$@)
5468
+ # Inputs: 0) ExifTool ref, 1) filter expression, 2) reference to value to filter
5469
+ # Returns: true unless a filter returned undef; changes value if necessary
5470
+ sub Filter($$$)
5421
5471
  {
5422
5472
  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
- }
5473
+ my ($self, $filter, $valPt) = @_;
5474
+ return 1 unless defined $filter and defined $$valPt;
5475
+ my $rtnVal;
5476
+ if (not ref $$valPt) {
5477
+ $_ = $$valPt;
5478
+ #### eval Filter ($_, $self)
5479
+ eval $filter;
5480
+ if (defined $_) {
5481
+ $$valPt = $_;
5482
+ $rtnVal = 1;
5483
+ }
5484
+ } elsif (ref $$valPt eq 'SCALAR') {
5485
+ my $val = $$$valPt; # make a copy to avoid filtering twice
5486
+ $rtnVal = $self->Filter($filter, \$val);
5487
+ $$valPt = \$val;
5488
+ } elsif (ref $$valPt eq 'ARRAY') {
5489
+ my @val = @{$$valPt}; # make a copy to avoid filtering twice
5490
+ $self->Filter($filter, \$_) and $rtnVal = 1 foreach @val;
5491
+ $$valPt = \@val;
5492
+ } elsif (ref $$valPt eq 'HASH') {
5493
+ my %val = %{$$valPt}; # make a copy to avoid filtering twice
5494
+ $self->Filter($filter, \$val{$_}) and $rtnVal = 1 foreach keys %val;
5495
+ $$valPt = \%val;
5496
+ } else {
5497
+ $rtnVal = 1;
5447
5498
  }
5499
+ return $rtnVal;
5448
5500
  }
5449
5501
 
5450
5502
  #------------------------------------------------------------------------------
@@ -5681,12 +5733,12 @@ sub ConvertFileSize($)
5681
5733
  {
5682
5734
  my $val = shift;
5683
5735
  $val < 2048 and return "$val bytes";
5684
- $val < 10240 and return sprintf('%.1f kB', $val / 1024);
5685
- $val < 2097152 and return sprintf('%.0f kB', $val / 1024);
5686
- $val < 10485760 and return sprintf('%.1f MB', $val / 1048576);
5687
- $val < 2147483648 and return sprintf('%.0f MB', $val / 1048576);
5688
- $val < 10737418240 and return sprintf('%.1f GB', $val / 1073741824);
5689
- return sprintf('%.0f GB', $val / 1073741824);
5736
+ $val < 10240 and return sprintf('%.1f KiB', $val / 1024);
5737
+ $val < 2097152 and return sprintf('%.0f KiB', $val / 1024);
5738
+ $val < 10485760 and return sprintf('%.1f MiB', $val / 1048576);
5739
+ $val < 2147483648 and return sprintf('%.0f MiB', $val / 1048576);
5740
+ $val < 10737418240 and return sprintf('%.1f GiB', $val / 1073741824);
5741
+ return sprintf('%.0f GiB', $val / 1073741824);
5690
5742
  }
5691
5743
 
5692
5744
  #------------------------------------------------------------------------------
@@ -7096,6 +7148,7 @@ sub DoProcessTIFF($$;$)
7096
7148
  # no longer do this because various files use different values
7097
7149
  # (TIFF=0x2a, RW2/RWL=0x55, HDP=0xbc, BTF=0x2b, ORF=0x4f52/0x5352/0x????)
7098
7150
  # return 0 unless $identifier == 0x2a;
7151
+ $self->Warn('Invalid magic number in EXIF TIFF header') if $fileType eq 'APP1' and $identifier != 0x2a;
7099
7152
 
7100
7153
  # get offset to IFD0
7101
7154
  return 0 if length $$dataPt < 8;
@@ -7555,7 +7608,7 @@ sub ProcessDirectory($$$;$)
7555
7608
 
7556
7609
  #------------------------------------------------------------------------------
7557
7610
  # Get Metadata path
7558
- # Inputs: 0) Exiftool object ref
7611
+ # Inputs: 0) ExifTool object ref
7559
7612
  # Return: Metadata path string
7560
7613
  sub MetadataPath($)
7561
7614
  {
@@ -7747,7 +7800,7 @@ sub HandleTag($$$$;%)
7747
7800
  my ($subdir, $format, $noTagInfo, $rational);
7748
7801
 
7749
7802
  if ($tagInfo) {
7750
- $subdir = $$tagInfo{SubDirectory}
7803
+ $subdir = $$tagInfo{SubDirectory};
7751
7804
  } else {
7752
7805
  return undef unless $verbose;
7753
7806
  $tagInfo = { Name => "tag $tag" }; # create temporary tagInfo hash
@@ -8197,7 +8250,7 @@ sub VerboseDir($$;$$)
8197
8250
  }
8198
8251
  my $indent = substr($$self{INDENT}, 0, -2);
8199
8252
  my $out = $$self{OPTIONS}{TextOut};
8200
- my $str = $entries ? " with $entries entries" : '';
8253
+ my $str = ($entries or defined $entries and not $size) ? " with $entries entries" : '';
8201
8254
  $str .= ", $size bytes" if $size;
8202
8255
  print $out "$indent+ [$name directory$str]\n";
8203
8256
  }