exiftool-vendored.exe 12.30.0 → 12.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/bin/exiftool_files/Changes +129 -3
  2. package/bin/exiftool_files/README +2 -2
  3. package/bin/exiftool_files/arg_files/xmp2exif.args +2 -1
  4. package/bin/exiftool_files/config_files/example.config +1 -1
  5. package/bin/exiftool_files/exiftool.pl +100 -58
  6. package/bin/exiftool_files/fmt_files/gpx.fmt +1 -1
  7. package/bin/exiftool_files/fmt_files/gpx_wpt.fmt +1 -1
  8. package/bin/exiftool_files/lib/Image/ExifTool/BuildTagLookup.pm +13 -3
  9. package/bin/exiftool_files/lib/Image/ExifTool/CBOR.pm +331 -0
  10. package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +175 -12
  11. package/bin/exiftool_files/lib/Image/ExifTool/CanonCustom.pm +12 -2
  12. package/bin/exiftool_files/lib/Image/ExifTool/Charset.pm +2 -0
  13. package/bin/exiftool_files/lib/Image/ExifTool/DPX.pm +13 -2
  14. package/bin/exiftool_files/lib/Image/ExifTool/DarwinCore.pm +2 -2
  15. package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +109 -3
  16. package/bin/exiftool_files/lib/Image/ExifTool/FLIR.pm +33 -8
  17. package/bin/exiftool_files/lib/Image/ExifTool/GIF.pm +5 -1
  18. package/bin/exiftool_files/lib/Image/ExifTool/GPS.pm +14 -10
  19. package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +13 -2
  20. package/bin/exiftool_files/lib/Image/ExifTool/GoPro.pm +16 -1
  21. package/bin/exiftool_files/lib/Image/ExifTool/ICC_Profile.pm +96 -4
  22. package/bin/exiftool_files/lib/Image/ExifTool/JSON.pm +7 -3
  23. package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +154 -24
  24. package/bin/exiftool_files/lib/Image/ExifTool/M2TS.pm +27 -12
  25. package/bin/exiftool_files/lib/Image/ExifTool/MacOS.pm +2 -2
  26. package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +1204 -96
  27. package/bin/exiftool_files/lib/Image/ExifTool/NikonCustom.pm +5 -1
  28. package/bin/exiftool_files/lib/Image/ExifTool/NikonSettings.pm +135 -71
  29. package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +5 -1
  30. package/bin/exiftool_files/lib/Image/ExifTool/OpenEXR.pm +4 -2
  31. package/bin/exiftool_files/lib/Image/ExifTool/PDF.pm +11 -12
  32. package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +4 -1
  33. package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +2 -2
  34. package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +2 -1
  35. package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +69 -10
  36. package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +141 -111
  37. package/bin/exiftool_files/lib/Image/ExifTool/README +9 -2
  38. package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +56 -13
  39. package/bin/exiftool_files/lib/Image/ExifTool/TagInfoXML.pm +9 -4
  40. package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +6473 -5827
  41. package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +1401 -54
  42. package/bin/exiftool_files/lib/Image/ExifTool/WritePDF.pl +1 -0
  43. package/bin/exiftool_files/lib/Image/ExifTool/WritePNG.pl +2 -0
  44. package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +10 -0
  45. package/bin/exiftool_files/lib/Image/ExifTool/WriteXMP.pl +10 -11
  46. package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +50 -5
  47. package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +125 -31
  48. package/bin/exiftool_files/lib/Image/ExifTool/XMP2.pl +3 -1
  49. package/bin/exiftool_files/lib/Image/ExifTool/XMPStruct.pl +3 -1
  50. package/bin/exiftool_files/lib/Image/ExifTool.pm +8931 -8864
  51. package/bin/exiftool_files/lib/Image/ExifTool.pod +21 -13
  52. package/package.json +3 -3
@@ -24,7 +24,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
24
24
  use Image::ExifTool::Exif;
25
25
  use Image::ExifTool::GPS;
26
26
 
