exiftool_vendored 11.94.0 → 12.06.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 (62) hide show
  1. checksums.yaml +5 -5
  2. data/bin/Changes +163 -3
  3. data/bin/MANIFEST +5 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +32 -32
  7. data/bin/exiftool +152 -52
  8. data/bin/lib/Image/ExifTool.pm +166 -115
  9. data/bin/lib/Image/ExifTool.pod +108 -81
  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 +6 -3
  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 +16 -3
  17. data/bin/lib/Image/ExifTool/Exif.pm +15 -6
  18. data/bin/lib/Image/ExifTool/Font.pm +9 -2
  19. data/bin/lib/Image/ExifTool/GIF.pm +5 -0
  20. data/bin/lib/Image/ExifTool/GeoTiff.pm +2 -0
  21. data/bin/lib/Image/ExifTool/Geotag.pm +69 -21
  22. data/bin/lib/Image/ExifTool/GoPro.pm +10 -1
  23. data/bin/lib/Image/ExifTool/H264.pm +1 -1
  24. data/bin/lib/Image/ExifTool/HtmlDump.pm +2 -2
  25. data/bin/lib/Image/ExifTool/ID3.pm +91 -12
  26. data/bin/lib/Image/ExifTool/Lang/de.pm +3 -1
  27. data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
  28. data/bin/lib/Image/ExifTool/M2TS.pm +44 -24
  29. data/bin/lib/Image/ExifTool/MWG.pm +9 -1
  30. data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
  31. data/bin/lib/Image/ExifTool/Minolta.pm +3 -2
  32. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +11 -10
  33. data/bin/lib/Image/ExifTool/Nikon.pm +156 -18
  34. data/bin/lib/Image/ExifTool/Olympus.pm +34 -17
  35. data/bin/lib/Image/ExifTool/PNG.pm +14 -3
  36. data/bin/lib/Image/ExifTool/PPM.pm +5 -5
  37. data/bin/lib/Image/ExifTool/Panasonic.pm +147 -13
  38. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +33 -0
  39. data/bin/lib/Image/ExifTool/Parrot.pm +2 -1
  40. data/bin/lib/Image/ExifTool/Pentax.pm +3 -1
  41. data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
  42. data/bin/lib/Image/ExifTool/QuickTime.pm +277 -33
  43. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +460 -67
  44. data/bin/lib/Image/ExifTool/README +21 -20
  45. data/bin/lib/Image/ExifTool/RIFF.pm +123 -3
  46. data/bin/lib/Image/ExifTool/RTF.pm +12 -7
  47. data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
  48. data/bin/lib/Image/ExifTool/Shift.pl +1 -0
  49. data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
  50. data/bin/lib/Image/ExifTool/Sony.pm +379 -12
  51. data/bin/lib/Image/ExifTool/TagLookup.pm +1959 -1874
  52. data/bin/lib/Image/ExifTool/TagNames.pod +346 -55
  53. data/bin/lib/Image/ExifTool/Validate.pm +4 -4
  54. data/bin/lib/Image/ExifTool/WriteExif.pl +3 -2
  55. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +26 -15
  56. data/bin/lib/Image/ExifTool/Writer.pl +52 -23
  57. data/bin/lib/Image/ExifTool/XMP.pm +41 -4
  58. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  59. data/bin/lib/Image/ExifTool/ZISRAW.pm +123 -0
  60. data/bin/perl-Image-ExifTool.spec +31 -31
  61. data/lib/exiftool_vendored/version.rb +1 -1
  62. metadata +4 -4
@@ -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.94';
31
+ $VERSION = '12.06';
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::MDItem MacOS::XAttr
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
+ PHP PCX DCX DWF DWG WTV Torrent VCard LRI R3D AA PDB MOI ISO
192
+ 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
@@ -253,6 +254,7 @@ my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
253
254
  CRW => ['CRW', 'Canon RAW format'],
254
255
  CS1 => ['PSD', 'Sinar CaptureShop 1-Shot RAW'],
255
256
  CSV => ['TXT', 'Comma-Separated Values'],
257
+ CZI => ['CZI', 'Zeiss Integrated Software RAW'],
256
258
  DC3 => 'DICM',
257
259
  DCM => 'DICM',
258
260
  DCP => ['TIFF', 'DNG Camera Profile'],
