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.
- checksums.yaml +4 -4
- data/bin/Changes +201 -2
- data/bin/MANIFEST +8 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +43 -42
- data/bin/exiftool +172 -99
- data/bin/lib/Image/ExifTool.pm +170 -117
- data/bin/lib/Image/ExifTool.pod +132 -97
- data/bin/lib/Image/ExifTool/AIFF.pm +2 -2
- data/bin/lib/Image/ExifTool/APE.pm +2 -2
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +21 -10
- data/bin/lib/Image/ExifTool/Canon.pm +202 -13
- data/bin/lib/Image/ExifTool/CanonCustom.pm +82 -16
- data/bin/lib/Image/ExifTool/DPX.pm +56 -2
- data/bin/lib/Image/ExifTool/DarwinCore.pm +22 -3
- data/bin/lib/Image/ExifTool/EXE.pm +8 -5
- data/bin/lib/Image/ExifTool/Exif.pm +15 -6
- data/bin/lib/Image/ExifTool/Font.pm +9 -2
- data/bin/lib/Image/ExifTool/GIF.pm +6 -1
- data/bin/lib/Image/ExifTool/GeoTiff.pm +2 -0
- data/bin/lib/Image/ExifTool/Geotag.pm +2 -2
- data/bin/lib/Image/ExifTool/GoPro.pm +48 -22
- data/bin/lib/Image/ExifTool/H264.pm +1 -1
- data/bin/lib/Image/ExifTool/ID3.pm +86 -12
- data/bin/lib/Image/ExifTool/IPTC.pm +1 -0
- data/bin/lib/Image/ExifTool/Import.pm +12 -9
- data/bin/lib/Image/ExifTool/JSON.pm +27 -4
- data/bin/lib/Image/ExifTool/Lang/de.pm +3 -1
- data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
- data/bin/lib/Image/ExifTool/M2TS.pm +1 -1
- data/bin/lib/Image/ExifTool/MPF.pm +2 -2
- data/bin/lib/Image/ExifTool/MacOS.pm +154 -38
- data/bin/lib/Image/ExifTool/Matroska.pm +3 -1
- data/bin/lib/Image/ExifTool/Minolta.pm +7 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +143 -17
- data/bin/lib/Image/ExifTool/Olympus.pm +40 -17
- data/bin/lib/Image/ExifTool/PNG.pm +14 -3
- data/bin/lib/Image/ExifTool/PPM.pm +5 -5
- data/bin/lib/Image/ExifTool/Panasonic.pm +148 -14
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +34 -0
- data/bin/lib/Image/ExifTool/Parrot.pm +2 -1
- data/bin/lib/Image/ExifTool/Pentax.pm +11 -3
- data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
- data/bin/lib/Image/ExifTool/QuickTime.pm +240 -37
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +419 -60
- data/bin/lib/Image/ExifTool/README +25 -21
- data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
- data/bin/lib/Image/ExifTool/Radiance.pm +7 -2
- data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
- data/bin/lib/Image/ExifTool/Shift.pl +1 -0
- data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
- data/bin/lib/Image/ExifTool/Sony.pm +423 -39
- data/bin/lib/Image/ExifTool/Stim.pm +2 -2
- data/bin/lib/Image/ExifTool/TagLookup.pm +5798 -5675
- data/bin/lib/Image/ExifTool/TagNames.pod +575 -100
- data/bin/lib/Image/ExifTool/Validate.pm +4 -4
- data/bin/lib/Image/ExifTool/WriteExif.pl +1 -0
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +30 -21
- data/bin/lib/Image/ExifTool/Writer.pl +49 -24
- data/bin/lib/Image/ExifTool/XMP.pm +99 -17
- data/bin/lib/Image/ExifTool/XMP2.pl +1 -0
- data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
- data/bin/lib/Image/ExifTool/ZISRAW.pm +123 -0
- data/bin/perl-Image-ExifTool.spec +42 -41
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +9 -8
@@ -17,7 +17,7 @@ package Image::ExifTool::Validate;
|
|
17
17
|
use strict;
|
18
18
|
use vars qw($VERSION %exifSpec);
|
19
19
|
|
20
|
-
$VERSION = '1.
|
20
|
+
$VERSION = '1.18';
|
21
21
|
|
22
22
|
use Image::ExifTool qw(:Utils);
|
23
23
|
use Image::ExifTool::Exif;
|
@@ -214,11 +214,11 @@ my %validValue = (
|
|
214
214
|
IFD0 => {
|
215
215
|
0x100 => 'defined $val', # ImageWidth
|
216
216
|
0x101 => 'defined $val', # ImageLength
|
217
|
-
0x102 => 'defined $val', # BitsPerSample
|
217
|
+
# (default is 1) 0x102 => 'defined $val', # BitsPerSample
|
218
218
|
0x103 => q{
|
219
219
|
not defined $val or $val =~ /^(1|5|6|32773)$/ or
|
220
220
|
($val == 2 and (not defined $val{0x102} or $val{0x102} == 1));
|
221
|
-
},
|
221
|
+
}, # Compression
|
222
222
|
0x106 => '$val =~ /^[0123]$/', # PhotometricInterpretation
|
223
223
|
0x111 => 'defined $val', # StripOffsets
|
224
224
|
# SamplesPerPixel
|
@@ -237,7 +237,7 @@ my %validValue = (
|
|
237
237
|
0x117 => 'defined $val', # StripByteCounts
|
238
238
|
0x11a => 'defined $val', # XResolution
|
239
239
|
0x11b => 'defined $val', # YResolution
|
240
|
-
0x128 => '$val =~ /^[123]$/', # ResolutionUnit
|
240
|
+
0x128 => 'not defined $val or $val =~ /^[123]$/', # ResolutionUnit
|
241
241
|
# ColorMap (must be palette image with correct number of colors)
|
242
242
|
0x140 => q{
|
243
243
|
return '' if defined $val{0x106} and $val{0x106} == 3 xor defined $val;
|
@@ -1832,6 +1832,7 @@ NoOverwrite: next if $isNew > 0;
|
|
1832
1832
|
warn "Internal error writing offsets for $$newInfo{Name}\n";
|
1833
1833
|
return undef;
|
1834
1834
|
}
|
1835
|
+
$newValuePt = \$newValue;
|
1835
1836
|
}
|
1836
1837
|
$offsetInfo or $offsetInfo = $offsetInfo[$ifd] = { };
|
1837
1838
|
# save location of valuePtr in new directory
|
@@ -144,7 +144,7 @@ sub PrintInvGPSCoordinates($)
|
|
144
144
|
$v[2] = Image::ExifTool::ToFloat($v[2]) * ($below ? -1 : 1) if @v == 3;
|
145
145
|
return "@v";
|
146
146
|
}
|
147
|
-
return $val if $val =~ /^([-+]\d+(\.\d*)?){2,3}(CRS.*)
|
147
|
+
return $val if $val =~ /^([-+]\d+(\.\d*)?){2,3}(CRS.*)?\/?$/; # already in ISO6709 format?
|
148
148
|
return undef;
|
149
149
|
}
|
150
150
|
|
@@ -159,15 +159,16 @@ sub ConvInvISO6709($)
|
|
159
159
|
my @a = split ' ', $val;
|
160
160
|
if (@a == 2 or @a == 3) {
|
161
161
|
# latitude must have 2 digits before the decimal, and longitude 3,
|
162
|
-
# and all values must start with a "+" or "-"
|
163
|
-
|
162
|
+
# and all values must start with a "+" or "-", and Google Photos
|
163
|
+
# requires at least 3 digits after the decimal point
|
164
|
+
my @fmt = ('%s%02d.%s%s','%s%03d.%s%s','%s%d.%s%s');
|
164
165
|
foreach (@a) {
|
165
166
|
return undef unless Image::ExifTool::IsFloat($_);
|
166
|
-
$_ =~ s/^([-+]?)(\d+)/sprintf(shift(@fmt)
|
167
|
+
$_ =~ s/^([-+]?)(\d+)\.?(\d*)/sprintf(shift(@fmt),$1||'+',$2,$3,length($3)<3 ? '0'x(3-length($3)) : '')/e;
|
167
168
|
}
|
168
|
-
return join '', @a;
|
169
|
+
return join '', @a, '/';
|
169
170
|
}
|
170
|
-
return $val if $val =~ /^([-+]\d+(\.\d*)?){2,3}(CRS.*)
|
171
|
+
return $val if $val =~ /^([-+]\d+(\.\d*)?){2,3}(CRS.*)?\/?$/; # already in ISO6709 format?
|
171
172
|
return undef;
|
172
173
|
}
|
173
174
|
|
@@ -300,15 +301,19 @@ sub CheckQTValue($$$)
|
|
300
301
|
|
301
302
|
#------------------------------------------------------------------------------
|
302
303
|
# Format QuickTime value for writing
|
303
|
-
# Inputs: 0) ExifTool ref, 1) value ref, 2) Format (or undef)
|
304
|
+
# Inputs: 0) ExifTool ref, 1) value ref, 2) Format (or undef), 3) Writable (or undef)
|
304
305
|
# Returns: Flags for QT data type, and reformats value as required
|
305
|
-
sub FormatQTValue(
|
306
|
+
sub FormatQTValue($$;$$)
|
306
307
|
{
|
307
|
-
my ($et, $valPt, $format) = @_;
|
308
|
+
my ($et, $valPt, $format, $writable) = @_;
|
308
309
|
my $flags;
|
309
310
|
if ($format and $format ne 'string') {
|
310
311
|
$$valPt = WriteValue($$valPt, $format);
|
311
|
-
$
|
312
|
+
if ($writable and $qtFormat{$writable}) {
|
313
|
+
$flags = $qtFormat{$writable};
|
314
|
+
} else {
|
315
|
+
$flags = $qtFormat{$format} || 0;
|
316
|
+
}
|
312
317
|
} elsif ($$valPt =~ /^\xff\xd8\xff/) {
|
313
318
|
$flags = 0x0d; # JPG
|
314
319
|
} elsif ($$valPt =~ /^(\x89P|\x8aM|\x8bJ)NG\r\n\x1a\n/) {
|
@@ -1122,9 +1127,9 @@ sub WriteQuickTime($$$)
|
|
1122
1127
|
my $newVal = $et->GetNewValue($nvHash);
|
1123
1128
|
next unless defined $newVal;
|
1124
1129
|
my $prVal = $newVal;
|
1125
|
-
my $flags = FormatQTValue($et, \$newVal, $format);
|
1130
|
+
my $flags = FormatQTValue($et, \$newVal, $format, $$tagInfo{Writable});
|
1126
1131
|
next unless defined $newVal;
|
1127
|
-
my ($ctry, $lang) = (0,
|
1132
|
+
my ($ctry, $lang) = (0, 0);
|
1128
1133
|
if ($$ti{LangCode}) {
|
1129
1134
|
unless ($$ti{LangCode} =~ /^([A-Z]{3})?[-_]?([A-Z]{2})?$/i) {
|
1130
1135
|
$et->Warn("Invalid language code for $$ti{Name}");
|
@@ -1180,7 +1185,11 @@ sub WriteQuickTime($$$)
|
|
1180
1185
|
} else {
|
1181
1186
|
if ($format) {
|
1182
1187
|
# update flags for the format we are writing
|
1183
|
-
|
1188
|
+
if ($$tagInfo{Writable} and $qtFormat{$$tagInfo{Writable}}) {
|
1189
|
+
$flags = $qtFormat{$$tagInfo{Writable}};
|
1190
|
+
} elsif ($qtFormat{$format}) {
|
1191
|
+
$flags = $qtFormat{$format};
|
1192
|
+
}
|
1184
1193
|
} else {
|
1185
1194
|
$format = QuickTimeFormat($flags, $len);
|
1186
1195
|
}
|
@@ -1199,12 +1208,13 @@ sub WriteQuickTime($$$)
|
|
1199
1208
|
}
|
1200
1209
|
my $prVal = $newVal;
|
1201
1210
|
# format new value for writing (and get new flags)
|
1202
|
-
$flags = FormatQTValue($et, \$newVal, $format);
|
1211
|
+
$flags = FormatQTValue($et, \$newVal, $format, $$tagInfo{Writable});
|
1203
1212
|
my $grp = $et->GetGroup($langInfo, 1);
|
1204
1213
|
$et->VerboseValue("- $grp:$$langInfo{Name}", $val);
|
1205
1214
|
$et->VerboseValue("+ $grp:$$langInfo{Name}", $prVal);
|
1206
1215
|
$newData = substr($buff, 0, $pos-16) unless defined $newData;
|
1207
|
-
$
|
1216
|
+
my $wLang = $lang eq $undLang ? 0 : $lang;
|
1217
|
+
$newData .= pack('Na4Nnn', length($newVal)+16, $type, $flags, $ctry, $wLang);
|
1208
1218
|
$newData .= $newVal;
|
1209
1219
|
++$$et{CHANGED};
|
1210
1220
|
} elsif (defined $newData) {
|
@@ -1268,10 +1278,11 @@ sub WriteQuickTime($$$)
|
|
1268
1278
|
# add back necessary header and encode as necessary
|
1269
1279
|
if (defined $lang) {
|
1270
1280
|
$newData = $et->Encode($newData, $lang < 0x400 ? $charsetQuickTime : 'UTF8');
|
1281
|
+
my $wLang = $lang eq $undLang ? 0 : $lang;
|
1271
1282
|
if ($$tagInfo{IText} and $$tagInfo{IText} == 6) {
|
1272
|
-
$newData = pack('Nn', 0, $
|
1283
|
+
$newData = pack('Nn', 0, $wLang) . $newData . "\0";
|
1273
1284
|
} else {
|
1274
|
-
$newData = pack('nn', length($newData), $
|
1285
|
+
$newData = pack('nn', length($newData), $wLang) . $newData;
|
1275
1286
|
}
|
1276
1287
|
} elsif (not $format or $format =~ /^string/ and
|
1277
1288
|
not $$tagInfo{Binary} and not $$tagInfo{ValueConv})
|
@@ -1406,9 +1417,9 @@ sub WriteQuickTime($$$)
|
|
1406
1417
|
my $newVal = $et->GetNewValue($nvHash);
|
1407
1418
|
next unless defined $newVal;
|
1408
1419
|
my $prVal = $newVal;
|
1409
|
-
my $flags = FormatQTValue($et, \$newVal, $$tagInfo{Format});
|
1420
|
+
my $flags = FormatQTValue($et, \$newVal, $$tagInfo{Format}, $$tagInfo{Writable});
|
1410
1421
|
next unless defined $newVal;
|
1411
|
-
my ($ctry, $lang) = (0,0);
|
1422
|
+
my ($ctry, $lang) = (0, 0);
|
1412
1423
|
# handle alternate languages
|
1413
1424
|
if ($$tagInfo{LangCode}) {
|
1414
1425
|
$tag = substr($tag, 0, 4); # strip language code from tag ID
|
@@ -1424,10 +1435,8 @@ sub WriteQuickTime($$$)
|
|
1424
1435
|
}
|
1425
1436
|
if ($$dirInfo{HasData}) {
|
1426
1437
|
# add 'data' header
|
1427
|
-
$lang or $lang = $undLang;
|
1428
1438
|
$newVal = pack('Na4Nnn',16+length($newVal),'data',$flags,$ctry,$lang).$newVal;
|
1429
1439
|
} elsif ($tag =~ /^\xa9/ or $$tagInfo{IText}) {
|
1430
|
-
$lang or $lang = $undLang;
|
1431
1440
|
if ($ctry) {
|
1432
1441
|
my $grp = $et->GetGroup($tagInfo,1);
|
1433
1442
|
$et->Warn("Can't use country code for $grp:$$tagInfo{Name}");
|
@@ -359,21 +359,25 @@ sub SetNewValue($;$$%)
|
|
359
359
|
my $convType = $options{Type} || ($$self{OPTIONS}{PrintConv} ? 'PrintConv' : 'ValueConv');
|
360
360
|
|
361
361
|
# filter value if necessary
|
362
|
-
$self->Filter($$self{OPTIONS}{FilterW}, \$value) if $convType eq 'PrintConv';
|
362
|
+
$self->Filter($$self{OPTIONS}{FilterW}, \$value) or return 0 if $convType eq 'PrintConv';
|
363
363
|
|
364
364
|
my (@wantGroup, $family2);
|
365
365
|
my $wantGroup = $options{Group};
|
366
366
|
if ($wantGroup) {
|
367
367
|
foreach (split /:/, $wantGroup) {
|
368
368
|
next unless length($_) and /^(\d+)?(.*)/; # separate family number and group name
|
369
|
-
my ($f, $g) = ($1,
|
369
|
+
my ($f, $g) = ($1, $2);
|
370
|
+
my $lcg = lc $g;
|
370
371
|
# save group/family unless '*' or 'all'
|
371
|
-
push @wantGroup, [ $f, $
|
372
|
-
if (
|
373
|
-
|
374
|
-
$
|
372
|
+
push @wantGroup, [ $f, $lcg ] unless $lcg eq '*' or $lcg eq 'all';
|
373
|
+
if ($g =~ s/^ID-//i) { # family 7 is a tag ID
|
374
|
+
return 0 if defined $f and $f ne 7;
|
375
|
+
$wantGroup[-1] = [ 7, $g ]; # group name with 'ID-' removed and case preserved
|
376
|
+
} elsif (defined $f) {
|
377
|
+
$f > 2 and return 0; # only allow family 0, 1 or 2
|
378
|
+
$family2 = 1 if $f == 2; # set flag indicating family 2 was used
|
375
379
|
} else {
|
376
|
-
$family2 = 1 if $family2groups{$
|
380
|
+
$family2 = 1 if $family2groups{$lcg};
|
377
381
|
}
|
378
382
|
}
|
379
383
|
undef $wantGroup unless @wantGroup;
|
@@ -622,6 +626,8 @@ TAG: foreach $tagInfo (@matchingTags) {
|
|
622
626
|
next;
|
623
627
|
}
|
624
628
|
next if $lcWant eq lc $grp[2];
|
629
|
+
} elsif ($fam == 7) {
|
630
|
+
next if IsSameID($$tagInfo{TagID}, $lcWant);
|
625
631
|
} elsif ($fam != 1 and not $$tagInfo{AllowGroup}) {
|
626
632
|
next if $lcWant eq lc $grp[$fam];
|
627
633
|
if ($wgAll and not $fam and $allFam0{$lcWant}) {
|
@@ -1258,6 +1264,7 @@ sub SetNewValuesFromFile($$;@)
|
|
1258
1264
|
Filter => $$options{Filter},
|
1259
1265
|
FixBase => $$options{FixBase},
|
1260
1266
|
GlobalTimeShift => $$options{GlobalTimeShift},
|
1267
|
+
HexTagIDs => $$options{HexTagIDs},
|
1261
1268
|
IgnoreMinorErrors=>$$options{IgnoreMinorErrors},
|
1262
1269
|
Lang => $$options{Lang},
|
1263
1270
|
LargeFileSupport=> $$options{LargeFileSupport},
|
@@ -1409,7 +1416,9 @@ sub SetNewValuesFromFile($$;@)
|
|
1409
1416
|
foreach (split /:/, $grp) {
|
1410
1417
|
# save family/groups in list (ignoring 'all' and '*')
|
1411
1418
|
next unless length($_) and /^(\d+)?(.*)/;
|
1412
|
-
|
1419
|
+
my ($f, $g) = ($1, $2);
|
1420
|
+
$f = 7 if $g =~ s/^ID-//i;
|
1421
|
+
push @fg, [ $f, $g ] unless $g eq '*' or $g eq 'all';
|
1413
1422
|
}
|
1414
1423
|
}
|
1415
1424
|
# allow ValueConv to be specified by a '#' on the tag name
|
@@ -1475,10 +1484,12 @@ SET: foreach $set (@setList) {
|
|
1475
1484
|
}
|
1476
1485
|
foreach (@{$$set[0]}) {
|
1477
1486
|
my ($f, $g) = @$_;
|
1478
|
-
if (defined $f) {
|
1479
|
-
next SET unless defined $grp[$f] and $g eq $grp[$f];
|
1480
|
-
} else {
|
1487
|
+
if (not defined $f) {
|
1481
1488
|
next SET unless $grp{$g};
|
1489
|
+
} elsif ($f == 7) {
|
1490
|
+
next SET unless IsSameID($srcExifTool->GetTagID($tag), $g);
|
1491
|
+
} else {
|
1492
|
+
next SET unless defined $grp[$f] and $g eq $grp[$f];
|
1482
1493
|
}
|
1483
1494
|
}
|
1484
1495
|
}
|
@@ -1598,21 +1609,25 @@ sub GetNewValue($$;$)
|
|
1598
1609
|
$nvHash = $self->GetNewValueHash($tagInfo);
|
1599
1610
|
} else {
|
1600
1611
|
# separate group from tag name
|
1601
|
-
|
1612
|
+
my @groups;
|
1613
|
+
@groups = split ':', $1 if $tag =~ s/(.*)://;
|
1602
1614
|
my @tagInfoList = FindTagInfo($tag);
|
1603
1615
|
# decide which tag we want
|
1604
1616
|
GNV_TagInfo: foreach $tagInfo (@tagInfoList) {
|
1605
1617
|
my $nvh = $self->GetNewValueHash($tagInfo) or next;
|
1606
|
-
# select tag in specified group if necessary
|
1607
|
-
|
1618
|
+
# select tag in specified group(s) if necessary
|
1619
|
+
foreach (@groups) {
|
1620
|
+
next if $_ eq $$nvh{WriteGroup};
|
1608
1621
|
my @grps = $self->GetGroup($tagInfo);
|
1609
1622
|
if ($grps[0] eq $$nvh{WriteGroup}) {
|
1610
1623
|
# check family 1 group only if WriteGroup is not specific
|
1611
|
-
|
1624
|
+
next if $_ eq $grps[1];
|
1612
1625
|
} else {
|
1613
1626
|
# otherwise check family 0 group
|
1614
|
-
|
1627
|
+
next if $_ eq $grps[0];
|
1615
1628
|
}
|
1629
|
+
# also check family 7
|
1630
|
+
next if /^ID-(.*)/i and IsSameID($$tagInfo{TagID}, $1);
|
1616
1631
|
# step to next entry in list
|
1617
1632
|
$nvh = $$nvh{Next} or next GNV_TagInfo;
|
1618
1633
|
}
|
@@ -2007,7 +2022,7 @@ sub SetFileName($$;$$$)
|
|
2007
2022
|
|
2008
2023
|
#------------------------------------------------------------------------------
|
2009
2024
|
# Set file permissions, group/user id and various MDItem tags from new tag values
|
2010
|
-
# Inputs: 0)
|
2025
|
+
# Inputs: 0) ExifTool ref, 1) file name or glob (must be a name for MDItem tags)
|
2011
2026
|
# Returns: 1=something was set OK, 0=didn't try, -1=error (and warning set)
|
2012
2027
|
# Notes: There may be errors even if 1 is returned
|
2013
2028
|
sub SetSystemTags($$)
|
@@ -3269,7 +3284,7 @@ sub IsSameFile($$$)
|
|
3269
3284
|
|
3270
3285
|
#------------------------------------------------------------------------------
|
3271
3286
|
# Is this a raw file type?
|
3272
|
-
# Inputs: 0)
|
3287
|
+
# Inputs: 0) ExifTool ref
|
3273
3288
|
# Returns: true if FileType is a type of RAW image
|
3274
3289
|
sub IsRawType($)
|
3275
3290
|
{
|
@@ -4020,6 +4035,7 @@ sub WriteDirectory($$$;$)
|
|
4020
4035
|
if ($dataPt or $$dirInfo{RAF}) {
|
4021
4036
|
++$$self{CHANGED};
|
4022
4037
|
$out and print $out " Deleting $grp1\n";
|
4038
|
+
$self->Warn('ICC_Profile deleted. Image colors may be affected') if $grp1 eq 'ICC_Profile';
|
4023
4039
|
# can no longer validate TIFF_END if deleting an entire IFD
|
4024
4040
|
delete $$self{TIFF_END} if $dirName =~ /IFD/;
|
4025
4041
|
}
|
@@ -4691,17 +4707,17 @@ sub InverseDateTime($$;$$)
|
|
4691
4707
|
{
|
4692
4708
|
my ($self, $val, $tzFlag, $dateOnly) = @_;
|
4693
4709
|
my ($rtnVal, $tz);
|
4710
|
+
my $fmt = $$self{OPTIONS}{DateFormat};
|
4694
4711
|
# strip off timezone first if it exists
|
4695
|
-
if ($val =~ s/([+-])(\d{1,2}):?(\d{2})\s*(DST)?$//i) {
|
4712
|
+
if (not $fmt and $val =~ s/([+-])(\d{1,2}):?(\d{2})\s*(DST)?$//i) {
|
4696
4713
|
$tz = sprintf("$1%.2d:$3", $2);
|
4697
|
-
} elsif ($val =~ s/Z$//i) {
|
4714
|
+
} elsif (not $fmt and $val =~ s/Z$//i) {
|
4698
4715
|
$tz = 'Z';
|
4699
4716
|
} else {
|
4700
4717
|
$tz = '';
|
4701
4718
|
# allow special value of 'now'
|
4702
4719
|
return $self->TimeNow($tzFlag) if lc($val) eq 'now';
|
4703
4720
|
}
|
4704
|
-
my $fmt = $$self{OPTIONS}{DateFormat};
|
4705
4721
|
# only convert date if a format was specified and the date is recognizable
|
4706
4722
|
if ($fmt) {
|
4707
4723
|
unless (defined $strptimeLib) {
|
@@ -5525,7 +5541,11 @@ sub WriteJPEG($$)
|
|
5525
5541
|
my $buff = $self->WriteDirectory(\%dirInfo, $tagTablePtr, \&WriteTIFF);
|
5526
5542
|
if (defined $buff and length $buff) {
|
5527
5543
|
if (length($buff) + length($exifAPP1hdr) > $maxSegmentLen) {
|
5528
|
-
$self->
|
5544
|
+
if ($self->Options('NoMultiExif')) {
|
5545
|
+
$self->Error('EXIF is too large for JPEG segment');
|
5546
|
+
} else {
|
5547
|
+
$self->Warn('Creating multi-segment EXIF',1);
|
5548
|
+
}
|
5529
5549
|
}
|
5530
5550
|
# switch to buffered output if required
|
5531
5551
|
if (($$self{PREVIEW_INFO} or $$self{LeicaTrailer}) and not $oldOutfile) {
|
@@ -5891,6 +5911,7 @@ sub WriteJPEG($$)
|
|
5891
5911
|
# group delete of APP segments
|
5892
5912
|
if ($$delGroup{$dirName}) {
|
5893
5913
|
$verbose and print $out " Deleting $dirName segment\n";
|
5914
|
+
$self->Warn('ICC_Profile deleted. Image colors may be affected') if $dirName eq 'ICC_Profile';
|
5894
5915
|
++$$self{CHANGED};
|
5895
5916
|
next Marker;
|
5896
5917
|
}
|
@@ -5997,7 +6018,11 @@ sub WriteJPEG($$)
|
|
5997
6018
|
# delete segment if IFD contains no entries
|
5998
6019
|
length $$segDataPt or $del = 1, last;
|
5999
6020
|
if (length($$segDataPt) + length($exifAPP1hdr) > $maxSegmentLen) {
|
6000
|
-
$self->
|
6021
|
+
if ($self->Options('NoMultiExif')) {
|
6022
|
+
$self->Error('EXIF is too large for JPEG segment');
|
6023
|
+
} else {
|
6024
|
+
$self->Warn('Writing multi-segment EXIF',1);
|
6025
|
+
}
|
6001
6026
|
}
|
6002
6027
|
# switch to buffered output if required
|
6003
6028
|
if (($$self{PREVIEW_INFO} or $$self{LeicaTrailer}) and not $oldOutfile) {
|
@@ -6779,7 +6804,7 @@ sub WriteBinaryData($$$)
|
|
6779
6804
|
my $val = ReadValue($dataPt, $entry, $format, $count, $dirLen-$entry);
|
6780
6805
|
next unless defined $val;
|
6781
6806
|
my $nvHash = $self->GetNewValueHash($tagInfo, $$self{CUR_WRITE_GROUP});
|
6782
|
-
next unless $self->IsOverwriting($nvHash, $val);
|
6807
|
+
next unless $self->IsOverwriting($nvHash, $val) > 0;
|
6783
6808
|
my $newVal = $self->GetNewValue($nvHash);
|
6784
6809
|
next unless defined $newVal; # can't delete from a binary table
|
6785
6810
|
# update DataMember with new value if necessary
|
@@ -25,7 +25,8 @@
|
|
25
25
|
# 10) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart2.pdf (Oct 2008)
|
26
26
|
# 11) http://www.extensis.com/en/support/kb_article.jsp?articleNumber=6102211
|
27
27
|
# 12) http://www.cipa.jp/std/documents/e/DC-010-2012_E.pdf
|
28
|
-
# 13) http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf
|
28
|
+
# 13) http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf (changed to
|
29
|
+
# http://www.cipa.jp/std/documents/e/DC-X010-2017.pdf)
|
29
30
|
#
|
30
31
|
# Notes: - Property qualifiers are handled as if they were separate
|
31
32
|
# properties (with no associated namespace).
|
@@ -49,7 +50,7 @@ use Image::ExifTool::Exif;
|
|
49
50
|
use Image::ExifTool::GPS;
|
50
51
|
require Exporter;
|
51
52
|
|
52
|
-
$VERSION = '3.
|
53
|
+
$VERSION = '3.36';
|
53
54
|
@ISA = qw(Exporter);
|
54
55
|
@EXPORT_OK = qw(EscapeXML UnescapeXML);
|
55
56
|
|
@@ -889,6 +890,7 @@ my %sRetouchArea = (
|
|
889
890
|
ModifyDate => { Groups => { 2 => 'Time' }, %dateTimeInfo, Priority => 0 },
|
890
891
|
Nickname => { },
|
891
892
|
Rating => { Writable => 'real', Notes => 'a value from 0 to 5, or -1 for "rejected"' },
|
893
|
+
RatingPercent=>{ Writable => 'real', Avoid => 1, Notes => 'non-standard' },
|
892
894
|
Thumbnails => {
|
893
895
|
FlatName => 'Thumbnail',
|
894
896
|
Struct => \%sThumbnail,
|
@@ -1144,7 +1146,7 @@ my %sPantryItem = (
|
|
1144
1146
|
LayerText => { },
|
1145
1147
|
},
|
1146
1148
|
},
|
1147
|
-
TransmissionReference
|
1149
|
+
TransmissionReference => { Notes => 'Now used as a job identifier' },
|
1148
1150
|
Urgency => {
|
1149
1151
|
Writable => 'integer',
|
1150
1152
|
Notes => 'should be in the range 1-8 to conform with the XMP spec',
|
@@ -1289,11 +1291,11 @@ my %sPantryItem = (
|
|
1289
1291
|
SharpenDetail => { Writable => 'integer' },
|
1290
1292
|
SharpenEdgeMasking => { Writable => 'integer' },
|
1291
1293
|
SharpenRadius => { Writable => 'real' },
|
1292
|
-
SplitToningBalance => { Writable => 'integer' },
|
1293
|
-
SplitToningHighlightHue => { Writable => 'integer' },
|
1294
|
-
SplitToningHighlightSaturation => { Writable => 'integer' },
|
1295
|
-
SplitToningShadowHue => { Writable => 'integer' },
|
1296
|
-
SplitToningShadowSaturation => { Writable => 'integer' },
|
1294
|
+
SplitToningBalance => { Writable => 'integer', Notes => 'also used for newer ColorGrade settings' },
|
1295
|
+
SplitToningHighlightHue => { Writable => 'integer', Notes => 'also used for newer ColorGrade settings' },
|
1296
|
+
SplitToningHighlightSaturation => { Writable => 'integer', Notes => 'also used for newer ColorGrade settings' },
|
1297
|
+
SplitToningShadowHue => { Writable => 'integer', Notes => 'also used for newer ColorGrade settings' },
|
1298
|
+
SplitToningShadowSaturation => { Writable => 'integer', Notes => 'also used for newer ColorGrade settings' },
|
1297
1299
|
Vibrance => { Writable => 'integer' },
|
1298
1300
|
# new tags written by LR 1.4 (not sure in what version they first appeared)
|
1299
1301
|
GrayMixerRed => { Writable => 'integer' },
|
@@ -1482,9 +1484,71 @@ my %sPantryItem = (
|
|
1482
1484
|
Struct => {
|
1483
1485
|
STRUCT_NAME => 'Look',
|
1484
1486
|
NAMESPACE => 'crs',
|
1485
|
-
Name
|
1487
|
+
Name => { },
|
1488
|
+
Amount => { },
|
1489
|
+
Cluster => { },
|
1490
|
+
UUID => { },
|
1491
|
+
SupportsMonochrome => { },
|
1492
|
+
SupportsAmount => { },
|
1493
|
+
SupportsOutputReferred => { },
|
1494
|
+
Copyright => { },
|
1495
|
+
Group => { Writable => 'lang-alt' },
|
1496
|
+
Parameters => {
|
1497
|
+
Struct => {
|
1498
|
+
STRUCT_NAME => 'LookParms',
|
1499
|
+
NAMESPACE => 'crs',
|
1500
|
+
Version => { },
|
1501
|
+
ProcessVersion => { },
|
1502
|
+
Clarity2012 => { },
|
1503
|
+
ConvertToGrayscale => { },
|
1504
|
+
CameraProfile => { },
|
1505
|
+
LookTable => { },
|
1506
|
+
ToneCurvePV2012 => { List => 'Seq' },
|
1507
|
+
},
|
1508
|
+
},
|
1486
1509
|
}
|
1487
1510
|
},
|
1511
|
+
# more again (ref forum11258)
|
1512
|
+
GrainSeed => { },
|
1513
|
+
ClipboardOrientation => { Writable => 'integer' },
|
1514
|
+
ClipboardAspectRatio => { Writable => 'integer' },
|
1515
|
+
PresetType => { },
|
1516
|
+
Cluster => { },
|
1517
|
+
UUID => { Avoid => 1 },
|
1518
|
+
SupportsAmount => { Writable => 'boolean' },
|
1519
|
+
SupportsColor => { Writable => 'boolean' },
|
1520
|
+
SupportsMonochrome => { Writable => 'boolean' },
|
1521
|
+
SupportsHighDynamicRange=> { Writable => 'boolean' },
|
1522
|
+
SupportsNormalDynamicRange=> { Writable => 'boolean' },
|
1523
|
+
SupportsSceneReferred => { Writable => 'boolean' },
|
1524
|
+
SupportsOutputReferred => { Writable => 'boolean' },
|
1525
|
+
CameraModelRestriction => { },
|
1526
|
+
Copyright => { Avoid => 1 },
|
1527
|
+
ContactInfo => { },
|
1528
|
+
GrainSeed => { Writable => 'integer' },
|
1529
|
+
Name => { Writable => 'lang-alt', Avoid => 1 },
|
1530
|
+
ShortName => { Writable => 'lang-alt' },
|
1531
|
+
SortName => { Writable => 'lang-alt' },
|
1532
|
+
Group => { Writable => 'lang-alt', Avoid => 1 },
|
1533
|
+
Description => { Writable => 'lang-alt', Avoid => 1 },
|
1534
|
+
# new for DNG converter 13.0
|
1535
|
+
LookName => { NotFlat => 1 }, # (grr... conflicts with "Name" element of "Look" struct!)
|
1536
|
+
# new for Lightroom CC 2021 (ref forum11745)
|
1537
|
+
ColorGradeMidtoneHue => { Writable => 'integer' },
|
1538
|
+
ColorGradeMidtoneSat => { Writable => 'integer' },
|
1539
|
+
ColorGradeShadowLum => { Writable => 'integer' },
|
1540
|
+
ColorGradeMidtoneLum => { Writable => 'integer' },
|
1541
|
+
ColorGradeHighlightLum => { Writable => 'integer' },
|
1542
|
+
ColorGradeBlending => { Writable => 'integer' },
|
1543
|
+
ColorGradeGlobalHue => { Writable => 'integer' },
|
1544
|
+
ColorGradeGlobalSat => { Writable => 'integer' },
|
1545
|
+
ColorGradeGlobalLum => { Writable => 'integer' },
|
1546
|
+
# new for Adobe Camera Raw 13 (ref forum11745)
|
1547
|
+
LensProfileIsEmbedded => { Writable => 'boolean'},
|
1548
|
+
AutoToneDigest => { },
|
1549
|
+
AutoToneDigestNoSat => { },
|
1550
|
+
ToggleStyleDigest => { },
|
1551
|
+
ToggleStyleAmount => { Writable => 'integer' },
|
1488
1552
|
);
|
1489
1553
|
|
1490
1554
|
# Tiff namespace properties (tiff)
|
@@ -2042,7 +2106,7 @@ my %sPantryItem = (
|
|
2042
2106
|
PRIORITY => 0, # not as reliable as actual EXIF tags
|
2043
2107
|
NOTES => q{
|
2044
2108
|
EXIF tags added by the EXIF 2.31 for XMP specification (see
|
2045
|
-
L<http://www.cipa.jp/std/documents/e/DC-
|
2109
|
+
L<http://www.cipa.jp/std/documents/e/DC-X010-2017.pdf>).
|
2046
2110
|
},
|
2047
2111
|
Gamma => { Writable => 'rational' },
|
2048
2112
|
PhotographicSensitivity => { Writable => 'integer' },
|
@@ -2747,8 +2811,9 @@ sub AddFlattenedTags($;$$)
|
|
2747
2811
|
if ($flatInfo) {
|
2748
2812
|
ref $flatInfo eq 'HASH' or warn("$flatInfo is not a HASH!\n"), next; # (to be safe)
|
2749
2813
|
# pre-defined flattened tags should have Flat flag set
|
2750
|
-
if (not defined $$flatInfo{Flat}
|
2751
|
-
|
2814
|
+
if (not defined $$flatInfo{Flat}) {
|
2815
|
+
next if $$flatInfo{NotFlat};
|
2816
|
+
warn "Missing Flat flag for $$flatInfo{Name}\n" if $Image::ExifTool::debug;
|
2752
2817
|
}
|
2753
2818
|
$$flatInfo{Flat} = 0;
|
2754
2819
|
# copy all missing entries from field information
|
@@ -2935,13 +3000,15 @@ sub PrintLensID(@)
|
|
2935
3000
|
# for Pentax, CS4 stores an int16u, but we use 2 x int8u
|
2936
3001
|
$id = join(' ', unpack('C*', pack('n', $id)));
|
2937
3002
|
}
|
2938
|
-
my $str = $$printConv{$id} || "Unknown ($id)";
|
2939
3003
|
# Nikon is a special case because Adobe doesn't store the full LensID
|
3004
|
+
# (Apple Photos does, but we have to convert back to hex)
|
2940
3005
|
if ($mk eq 'Nikon') {
|
2941
|
-
|
3006
|
+
$id = sprintf('%X', $id);
|
3007
|
+
$id = "0$id" if length($id) & 0x01; # pad with leading 0 if necessary
|
3008
|
+
$id =~ s/(..)/$1 /g and $id =~ s/ $//; # put spaces between bytes
|
2942
3009
|
my (%newConv, %used);
|
2943
3010
|
my $i = 0;
|
2944
|
-
foreach (grep /^$
|
3011
|
+
foreach (grep /^$id/, keys %$printConv) {
|
2945
3012
|
my $lens = $$printConv{$_};
|
2946
3013
|
next if $used{$lens}; # avoid duplicates
|
2947
3014
|
$used{$lens} = 1;
|
@@ -2950,6 +3017,7 @@ sub PrintLensID(@)
|
|
2950
3017
|
}
|
2951
3018
|
$printConv = \%newConv;
|
2952
3019
|
}
|
3020
|
+
my $str = $$printConv{$id} || "Unknown ($id)";
|
2953
3021
|
return Image::ExifTool::Exif::PrintLensID($et, $str, $printConv,
|
2954
3022
|
undef, $id, $focalLength, $sa, $maxAv, $sf, $lf, $lensModel);
|
2955
3023
|
}
|
@@ -3187,8 +3255,9 @@ NoLoop:
|
|
3187
3255
|
#} elsif (grep / /, @$props) {
|
3188
3256
|
# $$tagInfo{List} = 1;
|
3189
3257
|
}
|
3258
|
+
# save property list for verbose "adding" message unless this tag already exists
|
3259
|
+
$added = \@tagList unless $$tagTablePtr{$tagID};
|
3190
3260
|
AddTagToTable($tagTablePtr, $tagID, $tagInfo);
|
3191
|
-
$added = 1;
|
3192
3261
|
last;
|
3193
3262
|
}
|
3194
3263
|
# decode value if necessary (et:encoding was used before exiftool 7.71)
|
@@ -3272,8 +3341,16 @@ NoLoop:
|
|
3272
3341
|
}
|
3273
3342
|
if ($$et{OPTIONS}{Verbose}) {
|
3274
3343
|
if ($added) {
|
3344
|
+
my $props;
|
3345
|
+
if (@$added > 1) {
|
3346
|
+
$$tagInfo{Flat} = 0; # this is a flattened tag
|
3347
|
+
my @props = map { $$_[0] } @$added;
|
3348
|
+
$props = ' (' . join('/',@props) . ')';
|
3349
|
+
} else {
|
3350
|
+
$props = '';
|
3351
|
+
}
|
3275
3352
|
my $g1 = $et->GetGroup($key, 1);
|
3276
|
-
$et->VPrint(0, $$et{INDENT}, "[adding $g1:$tag]\n");
|
3353
|
+
$et->VPrint(0, $$et{INDENT}, "[adding $g1:$tag]$props\n");
|
3277
3354
|
}
|
3278
3355
|
my $tagID = join('/',@$props);
|
3279
3356
|
$et->VerboseInfo($tagID, $tagInfo, Value => $rawVal || $val);
|
@@ -3531,6 +3608,11 @@ sub ParseXMPElement($$$;$$$$)
|
|
3531
3608
|
# add svg namespace prefix if missing to ignore these entries in the tag name
|
3532
3609
|
$$propList[-1] = "svg:$prop";
|
3533
3610
|
}
|
3611
|
+
} elsif ($$et{XmpIgnoreProps}) { # ignore specified properties for tag name
|
3612
|
+
foreach (@{$$et{XmpIgnoreProps}}) {
|
3613
|
+
last unless @$propList;
|
3614
|
+
pop @$propList if $_ eq $$propList[0];
|
3615
|
+
}
|
3534
3616
|
}
|
3535
3617
|
|
3536
3618
|
# handle properties inside element attributes (RDF shorthand format):
|