27
- $VERSION = '1.18';
27
+ $VERSION = '1.19';
28
28
 
29
29
  sub ProcessFLIR($$;$);
30
30
  sub ProcessFLIRText($$$);
@@ -99,7 +99,7 @@ my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' );
99
99
  NOTES => q{
100
100
  Information extracted from FLIR FFF images and the APP1 FLIR segment of JPEG
101
101
  images. These tags may also be extracted from the first frame of an FLIR
102
- SEQ file.
102
+ SEQ file, or all frames if the ExtractEmbedded option is used.
103
103
  },
104
104
  "_header" => {
105
105
  Name => 'FFFHeader',
@@ -1457,6 +1457,7 @@ sub ProcessFLIR($$;$)
1457
1457
  my $raf = $$dirInfo{RAF} || new File::RandomAccess($$dirInfo{DataPt});
1458
1458
  my $verbose = $et->Options('Verbose');
1459
1459
  my $out = $et->Options('TextOut');
1460
+ my $base = $raf->Tell();
1460
1461
  my ($i, $hdr, $buff, $rec);
1461
1462
 
1462
1463
  # read and verify FFF header
@@ -1485,15 +1486,18 @@ sub ProcessFLIR($$;$)
1485
1486
  my $ver = Get32u(\$hdr, 0x14);
1486
1487
  last if $ver >= 100 and $ver < 200; # (have seen 100 and 101 - PH)
1487
1488
  ToggleByteOrder();
1488
- $i and $et->Warn("Unsupported FLIR $type version"), return 1;
1489
+ next unless $i;
1490
+ return 0 if $$et{DOC_NUM};
1491
+ $et->Warn("Unsupported FLIR $type version");
1492
+ return 1;
1489
1493
  }
1490
1494
 
1491
1495
  # read the FLIR record directory
1492
1496
  my $pos = Get32u(\$hdr, 0x18);
1493
1497
  my $num = Get32u(\$hdr, 0x1c);