@@ -527,6 +529,8 @@ my %createTypes = map { $_ => 1 } qw(XMP ICC MIE VRD DR4 EXIF EXV);
527
529
  XLTM => [['ZIP','FPX'], 'Office Open XML Spreadsheet Template Macro-enabled'],
528
530
  XLTX => [['ZIP','FPX'], 'Office Open XML Spreadsheet Template'],
529
531
  XMP => ['XMP', 'Extensible Metadata Platform'],
532
+ WOFF => ['Font', 'Web Open Font Format'],
533
+ WOFF2=> ['Font', 'Web Open Font Format2'],
530
534
  WTV => ['WTV', 'Windows recorded TV show'],
531
535
  ZIP => ['ZIP', 'ZIP archive'],
532
536
  );
@@ -581,6 +585,7 @@ my %fileDescription = (
581
585
  CRM => 'video/x-canon-crm',
582
586
  CRW => 'image/x-canon-crw',
583
587
  CSV => 'text/csv',
588
+ CZI => 'image/x-zeiss-czi', #PH (NC)
584
589
  DCP => 'application/octet-stream', #PH (NC)
585
590
  DCR => 'image/x-kodak-dcr',
586
591
  DCX => 'image/dcx',
@@ -781,6 +786,7 @@ my %moduleName = (
781
786
  CRW => 'CanonRaw',
782
787
  CHM => 'EXE',
783
788
  COS => 'CaptureOne',
789
+ CZI => 'ZISRAW',
784
790
  DEX => 0,
785
791
  DOCX => 'OOXML',
786
792
  DCX => 0,
@@ -851,6 +857,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
851
857
  BZ2 => 'BZh[1-9]\x31\x41\x59\x26\x53\x59',
852
858
  CHM => 'ITSF.{20}\x10\xfd\x01\x7c\xaa\x7b\xd0\x11\x9e\x0c\0\xa0\xc9\x22\xe6\xec',
853
859
  CRW => '(II|MM).{4}HEAP(CCDR|JPGM)',
860
+ CZI => 'ZISRAWFILE\0{6}',
854
861
  DCX => '\xb1\x68\xde\x3a',
855
862
  DEX => "dex\n035\0",
856
863
  DICOM=> '(.{128}DICM|\0[\x02\x04\x06\x08]\0[\0-\x20]|[\x02\x04\x06\x08]\0[\0-\x20]\0)',
@@ -872,7 +879,7 @@ $testLen = 1024; # number of bytes to read when testing for magic number
872
879
  FLIR => '[AF]FF\0',
873
880
  FLV => 'FLV\x01',
874
881
  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)',
882
+ '(.{6})?%!(PS-(AdobeFont-|Bitstream )|FontType1-)|Start(Comp|Master)?FontMetrics|wOF[F2])',
876
883
  FPF => 'FPF Public Image Format\0',
877
884
  FPX => '\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1',
878
885
  GIF => 'GIF8[79]a',
@@ -1445,6 +1452,11 @@ my %systemTagsNotes = (
1445
1452
  return Image::ExifTool::XMP::CheckXMP($self, $tagInfo, \$val);
1446
1453
  },
1447
1454
  },
