exiftool_vendored 10.58.0 → 10.65.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 +100 -1
- data/bin/MANIFEST +2 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +39 -38
- data/bin/arg_files/exif2iptc.args +3 -0
- data/bin/arg_files/iptc2exif.args +3 -0
- data/bin/config_files/example.config +16 -14
- data/bin/config_files/photoshop_paths.config +10 -0
- data/bin/exiftool +71 -65
- data/bin/lib/Image/ExifTool/APE.pm +5 -0
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +31 -15
- data/bin/lib/Image/ExifTool/Canon.pm +18 -4
- data/bin/lib/Image/ExifTool/CanonCustom.pm +3 -0
- data/bin/lib/Image/ExifTool/Charset/DOSLatin1.pm +49 -0
- data/bin/lib/Image/ExifTool/Charset/DOSLatinUS.pm +49 -0
- data/bin/lib/Image/ExifTool/Charset.pm +8 -5
- data/bin/lib/Image/ExifTool/Exif.pm +37 -18
- data/bin/lib/Image/ExifTool/FLAC.pm +47 -37
- data/bin/lib/Image/ExifTool/FLIR.pm +3 -3
- data/bin/lib/Image/ExifTool/FujiFilm.pm +5 -2
- data/bin/lib/Image/ExifTool/GPS.pm +6 -6
- data/bin/lib/Image/ExifTool/Geotag.pm +1 -1
- data/bin/lib/Image/ExifTool/H264.pm +2 -0
- data/bin/lib/Image/ExifTool/ID3.pm +8 -3
- data/bin/lib/Image/ExifTool/IPTC.pm +1 -1
- data/bin/lib/Image/ExifTool/Import.pm +4 -1
- data/bin/lib/Image/ExifTool/InDesign.pm +11 -7
- data/bin/lib/Image/ExifTool/Kodak.pm +4 -1
- data/bin/lib/Image/ExifTool/Lang/de.pm +31 -31
- data/bin/lib/Image/ExifTool/MWG.pm +12 -4
- data/bin/lib/Image/ExifTool/MakerNotes.pm +3 -3
- data/bin/lib/Image/ExifTool/Matroska.pm +2 -1
- data/bin/lib/Image/ExifTool/Microsoft.pm +3 -3
- data/bin/lib/Image/ExifTool/Minolta.pm +71 -61
- data/bin/lib/Image/ExifTool/Nikon.pm +286 -43
- data/bin/lib/Image/ExifTool/NikonCustom.pm +1049 -0
- data/bin/lib/Image/ExifTool/Olympus.pm +4 -1
- data/bin/lib/Image/ExifTool/PNG.pm +4 -7
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +24 -1
- data/bin/lib/Image/ExifTool/Pentax.pm +20 -6
- data/bin/lib/Image/ExifTool/Photoshop.pm +24 -3
- data/bin/lib/Image/ExifTool/QuickTime.pm +545 -14
- data/bin/lib/Image/ExifTool/README +16 -9
- data/bin/lib/Image/ExifTool/RIFF.pm +8 -1
- data/bin/lib/Image/ExifTool/Samsung.pm +5 -4
- data/bin/lib/Image/ExifTool/Sigma.pm +9 -1
- data/bin/lib/Image/ExifTool/Sony.pm +327 -153
- data/bin/lib/Image/ExifTool/TagLookup.pm +3273 -3220
- data/bin/lib/Image/ExifTool/TagNames.pod +317 -38
- data/bin/lib/Image/ExifTool/Validate.pm +15 -1
- data/bin/lib/Image/ExifTool/WriteExif.pl +5 -0
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +23 -1
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +8 -2
- data/bin/lib/Image/ExifTool/WriteXMP.pl +7 -0
- data/bin/lib/Image/ExifTool/Writer.pl +96 -18
- data/bin/lib/Image/ExifTool/XMP.pm +20 -11
- data/bin/lib/Image/ExifTool/XMP2.pl +634 -583
- data/bin/lib/Image/ExifTool.pm +124 -17
- data/bin/lib/Image/ExifTool.pod +86 -82
- data/bin/perl-Image-ExifTool.spec +38 -37
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +4 -2
@@ -11,7 +11,7 @@ package Image::ExifTool::Validate;
|
|
11
11
|
use strict;
|
12
12
|
use vars qw($VERSION %exifSpec);
|
13
13
|
|
14
|
-
$VERSION = '1.
|
14
|
+
$VERSION = '1.03';
|
15
15
|
|
16
16
|
use Image::ExifTool qw(:Utils);
|
17
17
|
use Image::ExifTool::Exif;
|
@@ -285,6 +285,20 @@ sub FinishValidate($$)
|
|
285
285
|
}
|
286
286
|
}
|
287
287
|
}
|
288
|
+
# validate file extension
|
289
|
+
if ($$et{FILENAME} ne '') {
|
290
|
+
my $fileExt = ($$et{FILENAME} =~ /^.*\.([^.]+)$/s) ? uc($1) : '';
|
291
|
+
my $extFileType = Image::ExifTool::GetFileType($fileExt);
|
292
|
+
if ($extFileType and $extFileType ne $fileType) {
|
293
|
+
my $normExt = $$et{VALUE}{FileTypeExtension};
|
294
|
+
if ($normExt and $normExt ne $fileExt) {
|
295
|
+
my $lkup = $Image::ExifTool::fileTypeLookup{$fileExt};
|
296
|
+
if (ref $lkup or $lkup ne $normExt) {
|
297
|
+
$et->Warn("File has wrong extension (should be $normExt, not $fileExt)");
|
298
|
+
}
|
299
|
+
}
|
300
|
+
}
|
301
|
+
}
|
288
302
|
MakeValidateTag($et) if $mkTag;
|
289
303
|
}
|
290
304
|
|
@@ -563,6 +563,8 @@ sub WriteExif($$$)
|
|
563
563
|
# update local variables from fixed values
|
564
564
|
$base = $$dirInfo{Base};
|
565
565
|
$dataPos = $$dirInfo{DataPos};
|
566
|
+
# changed if ForceWrite tag was was set to "FixBase"
|
567
|
+
++$$et{CHANGED} if $$et{FORCE_WRITE}{FixBase};
|
566
568
|
}
|
567
569
|
|
568
570
|
# initialize variables to handle mandatory tags
|
@@ -2451,6 +2453,9 @@ NoOverwrite: next if $isNew > 0;
|
|
2451
2453
|
# (could be up to 10 bytes and still be empty)
|
2452
2454
|
$newData = '' if defined $newData and length($newData) < 12;
|
2453
2455
|
|
2456
|
+
# set changed if ForceWrite tag was set to "EXIF"
|
2457
|
+
++$$et{CHANGED} if defined $newData and length $newData and $$et{FORCE_WRITE}{EXIF};
|
2458
|
+
|
2454
2459
|
return $newData; # return our directory data
|
2455
2460
|
}
|
2456
2461
|
|
@@ -127,7 +127,7 @@ sub CheckIPTC($$$)
|
|
127
127
|
$len = $minlen;
|
128
128
|
}
|
129
129
|
}
|
130
|
-
if (defined $minlen) {
|
130
|
+
if (defined $minlen and $fmt ne 'string') { # (must truncate strings later, after recoding)
|
131
131
|
$maxlen or $maxlen = $minlen;
|
132
132
|
if ($len < $minlen) {
|
133
133
|
unless ($$et{OPTIONS}{IgnoreMinorErrors}) {
|
@@ -185,6 +185,26 @@ sub FormatIPTC($$$$$;$)
|
|
185
185
|
} elsif ($$xlatPtr and $rec < 7 and $$valPtr =~ /[\x80-\xff]/) {
|
186
186
|
TranslateCodedString($et, $valPtr, $xlatPtr, $read);
|
187
187
|
}
|
188
|
+
# must check length now (after any string recoding)
|
189
|
+
if (not $read and $format =~ /^string\[(\d+),?(\d*)\]$/) {
|
190
|
+
my ($minlen, $maxlen) = ($1, $2);
|
191
|
+
my $len = length $$valPtr;
|
192
|
+
$maxlen or $maxlen = $minlen;
|
193
|
+
if ($len < $minlen) {
|
194
|
+
if ($et->Warn("String to short for IPTC:$$tagInfo{Name} (padded)", 2)) {
|
195
|
+
$$valPtr .= ' ' x ($minlen - $len);
|
196
|
+
}
|
197
|
+
} elsif ($len > $maxlen) {
|
198
|
+
if ($et->Warn("IPTC:$$tagInfo{Name} exceeds length limit (truncated)", 2)) {
|
199
|
+
$$valPtr = substr($$valPtr, 0, $maxlen);
|
200
|
+
# make sure UTF-8 is still valid
|
201
|
+
if (($$xlatPtr || $et->Options('Charset')) eq 'UTF8') {
|
202
|
+
require Image::ExifTool::XMP;
|
203
|
+
Image::ExifTool::XMP::FixUTF8($valPtr,'.');
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
}
|
188
208
|
}
|
189
209
|
}
|
190
210
|
|
@@ -670,6 +690,8 @@ sub WriteIPTC($$$)
|
|
670
690
|
}
|
671
691
|
last;
|
672
692
|
}
|
693
|
+
# set changed if ForceWrite tag was set to "IPTC"
|
694
|
+
++$$et{CHANGED} if defined $newData and length $newData and $$et{FORCE_WRITE}{IPTC};
|
673
695
|
return $newData;
|
674
696
|
}
|
675
697
|
|
@@ -23,6 +23,7 @@ my %mp4Map = (
|
|
23
23
|
my %dirMap = (
|
24
24
|
MOV => \%movMap,
|
25
25
|
MP4 => \%mp4Map,
|
26
|
+
HEIC => { }, # can't currently write XMP to HEIC files
|
26
27
|
);
|
27
28
|
|
28
29
|
#------------------------------------------------------------------------------
|
@@ -135,7 +136,7 @@ sub WriteQuickTime($$$)
|
|
135
136
|
undef $tagInfo;
|
136
137
|
}
|
137
138
|
}
|
138
|
-
if ($tagInfo) {
|
139
|
+
if ($tagInfo and (not defined $$tagInfo{Writable} or $$tagInfo{Writable})) {
|
139
140
|
# read the atom data
|
140
141
|
$raf->Read($buff, $size) == $size or $et->Error("Error reading $tag data"), last;
|
141
142
|
my $subdir = $$tagInfo{SubDirectory};
|
@@ -310,7 +311,12 @@ sub WriteMOV($$)
|
|
310
311
|
$buff !~ /^(....)+(qt )/s)
|
311
312
|
{
|
312
313
|
# file is MP4 format if 'ftyp' exists without 'qt ' as a compatible brand
|
313
|
-
$
|
314
|
+
if ($buff =~ /^(heic|mif1|msf1|heix|hevc|hevx)/) {
|
315
|
+
$ftype = 'HEIC';
|
316
|
+
$et->Error("Can't currently write HEIC/HEIF files");
|
317
|
+
} else {
|
318
|
+
$ftype = 'MP4';
|
319
|
+
}
|
314
320
|
} else {
|
315
321
|
$ftype = 'MOV';
|
316
322
|
}
|
@@ -688,6 +688,12 @@ sub WriteXMP($$;$)
|
|
688
688
|
}
|
689
689
|
delete $$et{XMP_ERROR};
|
690
690
|
delete $$et{XMP_ABOUT};
|
691
|
+
|
692
|
+
# call InitWriteDirs to initialize FORCE_WRITE flags if necessary
|
693
|
+
$et->InitWriteDirs({}, 'XMP') if $xmpFile and $et->GetNewValue('ForceWrite');
|
694
|
+
# set changed if we are ForceWrite tag was set to "XMP"
|
695
|
+
++$changed if $$et{FORCE_WRITE}{XMP};
|
696
|
+
|
691
697
|
} elsif (defined $about) {
|
692
698
|
$et->VerboseValue('+ XMP-rdf:About', $about);
|
693
699
|
$about = EscapeXML($about); # must escape for XML
|
@@ -1116,6 +1122,7 @@ sub WriteXMP($$;$)
|
|
1116
1122
|
my $maxDataLen = $$dirInfo{MaxDataLen};
|
1117
1123
|
# get DataPt again because it may have been set by ProcessXMP
|
1118
1124
|
$dataPt = $$dirInfo{DataPt};
|
1125
|
+
|
1119
1126
|
# return now if we didn't change anything
|
1120
1127
|
unless ($changed or ($maxDataLen and $dataPt and defined $$dataPt and
|
1121
1128
|
length($$dataPt) > $maxDataLen))
|
@@ -268,7 +268,7 @@ my %ignorePrintConv = map { $_ => 1 } qw(OTHER BITMASK Notes);
|
|
268
268
|
# WriteGroup - group name where information is being written (correct case)
|
269
269
|
# WantGroup - group name as specified in call to function (case insensitive)
|
270
270
|
# Next - pointer to next new value hash (if more than one)
|
271
|
-
# NoReplace - set
|
271
|
+
# NoReplace - set if value was created with Replace=0
|
272
272
|
# AddBefore - number of list items added by a subsequent Replace=0 call
|
273
273
|
# IsNVH - Flag indicating this is a new value hash
|
274
274
|
# Shift - shift value
|
@@ -900,7 +900,7 @@ TAG: foreach $tagInfo (@matchingTags) {
|
|
900
900
|
my $nvHash = $self->GetNewValueHash($tagInfo, $writeGroup, 'create', $options{ProtectSaved});
|
901
901
|
# ignore new values protected with ProtectSaved
|
902
902
|
$nvHash or ++$numSet, next; # (increment $numSet to avoid warning)
|
903
|
-
$$nvHash{NoReplace} = 1
|
903
|
+
$$nvHash{NoReplace} = 1 unless $options{Replace};
|
904
904
|
$$nvHash{WantGroup} = $wantGroup;
|
905
905
|
$$nvHash{EditOnly} = 1 if $editOnly;
|
906
906
|
# save maker note information if writing maker notes
|
@@ -1619,7 +1619,7 @@ sub CountNewValues($)
|
|
1619
1619
|
# Save new values for subsequent restore
|
1620
1620
|
# Inputs: 0) ExifTool object reference
|
1621
1621
|
# Returns: Number of times new values have been saved
|
1622
|
-
# Notes: increments
|
1622
|
+
# Notes: increments SAVE_COUNT flag each time routine is called
|
1623
1623
|
sub SaveNewValues($)
|
1624
1624
|
{
|
1625
1625
|
my $self = shift;
|
@@ -2820,7 +2820,7 @@ sub InsertTagValues($$$;$)
|
|
2820
2820
|
}
|
2821
2821
|
# allow trailing '#' to indicate ValueConv value
|
2822
2822
|
$type = 'ValueConv' if $line =~ s/^#//;
|
2823
|
-
# (
|
2823
|
+
# (undocumented feature to allow '@' to evaluate values separately, but only in braces)
|
2824
2824
|
if ($bra and $line =~ s/^\@(#)?//) {
|
2825
2825
|
$asList = 1;
|
2826
2826
|
$type = 'ValueConv' if $1;
|
@@ -2933,7 +2933,7 @@ sub InsertTagValues($$$;$)
|
|
2933
2933
|
#### eval advanced formatting expression ($_, $self, @val, $advFmtSelf)
|
2934
2934
|
eval $expr;
|
2935
2935
|
$@ and $evalWarning = $@;
|
2936
|
-
$val = $_;
|
2936
|
+
$val = ref $_ eq 'ARRAY' ? join($$self{OPTIONS}{ListSep}, @$_): $_;
|
2937
2937
|
}
|
2938
2938
|
if ($evalWarning) {
|
2939
2939
|
my $str = CleanWarning() . " for '$var'";
|
@@ -3223,8 +3223,27 @@ sub IsOverwriting($$;$)
|
|
3223
3223
|
my $shiftType = $$tagInfo{Shift};
|
3224
3224
|
unless ($shiftType and $shiftType eq 'Time') {
|
3225
3225
|
unless (IsFloat($val)) {
|
3226
|
-
|
3227
|
-
|
3226
|
+
# do the ValueConv to try to get a number
|
3227
|
+
my $conv = $$tagInfo{ValueConv};
|
3228
|
+
if (defined $conv) {
|
3229
|
+
local $SIG{'__WARN__'} = \&SetWarning;
|
3230
|
+
undef $evalWarning;
|
3231
|
+
if (ref $conv eq 'CODE') {
|
3232
|
+
$val = &$conv($val, $self);
|
3233
|
+
} elsif (not ref $conv) {
|
3234
|
+
#### eval ValueConv ($val, $self)
|
3235
|
+
$val = eval $conv;
|
3236
|
+
$@ and $evalWarning = $@;
|
3237
|
+
}
|
3238
|
+
if ($evalWarning) {
|
3239
|
+
$self->Warn("ValueConv $$tagInfo{Name}: " . CleanWarning());
|
3240
|
+
return 0;
|
3241
|
+
}
|
3242
|
+
}
|
3243
|
+
unless (defined $val and IsFloat($val)) {
|
3244
|
+
$self->Warn("Can't shift $$tagInfo{Name} (not a number)");
|
3245
|
+
return 0;
|
3246
|
+
}
|
3228
3247
|
}
|
3229
3248
|
$shiftType = 'Number'; # allow any number to be shifted
|
3230
3249
|
}
|
@@ -3558,11 +3577,13 @@ sub GetLangInfo($$)
|
|
3558
3577
|
|
3559
3578
|
#------------------------------------------------------------------------------
|
3560
3579
|
# initialize ADD_DIRS and EDIT_DIRS hashes for all directories that need
|
3561
|
-
#
|
3580
|
+
# to be created or will have tags changed in them
|
3562
3581
|
# Inputs: 0) ExifTool object reference, 1) file type string (or map hash ref)
|
3563
3582
|
# 2) preferred family 0 group name for creating tags
|
3564
|
-
# Notes:
|
3565
|
-
#
|
3583
|
+
# Notes:
|
3584
|
+
# - the ADD_DIRS and EDIT_DIRS keys are the directory names, and the values
|
3585
|
+
# are the names of the parent directories (undefined for a top-level directory)
|
3586
|
+
# - also initializes FORCE_WRITE lookup
|
3566
3587
|
sub InitWriteDirs($$;$)
|
3567
3588
|
{
|
3568
3589
|
my ($self, $fileType, $preferredGroup) = @_;
|
@@ -3605,6 +3626,19 @@ sub InitWriteDirs($$;$)
|
|
3605
3626
|
$dirName = 'MIE' . ($1 || '');
|
3606
3627
|
}
|
3607
3628
|
my @dirNames;
|
3629
|
+
# allow a group name of '*' to force writing EXIF/IPTC/XMP (ForceWrite tag)
|
3630
|
+
if ($dirName eq '*' and $$nvHash{Value}) {
|
3631
|
+
my $val = $$nvHash{Value}[0];
|
3632
|
+
if ($val) {
|
3633
|
+
foreach (qw(EXIF IPTC XMP FixBase)) {
|
3634
|
+
next unless $val =~ /\b($_|All)\b/i;
|
3635
|
+
push @dirNames, $_;
|
3636
|
+
push @dirNames, 'EXIF' if $_ eq 'FixBase';
|
3637
|
+
$$self{FORCE_WRITE}{$_} = 1;
|
3638
|
+
}
|
3639
|
+
}
|
3640
|
+
$dirName = shift @dirNames;
|
3641
|
+
}
|
3608
3642
|
while ($dirName) {
|
3609
3643
|
my $parent = $$fileDirs{$dirName};
|
3610
3644
|
if (ref $parent) {
|
@@ -4278,6 +4312,58 @@ sub NewGUID()
|
|
4278
4312
|
$$ & 0xffff, rand(0x10000), rand(0x10000), rand(0x10000));
|
4279
4313
|
}
|
4280
4314
|
|
4315
|
+
#------------------------------------------------------------------------------
|
4316
|
+
# Make TIFF header for raw data
|
4317
|
+
# Inputs: 0) width, 1) height, 2) num colour components, 3) bits, 4) resolution
|
4318
|
+
# 5) color-map data for palette-color image (8 or 16 bit)
|
4319
|
+
# Returns: TIFF header
|
4320
|
+
# Notes: Multi-byte data must be little-endian
|
4321
|
+
sub MakeTiffHeader($$$$;$$)
|
4322
|
+
{
|
4323
|
+
my ($w, $h, $cols, $bits, $res, $cmap) = @_;
|
4324
|
+
$res or $res = 72;
|
4325
|
+
my $saveOrder = GetByteOrder();
|
4326
|
+
SetByteOrder('II');
|
4327
|
+
if (not $cmap) {
|
4328
|
+
$cmap = '';
|
4329
|
+
} elsif (length $cmap == 3 * 2**$bits) {
|
4330
|
+
# convert to short
|
4331
|
+
$cmap = pack 'v*', map { $_ | ($_<<8) } unpack 'C*', $cmap;
|
4332
|
+
} elsif (length $cmap != 6 * 2**$bits) {
|
4333
|
+
$cmap = '';
|
4334
|
+
}
|
4335
|
+
my $cmo = $cmap ? 12 : 0; # offset due to ColorMap IFD entry
|
4336
|
+
my $hdr =
|
4337
|
+
"\x49\x49\x2a\0\x08\0\0\0\x0e\0" . # 0x00 14 menu entries:
|
4338
|
+
"\xfe\x00\x04\0\x01\0\0\0\x00\0\0\0" . # 0x0a SubfileType = 0
|
4339
|
+
"\x00\x01\x04\0\x01\0\0\0" . Set32u($w) . # 0x16 ImageWidth
|
4340
|
+
"\x01\x01\x04\0\x01\0\0\0" . Set32u($h) . # 0x22 ImageHeight
|
4341
|
+
"\x02\x01\x03\0" . Set32u($cols) . # 0x2e BitsPerSample
|
4342
|
+
Set32u($cols == 1 ? $bits : 0xb6 + $cmo) .
|
4343
|
+
"\x03\x01\x03\0\x01\0\0\0\x01\0\0\0" . # 0x3a Compression = 1
|
4344
|
+
"\x06\x01\x03\0\x01\0\0\0" . # 0x46 PhotometricInterpretation
|
4345
|
+
Set32u($cmap ? 3 : $cols == 1 ? 1 : 2) .
|
4346
|
+
"\x11\x01\x04\0\x01\0\0\0" . # 0x52 StripOffsets
|
4347
|
+
Set32u(0xcc + $cmo + length($cmap)) .
|
4348
|
+
"\x15\x01\x03\0\x01\0\0\0" . Set32u($cols) . # 0x5e SamplesPerPixel
|
4349
|
+
"\x16\x01\x04\0\x01\0\0\0" . Set32u($h) . # 0x6a RowsPerStrip
|
4350
|
+
"\x17\x01\x04\0\x01\0\0\0" . # 0x76 StripByteCounts
|
4351
|
+
Set32u($w * $h * $cols * int(($bits+7)/8)) .
|
4352
|
+
"\x1a\x01\x05\0\x01\0\0\0" . Set32u(0xbc + $cmo) . # 0x82 XResolution
|
4353
|
+
"\x1b\x01\x05\0\x01\0\0\0" . Set32u(0xc4 + $cmo) . # 0x8e YResolution
|
4354
|
+
"\x1c\x01\x03\0\x01\0\0\0\x01\0\0\0" . # 0x9a PlanarConfiguration = 1
|
4355
|
+
"\x28\x01\x03\0\x01\0\0\0\x02\0\0\0" . # 0xa6 ResolutionUnit = 2
|
4356
|
+
($cmap ? # 0xb2 ColorMap [optional]
|
4357
|
+
"\x40\x01\x03\0" . Set32u(3 * 2**$bits) . "\xd8\0\0\0" : '') .
|
4358
|
+
"\0\0\0\0" . # 0xb2+$cmo (no IFD1)
|
4359
|
+
(Set16u($bits) x 3) . # 0xb6+$cmo BitsPerSample value
|
4360
|
+
Set32u($res) . "\x01\0\0\0" . # 0xbc+$cmo XResolution = 72
|
4361
|
+
Set32u($res) . "\x01\0\0\0" . # 0xc4+$cmo YResolution = 72
|
4362
|
+
$cmap; # 0xcc or 0xd8 (cmap and data go here)
|
4363
|
+
SetByteOrder($saveOrder);
|
4364
|
+
return $hdr;
|
4365
|
+
}
|
4366
|
+
|
4281
4367
|
#------------------------------------------------------------------------------
|
4282
4368
|
# Return current time in EXIF format
|
4283
4369
|
# Inputs: 0) flag to include timezone (0 to disable, undef or 1 to include)
|
@@ -5456,7 +5542,6 @@ sub WriteJPEG($$)
|
|
5456
5542
|
# rewrite this segment only if we are changing a tag which is contained in its
|
5457
5543
|
# directory (or deleting '*', in which case we need to identify the segment type)
|
5458
5544
|
while (exists $$editDirs{$markerName} or $$delGroup{'*'}) {
|
5459
|
-
my $oldChanged = $$self{CHANGED};
|
5460
5545
|
if ($marker == 0xe0) { # APP0 (JFIF, CIFF)
|
5461
5546
|
if ($$segDataPt =~ /^JFIF\0/) {
|
5462
5547
|
$segType = 'JFIF';
|
@@ -5535,7 +5620,6 @@ sub WriteJPEG($$)
|
|
5535
5620
|
$$segDataPt = $exifAPP1hdr . $buff;
|
5536
5621
|
} else {
|
5537
5622
|
last Marker unless $self->Options('IgnoreMinorErrors');
|
5538
|
-
$$self{CHANGED} = $oldChanged; # nothing changed
|
5539
5623
|
}
|
5540
5624
|
# switch to buffered output if required
|
5541
5625
|
if (($$self{PREVIEW_INFO} or $$self{LeicaTrailer}) and not $oldOutfile) {
|
@@ -5653,7 +5737,6 @@ sub WriteJPEG($$)
|
|
5653
5737
|
$$segDataPt = ''; # delete the XMP
|
5654
5738
|
}
|
5655
5739
|
} else {
|
5656
|
-
$$self{CHANGED} = $oldChanged;
|
5657
5740
|
$verbose and print $out " [XMP rewritten with no changes]\n";
|
5658
5741
|
if ($doneDir{XMP} > 1) {
|
5659
5742
|
# re-write original multi-segment XMP
|
@@ -5777,7 +5860,6 @@ sub WriteJPEG($$)
|
|
5777
5860
|
$$segDataPt = substr($$segDataPt,0,6) . $buff;
|
5778
5861
|
} else {
|
5779
5862
|
last Marker unless $self->Options('IgnoreMinorErrors');
|
5780
|
-
$$self{CHANGED} = $oldChanged; # nothing changed
|
5781
5863
|
}
|
5782
5864
|
# delete segment if IFD contains no entries
|
5783
5865
|
$del = 1 unless length($$segDataPt) > 6;
|
@@ -5809,8 +5891,6 @@ sub WriteJPEG($$)
|
|
5809
5891
|
# add header to new segment unless empty
|
5810
5892
|
$newData = 'Ducky' . $newData if length $newData;
|
5811
5893
|
$segDataPt = \$newData;
|
5812
|
-
} else {
|
5813
|
-
$$self{CHANGED} = $oldChanged;
|
5814
5894
|
}
|
5815
5895
|
$del = 1 unless length $$segDataPt;
|
5816
5896
|
}
|
@@ -5850,8 +5930,6 @@ sub WriteJPEG($$)
|
|
5850
5930
|
if (defined $newData) {
|
5851
5931
|
undef $$segDataPt; # free the old buffer
|
5852
5932
|
$segDataPt = \$newData;
|
5853
|
-
} else {
|
5854
|
-
$$self{CHANGED} = $oldChanged;
|
5855
5933
|
}
|
5856
5934
|
length $$segDataPt or $del = 1, last;
|
5857
5935
|
# write as multi-segment
|
@@ -48,7 +48,7 @@ use Image::ExifTool::Exif;
|
|
48
48
|
use Image::ExifTool::GPS;
|
49
49
|
require Exporter;
|
50
50
|
|
51
|
-
$VERSION = '3.
|
51
|
+
$VERSION = '3.07';
|
52
52
|
@ISA = qw(Exporter);
|
53
53
|
@EXPORT_OK = qw(EscapeXML UnescapeXML);
|
54
54
|
|
@@ -172,6 +172,7 @@ my %xmpNS = (
|
|
172
172
|
GImage => 'http://ns.google.com/photos/1.0/image/',
|
173
173
|
GPano => 'http://ns.google.com/photos/1.0/panorama/',
|
174
174
|
GSpherical=> 'http://ns.google.com/videos/1.0/spherical/',
|
175
|
+
GDepth => 'http://ns.google.com/photos/1.0/depthmap/',
|
175
176
|
dwc => 'http://rs.tdwg.org/dwc/index.htm',
|
176
177
|
GettyImagesGIFT => 'http://xmp.gettyimages.com/gift/1.0/',
|
177
178
|
);
|
@@ -732,6 +733,10 @@ my %sRetouchArea = (
|
|
732
733
|
Name => 'GSpherical',
|
733
734
|
SubDirectory => { TagTable => 'Image::ExifTool::XMP::GSpherical' },
|
734
735
|
},
|
736
|
+
GDepth => {
|
737
|
+
Name => 'GDepth',
|
738
|
+
SubDirectory => { TagTable => 'Image::ExifTool::XMP::GDepth' },
|
739
|
+
},
|
735
740
|
dwc => {
|
736
741
|
Name => 'dwc',
|
737
742
|
SubDirectory => { TagTable => 'Image::ExifTool::DarwinCore::Main' },
|
@@ -2042,9 +2047,8 @@ my %sPantryItem = (
|
|
2042
2047
|
PrintConv => \&Image::ExifTool::Exif::PrintLensInfo,
|
2043
2048
|
PrintConvInv => \&Image::ExifTool::Exif::ConvertLensInfo,
|
2044
2049
|
Notes => q{
|
2045
|
-
|
2046
|
-
|
2047
|
-
XMP-aux:LensInfo
|
2050
|
+
unfortunately the EXIF 2.3 for XMP specification defined this new tag
|
2051
|
+
instead of using the existing XMP-aux:LensInfo
|
2048
2052
|
},
|
2049
2053
|
},
|
2050
2054
|
LensMake => { },
|
@@ -2398,12 +2402,13 @@ sub IsUTF8($)
|
|
2398
2402
|
}
|
2399
2403
|
|
2400
2404
|
#------------------------------------------------------------------------------
|
2401
|
-
# Fix malformed UTF8 (by replacing bad bytes with
|
2402
|
-
# Inputs: 0) string reference
|
2405
|
+
# Fix malformed UTF8 (by replacing bad bytes with specified character)
|
2406
|
+
# Inputs: 0) string reference, 1) string to replace each bad byte,
|
2407
|
+
# may be '' to delete bad bytes, or undef to use '?'
|
2403
2408
|
# Returns: true if string was fixed, and updates string
|
2404
|
-
sub FixUTF8(
|
2409
|
+
sub FixUTF8($;$)
|
2405
2410
|
{
|
2406
|
-
my $strPt =
|
2411
|
+
my ($strPt, $bad) = @_;
|
2407
2412
|
my $fixed;
|
2408
2413
|
pos($$strPt) = 0; # start at beginning of string
|
2409
2414
|
for (;;) {
|
@@ -2415,9 +2420,11 @@ sub FixUTF8($)
|
|
2415
2420
|
my $n = $ch < 0xe0 ? 1 : ($ch < 0xf0 ? 2 : 3);
|
2416
2421
|
next if $$strPt =~ /\G[\x80-\xbf]{$n}/g;
|
2417
2422
|
}
|
2418
|
-
# replace bad character
|
2419
|
-
|
2420
|
-
|
2423
|
+
# replace bad character
|
2424
|
+
$bad = '?' unless defined $bad;
|
2425
|
+
substr($$strPt, $pos-1, 1) = $bad;
|
2426
|
+
pos($$strPt) = $pos-1 + length $bad;
|
2427
|
+
$fixed = 1;
|
2421
2428
|
}
|
2422
2429
|
return $fixed;
|
2423
2430
|
}
|
@@ -3610,6 +3617,8 @@ sub ProcessXMP($$;$)
|
|
3610
3617
|
$isSVG = 1;
|
3611
3618
|
} elsif ($1 eq 'plist') {
|
3612
3619
|
$type = 'PLIST';
|
3620
|
+
} elsif ($1 eq 'REDXIF') {
|
3621
|
+
$type = 'RMD';
|
3613
3622
|
} else {
|
3614
3623
|
return 0;
|
3615
3624
|
}
|