1494
- unless ($raf->Seek($pos) and $raf->Read($buff, $num * 0x20) == $num * 0x20) {
1498
+ unless ($raf->Seek($base+$pos) and $raf->Read($buff, $num * 0x20) == $num * 0x20) {
1495
1499
  $et->Warn('Truncated FLIR FFF directory');
1496
- return 1;
1500
+ return $$et{DOC_NUM} ? 0 : 1;
1497
1501
  }
1498
1502
 
1499
1503
  unless ($tagTablePtr) {
@@ -1504,6 +1508,7 @@ sub ProcessFLIR($$;$)
1504
1508
  # process the header data
1505
1509
  $et->HandleTag($tagTablePtr, '_header', $hdr);
1506
1510
 
1511
+ my $success = 1;
1507
1512
  my $oldIndent = $$et{INDENT};
1508
1513
  $$et{INDENT} .= '| ';
1509
1514
  $et->VerboseDir($type, $num);
@@ -1533,12 +1538,22 @@ sub ProcessFLIR($$;$)
1533
1538
  $verbose and printf $out "%s%d) FLIR Record 0x%.2x, offset 0x%.4x, length 0x%.4x\n",
1534
1539
  $$et{INDENT}, $i, $recType, $recPos, $recLen;
1535
1540
 
1536
- unless ($raf->Seek($recPos) and $raf->Read($rec, $recLen) == $recLen) {
1537
- $et->Warn('Invalid FLIR record');
1541
+ # skip RawData records for embedded documents
1542
+ if ($recType == 1 and $$et{DOC_NUM}) {
1543
+ $raf->Seek($base+$recPos+$recLen) or $success = 0, last;
1544
+ next;
1545
+ }
1546
+ unless ($raf->Seek($base+$recPos) and $raf->Read($rec, $recLen) == $recLen) {
1547
+ if ($$et{DOC_NUM}) {
1548
+ $success = 0; # abort processing more documents
1549
+ } else {
1550
+ $et->Warn('Invalid FLIR record');
1551
+ }
1538
1552
  last;
1539
1553
  }
1540
1554
  if ($$tagTablePtr{$recType}) {
1541
1555
  $et->HandleTag($tagTablePtr, $recType, undef,
1556
+ Base => $base,
1542
1557
  DataPt => \$rec,
1543
1558
  DataPos => $recPos,
1544
1559
  Start => 0,
@@ -1550,7 +1565,17 @@ sub ProcessFLIR($$;$)
1550
1565
  }
1551
1566
  delete $$et{SET_GROUP0};
1552
1567
  $$et{INDENT} = $oldIndent;
1553
- return 1;
1568
+
1569
+ # extract information from subsequent frames in SEQ file if ExtractEmbedded is used
1570
+ if ($$dirInfo{RAF} and $et->Options('ExtractEmbedded') and not $$et{DOC_NUM}) {
1571
+ for (;;) {
1572
+ $$et{DOC_NUM} = $$et{DOC_COUNT} + 1;
1573
+ last unless ProcessFLIR($et, $dirInfo, $tagTablePtr);
1574
+ # (DOC_COUNT will be incremented automatically if we extracted any tags)
1575
+ }
1576
+ delete $$et{DOC_NUM};
1577
+ }
1578
+ return $success;
1554
1579
  }
1555
1580
 
1556
1581
  #------------------------------------------------------------------------------
@@ -20,7 +20,7 @@ use strict;
20
20
  use vars qw($VERSION);
21
21
  use Image::ExifTool qw(:DataAccess :Utils);
22
22
 
23
- $VERSION = '1.18';
23
+ $VERSION = '1.19';
24
24
 
25
25
  # road map of directory locations in GIF images
26
26
  my %gifMap = (
@@ -54,6 +54,7 @@ my %gifMap = (
54
54
  Extensions => { # (for documentation only)
55
55
  SubDirectory => { TagTable => 'Image::ExifTool::GIF::Extensions' },
56
56
  },
57
+ TransparentColor => { },
57
58
  );
58
59
 
59
60
  # GIF89a application extensions:
@@ -475,6 +476,9 @@ Block:
475
476
  my $delay = Get16u(\$buff, 1);
476
477
  $delayTime += $delay;
477
478
  $verbose and printf $out "Graphic Control: delay=%.2f\n", $delay / 100;
479
+ # get transparent colour
480
+ my $bits = Get8u(\$buff, 0);
481
+ $et->HandleTag($tagTablePtr, 'TransparentColor', Get8u(\$buff,3)) if $bits & 0x01;
478
482
  $raf->Seek(-$length, 1) or last;
479
483
 
480
484
  } elsif ($a == 0x01 and $length == 12) { # plain text extension
@@ -137,22 +137,26 @@ my %coordConv = (
137
137
  my ($v, $et) = @_;
138
138
  $v = $et->TimeNow() if lc($v) eq 'now';
139
139
  my @tz;
140
- if ($v =~ s/([-+])(.*)//s) { # remove timezone
140
+ if ($v =~ s/([-+])(\d{1,2}):?(\d{2})\s*(DST)?$//i) { # remove timezone
141
141
  my $s = $1 eq '-' ? 1 : -1; # opposite sign to convert back to UTC
142
142
  my $t = $2;
143
- @tz = ($s*$1, $s*$2) if $t =~ /^(\d{2}):?(\d{2})\s*$/;
143
+ @tz = ($s*$2, $s*$3);
144
144
  }
145
- my @a = ($v =~ /((?=\d|\.\d)\d*(?:\.\d*)?)/g);
146
- push @a, '00' while @a < 3;
145
+ # (note: we must allow '.' as a time separator, eg. '10.30.00', with is tricky due to decimal seconds)
146
+ # YYYYmmddHHMMSS[.ss] format
147
+ my @a = ($v =~ /^[^\d]*\d{4}[^\d]*\d{1,2}[^\d]*\d{1,2}[^\d]*(\d{1,2})[^\d]*(\d{2})[^\d]*(\d{2}(?:\.\d+)?)[^\d]*$/);
148
+ # HHMMSS[.ss] format
149
+ @a or @a = ($v =~ /^[^\d]*(\d{1,2})[^\d]*(\d{2})[^\d]*(\d{2}(?:\.\d+)?)[^\d]*$/);
150
+ @a or warn('Invalid time (use HH:MM:SS[.ss][+/-HH:MM|Z])'), return undef;
147
151
  if (@tz) {
148
152
  # adjust to UTC
149
- $a[-2] += $tz[1];
150
- $a[-3] += $tz[0];
151
- while ($a[-2] >= 60) { $a[-2] -= 60; ++$a[-3] }
152
- while ($a[-2] < 0) { $a[-2] += 60; --$a[-3] }
153
- $a[-3] = ($a[-3] + 24) % 24;
153
+ $a[1] += $tz[1];
154
+ $a[0] += $tz[0];
155
+ while ($a[1] >= 60) { $a[1] -= 60; ++$a[0] }
156
+ while ($a[1] < 0) { $a[1] += 60; --$a[0] }
157
+ $a[0] = ($a[0] + 24) % 24;
154
158
  }
155
- return "$a[-3]:$a[-2]:$a[-1]";
159
+ return join(':', @a);
156
160
  },
157
161
  },
158
162
  0x0008 => {
@@ -28,7 +28,7 @@ use vars qw($VERSION);
28
28
  use Image::ExifTool qw(:Public);
29
29
  use Image::ExifTool::GPS;
30
30
 
31
- $VERSION = '1.64';
31
+ $VERSION = '1.65';
32
32
 
33
33
  sub JITTER() { return 2 } # maximum time jitter
34
34
 
@@ -262,8 +262,10 @@ sub LoadTrackLog($$;$)
262
262
  $param = 'time';
263
263
  } elsif (/^(Pos)?Lat/i) {
264
264
  $param = 'lat';
265
+ /ref$/i and $param .= 'ref';
265
266
  } elsif (/^(Pos)?Lon/i) {
266
267
  $param = 'lon';
268
+ /ref$/i and $param .= 'ref';
267
269
  } elsif (/^(Pos)?Alt/i) {
268
270
  $param = 'alt';
269
271
  } elsif (/^(Angle)?(Heading|Track)/i) {
@@ -453,7 +455,7 @@ DoneFix: $isDate = 1;
453
455
  # (ExifTool enhancements allow for standard tag names or descriptions as the column headings,
454
456
  # add support for time zones and flexible coordinates, and allow new DateTime and Shift columns)
455
457
  #
456
- my ($param, $date, $secs);
458
+ my ($param, $date, $secs, %neg);
457
459
  foreach $param (@csvHeadings) {
458
460
  my $val = shift @vals;
459
461
  last unless defined $val;
@@ -479,6 +481,10 @@ DoneFix: $isDate = 1;
479
481
  }
480
482
  } elsif ($param eq 'lat' or $param eq 'lon') {
481
483
  $$fix{$param} = Image::ExifTool::GPS::ToDegrees($val, 1);
484
+ } elsif ($param eq 'latref') {
485
+ $neg{lat} = 1 if $val =~ /^S/i;
486
+ } elsif ($param eq 'lonref') {
487
+ $neg{lon} = 1 if $val =~ /^W/i;
482
488
  } elsif ($param eq 'runtime') {
483
489
  $date = $trackTime;
484
490
  $secs = $val;
@@ -486,6 +492,11 @@ DoneFix: $isDate = 1;
486
492
  $$fix{$param} = $val;
487
493
  }
488
494
  }
495
+ # make coordinate negative according to reference direction if necessary
496
+ foreach $param (keys %neg) {
497
+ next unless defined $$fix{$param};
498
+ $$fix{$param} = -abs($$fix{$param});
499
+ }
489
500
  if ($date and defined $secs and defined $$fix{lat} and defined $$fix{lon}) {
490
501
  $time = $date + $secs;
491
502
  $$has{alt} = 1 if defined $$fix{alt};
@@ -16,7 +16,7 @@ use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
  use Image::ExifTool::QuickTime;
18
18
 
19
- $VERSION = '1.06';
19
+ $VERSION = '1.07';
20
20
 
21
21
  sub ProcessGoPro($$$);
22
22
  sub ProcessString($$$);
@@ -386,6 +386,21 @@ my %addUnits = (
386
386
  Binary => 1,
387
387
  },
388
388
  # ZFOV (APP6,GPMF) - seen: 148.34, 0 (fmt f, Hero8, Max)
389
+ # the following ref forum12825
390
+ MUID => {
391
+ Name => 'MediaUniqueID',
392
+ PrintConv => q{
393
+ my @a = split ' ', $val;
394
+ $_ = sprintf('%.8x',$_) foreach @a;
395
+ return join('', @a);
396
+ },
397
+ },
398
+ EXPT => 'MaximumShutterAngle',
399
+ MTRX => 'AccelerometerMatrix',
400
+ ORIN => 'InputOrientation',
401
+ ORIO => 'OutputOrientation',
402
+ UNIF => 'InputUniformity',
403
+ SROT => 'SensorReadoutTime',
389
404
  );
390
405
 
391
406
  # GoPro GPS5 tags (ref 2) (Hero5,Hero6)
@@ -11,6 +11,7 @@
11
11
  # 4) http://www.color.org/privatetag2007-01.pdf
12
12
  # 5) http://www.color.org/icc_specs2.xalter (approved revisions, 2010-07-16)
13
13
  # 6) Eef Vreeland private communication
14
+ # 7) https://color.org/specification/ICC.2-2019.pdf
14
15
  #
15
16
  # Notes: The ICC profile information is different: the format of each
16
17
  # tag is embedded in the information instead of in the directory
@@ -24,7 +25,7 @@ use strict;
24
25
  use vars qw($VERSION);
25
26
  use Image::ExifTool qw(:DataAccess :Utils);
26
27
 
27
- $VERSION = '1.36';
28
+ $VERSION = '1.38';
28
29
 
29
30
  sub ProcessICC($$);
30
31
  sub ProcessICC_Profile($$$);
@@ -52,6 +53,11 @@ my %profileClass = (
52
53
  abst => 'Abstract Profile',
53
54
  nmcl => 'NamedColor Profile',
54
55
  nkpf => 'Nikon Input Device Profile (NON-STANDARD!)', # (written by Nikon utilities)
56
+ # additions in v5 (ref 7)
57
+ cenc => 'ColorEncodingSpace Profile',
58
+ 'mid '=> 'MultiplexIdentification Profile',
59
+ mlnk => 'MultiplexLink Profile',
60
+ mvis => 'MultiplexVisualization Profile',
55
61
  );
56
62
  my %manuSig = ( #6
57
63
  'NONE' => 'none',
@@ -539,6 +545,90 @@ my %manuSig = ( #6
539
545
  Binary => 1, # (NC)
540
546
  },
541
547
 
548
+ # new tags in v5 (ref 7)
549
+ A2B3 => 'AToB3',
550
+ A2M0 => 'AToM0',
551
+ B2A3 => 'BToA3',
552
+ bcp0 => 'BRDFColorimetricParam0',
553
+ bcp1 => 'BRDFColorimetricParam1',
554
+ bcp2 => 'BRDFColorimetricParam2',
555
+ bcp3 => 'BRDFColorimetricParam3',
556
+ bsp0 => 'BRDFSpectralParam0',
557
+ bsp1 => 'BRDFSpectralParam1',
558
+ bsp2 => 'BRDFSpectralParam2',
559
+ bsp3 => 'BRDFSpectralParam3',
560
+ bAB0 => 'BRDFAToB0',
561
+ bAB1 => 'BRDFAToB1',
562
+ bAB2 => 'BRDFAToB2',
563
+ bAB3 => 'BRDFAToB3',
564
+ bBA0 => 'BRDFBToA0',
565
+ bBA1 => 'BRDFBToA1',
566
+ bBA2 => 'BRDFBToA2',
567
+ bBA3 => 'BRDFBToA3',
568
+ bBD0 => 'BRDFBToD0',
569
+ bBD1 => 'BRDFBToD1',
570
+ bBD2 => 'BRDFBToD2',
571
+ bBD3 => 'BRDFBToD3',
572
+ bDB0 => 'BRDFDToB0',
573
+ bDB1 => 'BRDFDToB1',
574
+ bDB2 => 'BRDFDToB2',
575
+ bDB3 => 'BRDFDToB3',
576
+ bMB0 => 'BRDFMToB0',
577
+ bMB1 => 'BRDFMToB1',
578
+ bMB2 => 'BRDFMToB2',
579
+ bMB3 => 'BRDFMToB3',
580
+ bMS0 => 'BRDFMToS0',
581
+ bMS1 => 'BRDFMToS1',
582
+ bMS2 => 'BRDFMToS2',
583
+ bMS3 => 'BRDFMToS3',
584
+ dAB0 => 'DirectionalAToB0',
585
+ dAB1 => 'DirectionalAToB1',
586
+ dAB2 => 'DirectionalAToB2',
587
+ dAB3 => 'DirectionalAToB3',
588
+ dBA0 => 'DirectionalBToA0',
589
+ dBA1 => 'DirectionalBToA1',
590
+ dBA2 => 'DirectionalBToA2',
591
+ dBA3 => 'DirectionalBToA3',
592
+ dBD0 => 'DirectionalBToD0',
593
+ dBD1 => 'DirectionalBToD1',
594
+ dBD2 => 'DirectionalBToD2',
595
+ dBD3 => 'DirectionalBToD3',
596
+ dDB0 => 'DirectionalDToB0',
597
+ dDB1 => 'DirectionalDToB1',
598
+ dDB2 => 'DirectionalDToB2',
599
+ dDB3 => 'DirectionalDToB3',
600
+ gdb0 => 'GamutBoundaryDescription0',
601
+ gdb1 => 'GamutBoundaryDescription1',
602
+ gdb2 => 'GamutBoundaryDescription2',
603
+ gdb3 => 'GamutBoundaryDescription3',
604
+ 'mdv '=> 'MultiplexDefaultValues',
605
+ mcta => 'MultiplexTypeArray',
606
+ minf => 'MeasurementInfo',
607
+ miin => 'MeasurementInputInfo',
608
+ M2A0 => 'MToA0',
609
+ M2B0 => 'MToB0',
610
+ M2B1 => 'MToB1',
611
+ M2B2 => 'MToB2',
612
+ M2B3 => 'MToB3',
613
+ M2S0 => 'MToS0',
614
+ M2S1 => 'MToS1',
615
+ M2S2 => 'MToS2',
616
+ M2S3 => 'MToS3',
617
+ cept => 'ColorEncodingParams',
618
+ csnm => 'ColorSpaceName',
619
+ cloo => 'ColorantOrderOut',
620
+ clio => 'ColorantInfoOut',
621
+ c2sp => 'CustomToStandardPcc',
622
+ 'CxF '=> 'CXF',
623
+ nmcl => 'NamedColor',
624
+ psin => 'ProfileSequenceInfo',
625
+ rfnm => 'ReferenceName',
626
+ svcn => 'SpectralViewingConditions',
627
+ swpt => 'SpectralWhitePoint',
628
+ s2cp => 'StandardToCustomPcc',
629
+ smap => 'SurfaceMap',
630
+ # smwp ? (seen in some v5 samples)
631
+
542
632
  # the following entry represents the ICC profile header, and doesn't
543
633
  # exist as a tag in the directory. It is only in this table to provide
544
634
  # a link so ExifTool can locate the header tags
@@ -850,7 +940,7 @@ sub FormatICCTag($$$)
850
940
  # dataType
851
941
  if ($type eq 'data' and $size >= 12) {
852
942
  my $form = Get32u($dataPt, $offset+8);
853
- # format 0 is ASCII data
943
+ # format 0 is UTF-8 data
854
944
  $form == 0 and return substr($$dataPt, $offset+12, $size-12);
855
945
  # binary data and other data types treat as binary (ie. don't format)
856
946
  }
@@ -1022,7 +1112,7 @@ sub ValidateICC($)
1022
1112
  $profileClass{substr($$valPtr, 12, 4)} or $err = 'profile class';
1023
1113
  my $col = substr($$valPtr, 16, 4); # ColorSpaceData
1024
1114
  my $con = substr($$valPtr, 20, 4); # ConnectionSpace
1025
- my $match = '(XYZ |Lab |Luv |YCbr|Yxy |RGB |GRAY|HSV |HLS |CMYK|CMY |[2-9A-F]CLR)';
1115
+ my $match = '(XYZ |Lab |Luv |YCbr|Yxy |RGB |GRAY|HSV |HLS |CMYK|CMY |[2-9A-F]CLR|nc..|\0{4})';
1026
1116
  $col =~ /$match/ or $err = 'color space';
1027
1117
  $con =~ /$match/ or $err = 'connection space';
1028
1118
  return $err ? "Invalid ICC profile (bad $err)" : undef;
@@ -1134,7 +1224,7 @@ sub ProcessICC_Profile($$$)
1134
1224
  my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID);
1135
1225
  # unknown tags aren't generated automatically by GetTagInfo()
1136
1226
  # if the tagID's aren't numeric, so we must do this manually:
1137
- if (not $tagInfo and $$et{OPTIONS}{Unknown}) {
1227
+ if (not $tagInfo and ($$et{OPTIONS}{Unknown} or $verbose)) {
1138
1228
  $tagInfo = { Unknown => 1 };
1139
1229
  AddTagToTable($tagTablePtr, $tagID, $tagInfo);
1140
1230
  }
@@ -1277,6 +1367,8 @@ under the same terms as Perl itself.
1277
1367
 
1278
1368
  =item L<http://developer.apple.com/documentation/GraphicsImaging/Reference/ColorSync_Manager/ColorSync_Manager.pdf>
1279
1369
 
1370
+ =item L<https://color.org/specification/ICC.2-2019.pdf>
1371
+
1280
1372
  =back
1281
1373
 
1282
1374
  =head1 SEE ALSO
@@ -14,7 +14,7 @@ use vars qw($VERSION);
14
14
  use Image::ExifTool qw(:DataAccess :Utils);
15
15
  use Image::ExifTool::Import;
16
16
 
17
- $VERSION = '1.03';
17
+ $VERSION = '1.05';
18
18
 
19
19
  sub ProcessJSON($$);
20
20
  sub ProcessTag($$$$%);
@@ -83,8 +83,12 @@ sub ProcessTag($$$$%)
83
83
  FoundTag($et, $tagTablePtr, $tag, $val, %flags, Struct => 1);
84
84
  return unless $et->Options('Struct') > 1;
85
85
  }
86
- foreach (sort keys %$val) {
87
- ProcessTag($et, $tagTablePtr, $tag . ucfirst, $$val{$_}, %flags, Flat => 1);
86
+ # support hashes with ordered keys
87
+ my @keys = $$val{_ordered_keys_} ? @{$$val{_ordered_keys_}} : sort keys %$val;
88
+ foreach (@keys) {
89
+ my $tg = $tag . ((/^\d/ and $tag =~ /\d$/) ? '_' : '') . ucfirst;
90
+ $tg =~ s/([^a-zA-Z])([a-z])/$1\U$2/g;
91
+ ProcessTag($et, $tagTablePtr, $tg, $$val{$_}, %flags, Flat => 1);
88
92
  }
89
93
  } elsif (ref $val eq 'ARRAY') {
90
94
  foreach (@$val) {