1455
+ XML => {
1456
+ Notes => 'the XML data block, extracted for some file types',
1457
+ Groups => { 0 => 'XML', 1 => 'XML' },
1458
+ Binary => 1,
1459
+ },
1448
1460
  ICC_Profile => {
1449
1461
  Notes => q{
1450
1462
  the full ICC_Profile data block. This tag is generated only if specifically
@@ -2236,6 +2248,7 @@ sub ClearOptions($)
2236
2248
  GeoSpeedRef => undef, # geotag GPSSpeedRef
2237
2249
  GlobalTimeShift => undef, # apply time shift to all extracted date/time values
2238
2250
  # Group# => undef, # return tags for specified groups in family #
2251
+ HexTagIDs => 0, # use hex tag ID's in family 7 group names
2239
2252
  HtmlDump => 0, # HTML dump (0-3, higher # = bigger limit)
2240
2253
  HtmlDumpBase => undef, # base address for HTML dump
2241
2254
  IgnoreMinorErrors => undef, # ignore minor errors when reading/writing
@@ -2249,6 +2262,7 @@ sub ClearOptions($)
2249
2262
  MakerNotes => undef, # extract maker notes as a block
2250
2263
  MDItemTags => undef, # extract MacOS metadata item tags
2251
2264
  MissingTagValue =>undef,# value for missing tags when expanded in expressions
2265
+ NoMultiExif => undef, # raise error when writing multi-segment EXIF
2252
2266
  NoPDFList => undef, # flag to avoid splitting PDF List-type tag values
2253
2267
  Password => undef, # password for password-protected PDF documents
2254
2268
  PrintConv => 1, # flag to enable print conversion
@@ -3095,30 +3109,9 @@ sub GetValue($$;$)
3095
3109
  }
3096
3110
  if (ref $conv eq 'HASH') {
3097
3111
  # 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 {
3112
+ if (not defined($value = $$conv{$val})) {
3109
3113
  if ($$conv{BITMASK}) {
3110
3114
  $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
3115
  } else {
3123
3116
  # use alternate conversion routine if available
3124
3117
  if ($$conv{OTHER}) {
@@ -3131,12 +3124,30 @@ sub GetValue($$;$)
3131
3124
  if ($$tagInfo{PrintHex} and $val and IsInt($val) and
3132
3125
  $convType eq 'PrintConv')
3133
3126
  {
3134
- $val = sprintf('0x%x',$val);
3127
+ $value = sprintf('Unknown (0x%x)',$val);
3128
+ } else {
3129
+ $value = "Unknown ($val)";
3135
3130
  }
3136
- $value = "Unknown ($val)";
3137
3131
  }
3138
3132
  }
3139
3133
  }
3134
+ # override with our localized language PrintConv if available
3135
+ my $tmp;
3136
+ if ($$self{CUR_LANG} and $convType eq 'PrintConv' and
3137
+ # (no need to check for lang-alt tag names -- they won't have a PrintConv)
3138
+ ref($tmp = $$self{CUR_LANG}{$$tagInfo{Name}}) eq 'HASH' and
3139
+ ($tmp = $$tmp{PrintConv}))
3140
+ {
3141
+ if ($$conv{BITMASK} and not defined $$conv{$val}) {
3142
+ my @vals = split ', ', $value;
3143
+ foreach (@vals) {
3144
+ $_ = $$tmp{$_} if defined $$tmp{$_};
3145
+ }
3146
+ $value = join ', ', @vals;
3147
+ } elsif (defined($tmp = $$tmp{$value})) {
3148
+ $value = $self->Decode($tmp, 'UTF8');
3149
+ }
3150
+ }
3140
3151
  } else {
3141
3152
  # call subroutine or do eval to convert value
3142
3153
  local $SIG{'__WARN__'} = \&SetWarning;
@@ -3198,7 +3209,7 @@ sub GetValue($$;$)
3198
3209
  # $valueConv is undefined if there was no print conversion done
3199
3210
  $valueConv = $value;
3200
3211
  }
3201
- Filter($$self{OPTIONS}{Filter}, \$value);
3212
+ $self->Filter($$self{OPTIONS}{Filter}, \$value);
3202
3213
  # return Both values as a list (ValueConv, PrintConv)
3203
3214
  return ($valueConv, $value);
3204
3215
  }
@@ -3206,7 +3217,7 @@ sub GetValue($$;$)
3206
3217
  DoEscape($value, $$self{ESCAPE_PROC}) if $$self{ESCAPE_PROC};
3207
3218
 
3208
3219
  # filter if necessary
3209
- Filter($$self{OPTIONS}{Filter}, \$value) if $$self{OPTIONS}{Filter} and $type eq 'PrintConv';
3220
+ $self->Filter($$self{OPTIONS}{Filter}, \$value) if $$self{OPTIONS}{Filter} and $type eq 'PrintConv';
3210
3221
 
