exiftool_vendored 12.34.0 → 12.38.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/Changes +61 -2
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/exiftool +65 -37
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +6 -2
- data/bin/lib/Image/ExifTool/Canon.pm +143 -9
- data/bin/lib/Image/ExifTool/CanonCustom.pm +12 -2
- data/bin/lib/Image/ExifTool/DarwinCore.pm +2 -2
- data/bin/lib/Image/ExifTool/Exif.pm +13 -1
- data/bin/lib/Image/ExifTool/FLIR.pm +33 -8
- data/bin/lib/Image/ExifTool/GIF.pm +5 -1
- data/bin/lib/Image/ExifTool/GPS.pm +14 -10
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +3 -3
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +108 -11
- data/bin/lib/Image/ExifTool/Nikon.pm +1203 -96
- data/bin/lib/Image/ExifTool/NikonCustom.pm +5 -1
- data/bin/lib/Image/ExifTool/NikonSettings.pm +135 -71
- data/bin/lib/Image/ExifTool/OpenEXR.pm +4 -2
- data/bin/lib/Image/ExifTool/PNG.pm +1 -0
- data/bin/lib/Image/ExifTool/QuickTime.pm +14 -2
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +26 -1
- data/bin/lib/Image/ExifTool/Sony.pm +3 -1
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +9 -4
- data/bin/lib/Image/ExifTool/TagLookup.pm +6363 -5846
- data/bin/lib/Image/ExifTool/TagNames.pod +1215 -39
- data/bin/lib/Image/ExifTool/WriteXMP.pl +10 -11
- data/bin/lib/Image/ExifTool/Writer.pl +10 -5
- data/bin/lib/Image/ExifTool/XMP.pm +110 -24
- data/bin/lib/Image/ExifTool/XMP2.pl +1 -1
- data/bin/lib/Image/ExifTool.pm +51 -12
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +2 -2
@@ -1290,9 +1290,19 @@ my %convPFn = ( PrintConv => \&ConvertPfn, PrintConvInv => \&ConvertPfnInv );
|
|
1290
1290
|
},
|
1291
1291
|
},
|
1292
1292
|
0x0106 => [{
|
1293
|
+
Name => 'AEBShotCount',
|
1294
|
+
Condition => '$$self{Model} =~ /\b90D\b/',
|
1295
|
+
Notes => 'EOS 90D', # (and who knows what others?)
|
1296
|
+
PrintConv => {
|
1297
|
+
2 => '2 shots',
|
1298
|
+
3 => '3 shots',
|
1299
|
+
5 => '5 shots',
|
1300
|
+
7 => '7 shots',
|
1301
|
+
},
|
1302
|
+
},{
|
1293
1303
|
Name => 'AEBShotCount',
|
1294
1304
|
Condition => '$count == 1',
|
1295
|
-
Notes => '
|
1305
|
+
Notes => 'other models storing a single value',
|
1296
1306
|
PrintConv => {
|
1297
1307
|
0 => '3 shots',
|
1298
1308
|
1 => '2 shots',
|
@@ -1302,7 +1312,7 @@ my %convPFn = ( PrintConv => \&ConvertPfn, PrintConvInv => \&ConvertPfnInv );
|
|
1302
1312
|
},{
|
1303
1313
|
Name => 'AEBShotCount',
|
1304
1314
|
Count => 2,
|
1305
|
-
Notes => 'two values
|
1315
|
+
Notes => 'models storing two values',
|
1306
1316
|
PrintConv => {
|
1307
1317
|
'3 0' => '3 shots',
|
1308
1318
|
'2 1' => '2 shots',
|
@@ -15,7 +15,7 @@ use strict;
|
|
15
15
|
use vars qw($VERSION);
|
16
16
|
use Image::ExifTool::XMP;
|
17
17
|
|
18
|
-
$VERSION = '1.
|
18
|
+
$VERSION = '1.06';
|
19
19
|
|
20
20
|
my %dateTimeInfo = (
|
21
21
|
# NOTE: Do NOT put "Groups" here because Groups hash must not be common!
|
@@ -38,7 +38,7 @@ my %event = (
|
|
38
38
|
earliestDate => { %dateTimeInfo, Groups => { 2 => 'Time' } },
|
39
39
|
endDayOfYear => { Writable => 'integer', Groups => { 2 => 'Time' } },
|
40
40
|
eventDate => { %dateTimeInfo, Groups => { 2 => 'Time' } },
|
41
|
-
eventID => { },
|
41
|
+
eventID => { Avoid => 1, Notes => 'avoided in favor of XMP-iptcExt:EventID' },
|
42
42
|
eventRemarks => { Writable => 'lang-alt' },
|
43
43
|
eventTime => {
|
44
44
|
Groups => { 2 => 'Time' },
|
@@ -56,7 +56,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
|
|
56
56
|
use Image::ExifTool qw(:DataAccess :Utils);
|
57
57
|
use Image::ExifTool::MakerNotes;
|
58
58
|
|
59
|
-
$VERSION = '4.
|
59
|
+
$VERSION = '4.38';
|
60
60
|
|
61
61
|
sub ProcessExif($$$);
|
62
62
|
sub WriteExif($$$);
|
@@ -4816,11 +4816,23 @@ my %subSecConv = (
|
|
4816
4816
|
},
|
4817
4817
|
GPSPosition => {
|
4818
4818
|
Groups => { 2 => 'Location' },
|
4819
|
+
Writable => 1,
|
4820
|
+
WriteAlso => {
|
4821
|
+
GPSLatitude => '$val =~ /(.*?)( ?[NS])?,/ ? $1 : undef',
|
4822
|
+
GPSLatitudeRef => '$val =~ /(-?)(.*?) ?([NS]?),/ ? ($3 || ($1 ? "S" : "N")) : undef',
|
4823
|
+
GPSLongitude => '$val =~ /, ?(.*?)( ?[EW]?)$/ ? $1 : undef',
|
4824
|
+
GPSLongitudeRef => '$val =~ /, ?(-?)(.*?) ?([EW]?)$/ ? ($3 || ($1 ? "W" : "E")) : undef',
|
4825
|
+
},
|
4819
4826
|
Require => {
|
4820
4827
|
0 => 'GPSLatitude',
|
4821
4828
|
1 => 'GPSLongitude',
|
4822
4829
|
},
|
4823
4830
|
Priority => 0,
|
4831
|
+
Notes => q{
|
4832
|
+
when written, writes GPSLatitude, GPSLatitudeRef, GPSLongitude and
|
4833
|
+
GPSLongitudeRef. This tag may be written using the same coordinate
|
4834
|
+
format as provided by Google Maps when right-clicking on a location
|
4835
|
+
},
|
4824
4836
|
ValueConv => '(length($val[0]) or length($val[1])) ? "$val[0] $val[1]" : undef',
|
4825
4837
|
PrintConv => '"$prt[0], $prt[1]"',
|
4826
4838
|
},
|
@@ -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.
|
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
|
-
|
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
|
-
|
1537
|
-
|
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
|
-
|
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.
|
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/([-+])(
|
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*$
|
143
|
+
@tz = ($s*$2, $s*$3);
|
144
144
|
}
|
145
|
-
|
146
|
-
|
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[
|
150
|
-
$a[
|
151
|
-
while ($a[
|
152
|
-
while ($a[
|
153
|
-
$a[
|
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
|
159
|
+
return join(':', @a);
|
156
160
|
},
|
157
161
|
},
|
158
162
|
0x0008 => {
|
@@ -25,7 +25,7 @@ use strict;
|
|
25
25
|
use vars qw($VERSION);
|
26
26
|
use Image::ExifTool qw(:DataAccess :Utils);
|
27
27
|
|
28
|
-
$VERSION = '1.
|
28
|
+
$VERSION = '1.38';
|
29
29
|
|
30
30
|
sub ProcessICC($$);
|
31
31
|
sub ProcessICC_Profile($$$);
|
@@ -549,7 +549,7 @@ my %manuSig = ( #6
|
|
549
549
|
A2B3 => 'AToB3',
|
550
550
|
A2M0 => 'AToM0',
|
551
551
|
B2A3 => 'BToA3',
|
552
|
-
bcp0 => '
|
552
|
+
bcp0 => 'BRDFColorimetricParam0',
|
553
553
|
bcp1 => 'BRDFColorimetricParam1',
|
554
554
|
bcp2 => 'BRDFColorimetricParam2',
|
555
555
|
bcp3 => 'BRDFColorimetricParam3',
|
@@ -602,7 +602,7 @@ my %manuSig = ( #6
|
|
602
602
|
gdb2 => 'GamutBoundaryDescription2',
|
603
603
|
gdb3 => 'GamutBoundaryDescription3',
|
604
604
|
'mdv '=> 'MultiplexDefaultValues',
|
605
|
-
mcta => '
|
605
|
+
mcta => 'MultiplexTypeArray',
|
606
606
|
minf => 'MeasurementInfo',
|
607
607
|
miin => 'MeasurementInputInfo',
|
608
608
|
M2A0 => 'MToA0',
|
@@ -16,7 +16,7 @@ use strict;
|
|
16
16
|
use vars qw($VERSION);
|
17
17
|
use Image::ExifTool qw(:DataAccess :Utils);
|
18
18
|
|
19
|
-
$VERSION = '1.
|
19
|
+
$VERSION = '1.32';
|
20
20
|
|
21
21
|
sub ProcessJpeg2000Box($$$);
|
22
22
|
sub ProcessJUMD($$$);
|
@@ -42,8 +42,9 @@ my %jp2Map = (
|
|
42
42
|
'UUID-IPTC' => 'JP2',
|
43
43
|
'UUID-EXIF' => 'JP2',
|
44
44
|
'UUID-XMP' => 'JP2',
|
45
|
-
|
46
|
-
|
45
|
+
jp2h => 'JP2',
|
46
|
+
colr => 'jp2h',
|
47
|
+
ICC_Profile => 'colr',
|
47
48
|
IFD1 => 'IFD0',
|
48
49
|
EXIF => 'IFD0', # to write EXIF as a block
|
49
50
|
ExifIFD => 'IFD0',
|
@@ -560,11 +561,34 @@ my %j2cMarker = (
|
|
560
561
|
|
561
562
|
%Image::ExifTool::Jpeg2000::ColorSpec = (
|
562
563
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
564
|
+
WRITE_PROC => \&Image::ExifTool::WriteBinaryData, # (we don't actually call this)
|
563
565
|
GROUPS => { 2 => 'Image' },
|
564
566
|
FORMAT => 'int8s',
|
567
|
+
WRITABLE => 1,
|
568
|
+
# (Note: 'colr' is not a real group, but is used as a hack to write the
|
569
|
+
# necessary colr box. This hack necessitated another hack in TagInfoXML.pm
|
570
|
+
# to avoid reporting this fake group in the XML output)
|
571
|
+
WRITE_GROUP => 'colr',
|
572
|
+
DATAMEMBER => [ 0 ],
|
573
|
+
IS_SUBDIR => [ 3 ],
|
574
|
+
NOTES => q{
|
575
|
+
The table below contains tags in the color specification (colr) box. This
|
576
|
+
box may be rewritten by writing either ICC_Profile, ColorSpace or
|
577
|
+
ColorSpecData. When writing, any existing colr boxes are replaced with the
|
578
|
+
newly created colr box.
|
579
|
+
|
580
|
+
B<NOTE>: Care must be taken when writing this color specification because
|
581
|
+
writing a specification that is incompatible with the image data may make
|
582
|
+
the image undisplayable.
|
583
|
+
},
|
565
584
|
0 => {
|
566
585
|
Name => 'ColorSpecMethod',
|
567
586
|
RawConv => '$$self{ColorSpecMethod} = $val',
|
587
|
+
Protected => 1,
|
588
|
+
Notes => q{
|
589
|
+
default for writing is 2 when writing ICC_Profile, 1 when writing
|
590
|
+
ColorSpace, or 4 when writing ColorSpecData
|
591
|
+
},
|
568
592
|
PrintConv => {
|
569
593
|
1 => 'Enumerated',
|
570
594
|
2 => 'Restricted ICC',
|
@@ -572,9 +596,15 @@ my %j2cMarker = (
|
|
572
596
|
4 => 'Vendor Color',
|
573
597
|
},
|
574
598
|
},
|
575
|
-
1 =>
|
599
|
+
1 => {
|
600
|
+
Name => 'ColorSpecPrecedence',
|
601
|
+
Notes => 'default for writing is 0',
|
602
|
+
Protected => 1,
|
603
|
+
},
|
576
604
|
2 => {
|
577
605
|
Name => 'ColorSpecApproximation',
|
606
|
+
Notes => 'default for writing is 0',
|
607
|
+
Protected => 1,
|
578
608
|
PrintConv => {
|
579
609
|
0 => 'Not Specified',
|
580
610
|
1 => 'Accurate',
|
@@ -599,6 +629,7 @@ my %j2cMarker = (
|
|
599
629
|
Name => 'ColorSpace',
|
600
630
|
Condition => '$$self{ColorSpecMethod} == 1',
|
601
631
|
Format => 'int32u',
|
632
|
+
Protected => 1,
|
602
633
|
PrintConv => { # ref 15444-2 2002-05-15
|
603
634
|
0 => 'Bi-level',
|
604
635
|
1 => 'YCbCr(1)',
|
@@ -628,6 +659,8 @@ my %j2cMarker = (
|
|
628
659
|
{
|
629
660
|
Name => 'ColorSpecData',
|
630
661
|
Format => 'undef[$size-3]',
|
662
|
+
Writable => 'undef',
|
663
|
+
Protected => 1,
|
631
664
|
Binary => 1,
|
632
665
|
},
|
633
666
|
],
|
@@ -817,6 +850,48 @@ sub CreateNewBoxes($$)
|
|
817
850
|
return 1;
|
818
851
|
}
|
819
852
|
|
853
|
+
#------------------------------------------------------------------------------
|
854
|
+
# Create Color Specification Box
|
855
|
+
# Inputs: 0) ExifTool object ref, 1) Output file or scalar ref
|
856
|
+
# Returns: 1 on success
|
857
|
+
sub CreateColorSpec($$)
|
858
|
+
{
|
859
|
+
my ($et, $outfile) = @_;
|
860
|
+
my $meth = $et->GetNewValue('Jpeg2000:ColorSpecMethod');
|
861
|
+
my $prec = $et->GetNewValue('Jpeg2000:ColorSpecPrecedence') || 0;
|
862
|
+
my $approx = $et->GetNewValue('Jpeg2000:ColorSpecApproximation') || 0;
|
863
|
+
my $icc = $et->GetNewValue('ICC_Profile');
|
864
|
+
my $space = $et->GetNewValue('Jpeg2000:ColorSpace');
|
865
|
+
my $cdata = $et->GetNewValue('Jpeg2000:ColorSpecData');
|
866
|
+
unless ($meth) {
|
867
|
+
if ($icc) {
|
868
|
+
$meth = 2;
|
869
|
+
} elsif (defined $space) {
|
870
|
+
$meth = 1;
|
871
|
+
} elsif (defined $cdata) {
|
872
|
+
$meth = 4;
|
873
|
+
} else {
|
874
|
+
$et->Warn('Color space not defined'), return 0;
|
875
|
+
}
|
876
|
+
}
|
877
|
+
if ($meth eq '1') {
|
878
|
+
defined $space or $et->Warn('Must specify ColorSpace'), return 0;
|
879
|
+
$cdata = pack('N', $space);
|
880
|
+
} elsif ($meth eq '2' or $meth eq '3') {
|
881
|
+
defined $icc or $et->Warn('Must specify ICC_Profile'), return 0;
|
882
|
+
$cdata = $icc;
|
883
|
+
} elsif ($meth eq '4') {
|
884
|
+
defined $cdata or $et->Warn('Must specify ColorSpecData'), return 0;
|
885
|
+
} else {
|
886
|
+
$et->Warn('Unknown ColorSpecMethod'), return 0;
|
887
|
+
}
|
888
|
+
my $boxhdr = pack('N', length($cdata) + 11) . 'colr';
|
889
|
+
Write($outfile, $boxhdr, pack('CCC',$meth,$prec,$approx), $cdata) or return 0;
|
890
|
+
++$$et{CHANGED};
|
891
|
+
$et->VPrint(1, " + Jpeg2000:ColorSpec\n");
|
892
|
+
return 1;
|
893
|
+
}
|
894
|
+
|
820
895
|
#------------------------------------------------------------------------------
|
821
896
|
# Process JPEG 2000 box
|
822
897
|
# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) Pointer to tag table
|
@@ -834,7 +909,7 @@ sub ProcessJpeg2000Box($$$)
|
|
834
909
|
my $raf = $$dirInfo{RAF};
|
835
910
|
my $outfile = $$dirInfo{OutFile};
|
836
911
|
my $dirEnd = $dirStart + $dirLen;
|
837
|
-
my ($err, $outBuff, $verbose);
|
912
|
+
my ($err, $outBuff, $verbose, $doColour);
|
838
913
|
|
839
914
|
if ($outfile) {
|
840
915
|
unless ($raf) {
|
@@ -842,13 +917,19 @@ sub ProcessJpeg2000Box($$$)
|
|
842
917
|
$outBuff = '';
|
843
918
|
$outfile = \$outBuff;
|
844
919
|
}
|
920
|
+
# determine if we will be writing colr box
|
921
|
+
if ($$dirInfo{DirName} and $$dirInfo{DirName} eq 'JP2Header') {
|
922
|
+
$doColour = 2 if defined $et->GetNewValue('ColorSpecMethod') or $et->GetNewValue('ICC_Profile') or
|
923
|
+
defined $et->GetNewValue('ColorSpecPrecedence') or defined $et->GetNewValue('ColorSpace') or
|
924
|
+
defined $et->GetNewValue('ColorSpecApproximation') or defined $et->GetNewValue('ColorSpecData');
|
925
|
+
}
|
845
926
|
} else {
|
846
927
|
# (must not set verbose flag when writing!)
|
847
928
|
$verbose = $$et{OPTIONS}{Verbose};
|
848
929
|
$et->VerboseDir($$dirInfo{DirName}) if $verbose;
|
849
930
|
}
|
850
931
|
# loop through all contained boxes
|
851
|
-
my ($pos, $boxLen);
|
932
|
+
my ($pos, $boxLen, $lastBox);
|
852
933
|
for ($pos=$dirStart; ; $pos+=$boxLen) {
|
853
934
|
my ($boxID, $buff, $valuePtr);
|
854
935
|
my $hdrLen = 8; # the box header length
|
@@ -857,9 +938,7 @@ sub ProcessJpeg2000Box($$$)
|
|
857
938
|
my $n = $raf->Read($buff,$hdrLen);
|
858
939
|
unless ($n == $hdrLen) {
|
859
940
|
$n and $err = '', last;
|
860
|
-
|
861
|
-
CreateNewBoxes($et, $outfile) or $err = 1;
|
862
|
-
}
|
941
|
+
CreateNewBoxes($et, $outfile) or $err = 1 if $outfile;
|
863
942
|
last;
|
864
943
|
}
|
865
944
|
$dataPt = \$buff;
|
@@ -871,6 +950,17 @@ sub ProcessJpeg2000Box($$$)
|
|
871
950
|
}
|
872
951
|
$boxLen = unpack("x$pos N",$$dataPt); # (length includes header and data)
|
873
952
|
$boxID = substr($$dataPt, $pos+4, 4);
|
953
|
+
# remove old colr boxes if necessary
|
954
|
+
if ($doColour and $boxID eq 'colr') {
|
955
|
+
if ($doColour == 1) { # did we successfully write the new colr box?
|
956
|
+
$et->VPrint(1," - Jpeg2000:ColorSpec\n");
|
957
|
+
++$$et{CHANGED};
|
958
|
+
next;
|
959
|
+
}
|
960
|
+
$et->Warn('Out-of-order colr box encountered');
|
961
|
+
undef $doColour;
|
962
|
+
}
|
963
|
+
$lastBox = $boxID;
|
874
964
|
$pos += $hdrLen; # move to end of box header
|
875
965
|
if ($boxLen == 1) {
|
876
966
|
# box header contains an additional 8-byte integer for length
|
@@ -1009,8 +1099,10 @@ sub ProcessJpeg2000Box($$$)
|
|
1009
1099
|
# remove this directory from our create list
|
1010
1100
|
delete $$et{AddJp2Dirs}{$$tagInfo{Name}};
|
1011
1101
|
my $newdir;
|
1012
|
-
# only edit writable UUID and
|
1013
|
-
if ($uuid or $boxID eq 'Exif' or ($boxID eq 'xml ' and $$et{IsJXL})
|
1102
|
+
# only edit writable UUID, Exif and jp2h boxes
|
1103
|
+
if ($uuid or $boxID eq 'Exif' or ($boxID eq 'xml ' and $$et{IsJXL}) or
|
1104
|
+
($boxID eq 'jp2h' and $$et{EDIT_DIRS}{jp2h}))
|
1105
|
+
{
|
1014
1106
|
$newdir = $et->WriteDirectory(\%subdirInfo, $subTable, $$subdir{WriteProc});
|
1015
1107
|
next if defined $newdir and not length $newdir; # next if deleting the box
|
1016
1108
|
} elsif (defined $uuid) {
|
@@ -1022,6 +1114,11 @@ sub ProcessJpeg2000Box($$$)
|
|
1022
1114
|
my $boxhdr = pack('N', length($newdir) + 8 + $prefixLen) . $boxID;
|
1023
1115
|
$boxhdr .= substr($$dataPt, $valuePtr, $prefixLen) if $prefixLen;
|
1024
1116
|
Write($outfile, $boxhdr, $newdir) or $err = 1;
|
1117
|
+
# write new colr box immediately after ihdr
|
1118
|
+
if ($doColour and $boxID eq 'ihdr') {
|
1119
|
+
# (shouldn't be multiple ihdr boxes, but just in case, write only 1)
|
1120
|
+
$doColour = $doColour==2 ? CreateColorSpec($et, $outfile) : 0;
|
1121
|
+
}
|
1025
1122
|
} else {
|
1026
1123
|
# extract as a block if specified
|
1027
1124
|
$subdirInfo{BlockInfo} = $tagInfo if $$tagInfo{BlockExtract};
|