3211
3222
  if (ref $value eq 'ARRAY') {
3212
3223
  if (defined $$self{OPTIONS}{ListItem}) {
@@ -3294,7 +3305,7 @@ sub GetGroup($$;$)
3294
3305
  {
3295
3306
  local $_;
3296
3307
  my ($self, $tag, $family) = @_;
3297
- my ($tagInfo, @groups, @families, $simplify, $byTagInfo, $ex);
3308
+ my ($tagInfo, @groups, @families, $simplify, $byTagInfo, $ex, $noID);
3298
3309
  if (ref $tag eq 'HASH') {
3299
3310
  $tagInfo = $tag;
3300
3311
  $tag = $$tagInfo{Name};
@@ -3325,6 +3336,7 @@ sub GetGroup($$;$)
3325
3336
  $simplify = 1 unless $family =~ /^:/;
3326
3337
  undef $family;
3327
3338
  foreach (0..2) { $groups[$_] = $$groups{$_}; }
3339
+ $noID = 1 if @families == 1 and $families[0] != 7;
3328
3340
  } else {
3329
3341
  return(($ex && $$ex{"G$family"}) || $$groups{$family}) if $family == 0 or $family == 2;
3330
3342
  $groups[1] = $$groups{1};
@@ -3336,14 +3348,29 @@ sub GetGroup($$;$)
3336
3348
  $groups[3] = 'Main';
3337
3349
  $groups[4] = ($tag =~ /\((\d+)\)$/) ? "Copy$1" : '';
3338
3350
  # 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};
3351
+ unless ($byTagInfo) {
3352
+ if ($ex) {
3353
+ $groups[0] = $$ex{G0} if $$ex{G0};
3354
+ $groups[1] = $$ex{G1} =~ /^\+(.*)/ ? "$groups[1]$1" : $$ex{G1} if $$ex{G1};
3355
+ $groups[3] = 'Doc' . $$ex{G3} if $$ex{G3};
3356
+ $groups[5] = $$ex{G5} || $groups[1] if defined $$ex{G5};
3357
+ if (defined $$ex{G6}) {
3358
+ $groups[5] = '' unless defined $groups[5]; # (can't leave a hole in the array)
3359
+ $groups[6] = $$ex{G6};
3360
+ }
3361
+ }
3362
+ # generate tag ID group names unless obviously not needed
3363
+ unless ($noID) {
3364
+ my $id = $$tagInfo{TagID};
3365
+ if (not defined $id) {
3366
+ $id = ''; # (just to be safe)
3367
+ } elsif ($id =~ /^\d+$/) {
3368
+ $id = sprintf('0x%x', $id) if $$self{OPTIONS}{HexTagIDs};
3369
+ } else {
3370
+ $id =~ s/([^-_A-Za-z0-9])/sprintf('%.2x',ord $1)/ge;
3371
+ }
3372
+ $groups[7] = 'ID-' . $id;
3373
+ defined $groups[$_] or $groups[$_] = '' foreach (5,6);
3347
3374
  }
3348
3375
  }
3349
3376
  if ($family) {
@@ -4191,6 +4218,22 @@ sub ParseArguments($;@)
4191
4218
  }
4192
4219
  }
4193
4220
 
4221
+ #------------------------------------------------------------------------------
4222
+ # Does group name match the tag ID?
4223
+ # Inputs: 0) tag ID, 1) group name (with "ID-" removed)
4224
+ # Returns: true on success
4225
+ sub IsSameID($$)
4226
+ {
4227
+ my ($id, $grp) = @_;
4228
+ return 1 if $grp eq $id; # decimal ID's or raw ID's
4229
+ if ($id =~ /^\d+$/) { # numerical numerical ID's may be in hex
4230
+ return 1 if $grp =~ s/^0x0*// and $grp eq sprintf('%x', $id);
4231
+ } else { # other ID's may conform to ExifTool group name conventions
4232
+ return 1 if $id =~ s/([^-_A-Za-z0-9])/sprintf('%.2x',ord $1)/ge and $grp eq $id;
4233
+ }
4234
+ return 0;
4235
+ }
4236
+
4194
4237
  #------------------------------------------------------------------------------
4195
4238
  # Get list of tags in specified group
4196
4239
  # Inputs: 0) ExifTool ref, 1) group spec, 2) tag key or reference to list of tag keys
@@ -4202,40 +4245,41 @@ sub GroupMatches($$$)
4202
4245
  my ($self, $group, $tagList) = @_;
4203
4246
  $tagList = [ $tagList ] unless ref $tagList;
4204
4247
  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);
4248
+ # check each group name individually (eg. "Author:1IPTC")
4249
+ my @grps = split ':', $group;
4250
+ my (@fmys, $g);
4251
+ for ($g=0; $g<@grps; ++$g) {
4252
+ if ($grps[$g] =~ s/^(\d*)(id-)?//i) {
4253
+ $fmys[$g] = $1 if length $1;
4254
+ if ($2) {
4255
+ $fmys[$g] = 7;
4256
+ next; # (don't convert tag ID's to lower case)
4257
+ }
4258
+ }
4259
+ $grps[$g] = lc $grps[$g];
4260
+ $grps[$g] = '' if $grps[$g] eq 'copy0'; # accept 'Copy0' for primary tag
4261
+ }
4262
+ foreach $tag (@$tagList) {
4263
+ my @groups = $self->GetGroup($tag, -1);
4209
4264
  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];
4265
+ my $grp = $grps[$g];
4266
+ next if $grp eq '*' or $grp eq 'all';
4267
+ my $f;
4268
+ if (defined($f = $fmys[$g])) {
4269
+ last unless defined $groups[$f];
4270
+ if ($f == 7) {
4271
+ next if IsSameID($self->GetTagID($tag), $grp);
4221
4272
  } else {
4222
- last unless grep /^$grp$/i, @groups;
4273
+ next if $grp eq lc $groups[$f];
4223
4274
  }
4224
- }
4225
- if ($g == @grps) {
4226
- return $tag unless wantarray;
4227
- push @matches, $tag;
4275
+ last;
4276
+ } else {
4277
+ last unless grep /^$grp$/i, @groups;
4228
4278
  }
4229
4279
  }
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
- }
4280
+ if ($g == @grps) {
4281
+ return $tag unless wantarray;
4282
+ push @matches, $tag;
4239
4283
  }
4240
4284
  }
4241
4285
  return wantarray ? @matches : $matches[0];
@@ -4694,13 +4738,13 @@ sub AddCompositeTags($;$)
4694
4738
  my ($module, $prefix, $tagID);
4695
4739
  unless (ref $add) {
4696
4740
  ($prefix = $add) =~ s/.*:://;
4697
- $prefix .= '::';
4698
4741
  $module = $add;
4699
4742
  $add .= '::Composite';
4700
4743
  no strict 'refs';
4701
4744
  $add = \%$add;
4745
+ $prefix .= '-';
4702
4746
  } else {
4703
- $prefix = 'UserDefined::';
4747
+ $prefix = 'UserDefined-';
4704
4748
  }
4705
4749
  my $defaultGroups = $$add{GROUPS};
4706
4750
  my $compTable = GetTagTable('Image::ExifTool::Composite');
@@ -5415,35 +5459,38 @@ sub GetDescriptions($$)
5415
5459
 
5416
5460
  #------------------------------------------------------------------------------
5417
5461
  # Apply filter to value(s) if necessary
5418
- # Inputs: 0) filter expression, 1-N) references to values(s) to filter
5419
- # Returns: nothing, but changes values if necessary
5420
- sub Filter($@)
5462
+ # Inputs: 0) ExifTool ref, 1) filter expression, 2) reference to value to filter
5463
+ # Returns: true unless a filter returned undef; changes value if necessary
5464
+ sub Filter($$$)
5421
5465
  {
5422
5466
  local $_;
5423
- my $filter = shift;
5424
- return unless defined $filter;
5425
- while (@_) {
5426
- my $valPt = shift;
5427
- next unless defined $$valPt;
5428
- if (not ref $$valPt) {
5429
- $_ = $$valPt;
5430
- #### eval Filter ($_)
5431
- eval $filter;
5432
- $$valPt = $_ if defined $_;
5433
- } elsif (ref $$valPt eq 'SCALAR') {
5434
- my $val = $$$valPt; # make a copy to avoid filtering twice
5435
- Filter($filter, \$val);
5436
- $$valPt = \$val;
5437
- } elsif (ref $$valPt eq 'ARRAY') {
5438
- my @val = @{$$valPt}; # make a copy to avoid filtering twice
5439
- Filter($filter, \$_) foreach @val;
5440
- $$valPt = \@val;
5441
- } elsif (ref $$valPt eq 'HASH') {
5442
- my %val = %{$$valPt}; # make a copy to avoid filtering twice
5443
- Filter($filter, \$val{$_}) foreach keys %val;
5444
- $$valPt = \%val;
5445
- }
5467
+ my ($self, $filter, $valPt) = @_;
5468
+ return 1 unless defined $filter and defined $$valPt;
5469
+ my $rtnVal;
5470
+ if (not ref $$valPt) {
5471
+ $_ = $$valPt;
5472
+ #### eval Filter ($_, $self)
5473
+ eval $filter;
5474
+ if (defined $_) {
5475
+ $$valPt = $_;
5476
+ $rtnVal = 1;
5477
+ }
5478
+ } elsif (ref $$valPt eq 'SCALAR') {
5479
+ my $val = $$$valPt; # make a copy to avoid filtering twice
5480
+ $rtnVal = $self->Filter($filter, \$val);
5481
+ $$valPt = \$val;
5482
+ } elsif (ref $$valPt eq 'ARRAY') {
5483
+ my @val = @{$$valPt}; # make a copy to avoid filtering twice
5484
+ $self->Filter($filter, \$_) and $rtnVal = 1 foreach @val;
5485
+ $$valPt = \@val;
5486
+ } elsif (ref $$valPt eq 'HASH') {
5487
+ my %val = %{$$valPt}; # make a copy to avoid filtering twice
5488
+ $self->Filter($filter, \$val{$_}) and $rtnVal = 1 foreach keys %val;
5489
+ $$valPt = \%val;
5490
+ } else {
5491
+ $rtnVal = 1;
5446
5492
  }
5493
+ return $rtnVal;
5447
5494
  }
5448
5495
 
5449
5496
  #------------------------------------------------------------------------------
@@ -5644,7 +5691,7 @@ sub ConvertUnixTime($;$$)
5644
5691
 
5645
5692
  #------------------------------------------------------------------------------
5646
5693
  # Get Unix time from EXIF-formatted date/time string with optional timezone
5647
- # Inputs: 0) EXIF date/time string, 1) non-zero if time is local
5694
+ # Inputs: 0) EXIF date/time string, 1) non-zero if time is local, or 2 to assume UTC
5648
5695
  # Returns: Unix time (seconds since 0:00 GMT Jan 1, 1970) or undefined on error
5649
5696
  sub GetUnixTime($;$)
5650
5697
  {
@@ -5655,10 +5702,14 @@ sub GetUnixTime($;$)
5655
5702
  my ($tzStr, $tzSec) = (pop(@tm), 0);
5656
5703
  # use specified timezone offset (if given) instead of local system time
5657
5704
  # if we are converting a local time value
5658
- if ($isLocal and $tzStr =~ /(?:Z|([-+])(\d+):(\d+))/i) {
5659
- # use specified timezone if one exists
5660
- $tzSec = ($2 * 60 + $3) * ($1 eq '-' ? -60 : 60) if $1;
5661
- undef $isLocal; # convert using GMT corrected for specified timezone
5705
+ if ($isLocal) {
5706
+ if ($tzStr =~ /(?:Z|([-+])(\d+):(\d+))/i) {
5707
+ # use specified timezone if one exists
5708
+ $tzSec = ($2 * 60 + $3) * ($1 eq '-' ? -60 : 60) if $1;
5709
+ undef $isLocal; # convert using GMT corrected for specified timezone
5710
+ } elsif ($isLocal eq '2') {
5711
+ undef $isLocal;
5712
+ }
5662
5713
  }
5663
5714
  $tm[1] -= 1; # convert month
5664
5715
  @tm = reverse @tm; # change to order required by timelocal()
@@ -7550,7 +7601,7 @@ sub ProcessDirectory($$$;$)
7550
7601
 
7551
7602
  #------------------------------------------------------------------------------
7552
7603
  # Get Metadata path
7553
- # Inputs: 0) Exiftool object ref
7604
+ # Inputs: 0) ExifTool object ref
7554
7605
  # Return: Metadata path string
7555
7606
  sub MetadataPath($)
7556
7607
  {
@@ -8192,7 +8243,7 @@ sub VerboseDir($$;$$)
8192
8243
  }
8193
8244
  my $indent = substr($$self{INDENT}, 0, -2);
8194
8245
  my $out = $$self{OPTIONS}{TextOut};
8195
- my $str = $entries ? " with $entries entries" : '';
8246
+ my $str = ($entries or defined $entries and not $size) ? " with $entries entries" : '';
8196
8247
  $str .= ", $size bytes" if $size;
8197
8248
  print $out "$indent+ [$name directory$str]\n";
8198
8249
  }