exiftool-vendored.exe 13.0.0 → 13.17.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.
- package/bin/exiftool.exe +0 -0
- package/bin/exiftool_files/exiftool.pl +169 -65
- package/bin/exiftool_files/lib/File/RandomAccess.pm +1 -1
- package/bin/exiftool_files/lib/File/RandomAccess.pod +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/AAC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/AES.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/AFCP.pm +6 -6
- package/bin/exiftool_files/lib/Image/ExifTool/AIFF.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/APE.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/APP12.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ASF.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Apple.pm +11 -9
- package/bin/exiftool_files/lib/Image/ExifTool/Audible.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BMP.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BPG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BZZ.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BigTIFF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BuildTagLookup.pm +46 -26
- package/bin/exiftool_files/lib/Image/ExifTool/CBOR.pm +5 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +68 -28
- package/bin/exiftool_files/lib/Image/ExifTool/CanonCustom.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/CanonRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/CanonVRD.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/CaptureOne.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Casio.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Charset.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DICOM.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DJI.pm +196 -30
- package/bin/exiftool_files/lib/Image/ExifTool/DNG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DPX.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DV.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DarwinCore.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DjVu.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/EXE.pm +138 -33
- package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +29 -16
- package/bin/exiftool_files/lib/Image/ExifTool/FITS.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/FLAC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/FLIF.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/FLIR.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Fixup.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Flash.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/FlashPix.pm +17 -21
- package/bin/exiftool_files/lib/Image/ExifTool/Font.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/FotoStation.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/GE.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/GIF.pm +144 -93
- package/bin/exiftool_files/lib/Image/ExifTool/GIMP.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/GM.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/GPS.pm +34 -30
- package/bin/exiftool_files/lib/Image/ExifTool/GeoTiff.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Geolocation.dat +0 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Geolocation.pm +19 -9
- package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +46 -12
- package/bin/exiftool_files/lib/Image/ExifTool/GoPro.pm +120 -8
- package/bin/exiftool_files/lib/Image/ExifTool/H264.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/HP.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/HTML.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/HtmlDump.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ICC_Profile.pm +81 -2
- package/bin/exiftool_files/lib/Image/ExifTool/ICO.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ID3.pm +8 -8
- package/bin/exiftool_files/lib/Image/ExifTool/IPTC.pm +10 -7
- package/bin/exiftool_files/lib/Image/ExifTool/ISO.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ITC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Import.pm +5 -4
- package/bin/exiftool_files/lib/Image/ExifTool/InDesign.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/InfiRay.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/JPEG.pm +38 -5
- package/bin/exiftool_files/lib/Image/ExifTool/JPEGDigest.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/JSON.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/JVC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +10 -9
- package/bin/exiftool_files/lib/Image/ExifTool/Kodak.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/LIF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/LNK.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/cs.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/de.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/en_ca.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/en_gb.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/es.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/fi.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/fr.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/it.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/ja.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/ko.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/nl.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/pl.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/ru.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/sk.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/sv.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/tr.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Leaf.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/LigoGPS.pm +409 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Lytro.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/M2TS.pm +57 -18
- package/bin/exiftool_files/lib/Image/ExifTool/MIE.pm +15 -6
- package/bin/exiftool_files/lib/Image/ExifTool/MIEUnits.pod +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MIFF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MISB.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MNG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MOI.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MPC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MPEG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MPF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MRC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MWG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MXF.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/MacOS.pm +3 -2
- package/bin/exiftool_files/lib/Image/ExifTool/MakerNotes.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Matroska.pm +22 -6
- package/bin/exiftool_files/lib/Image/ExifTool/Microsoft.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Minolta.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Motorola.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +457 -103
- package/bin/exiftool_files/lib/Image/ExifTool/NikonCapture.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/NikonCustom.pm +6 -6
- package/bin/exiftool_files/lib/Image/ExifTool/NikonSettings.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Nintendo.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/OOXML.pm +8 -8
- package/bin/exiftool_files/lib/Image/ExifTool/Ogg.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/OpenEXR.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Opus.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Other.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PCX.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PDF.pm +49 -18
- package/bin/exiftool_files/lib/Image/ExifTool/PGF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PICT.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PLIST.pm +4 -4
- package/bin/exiftool_files/lib/Image/ExifTool/PLUS.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +20 -8
- package/bin/exiftool_files/lib/Image/ExifTool/PPM.pm +12 -3
- package/bin/exiftool_files/lib/Image/ExifTool/PSP.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Palm.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +27 -3
- package/bin/exiftool_files/lib/Image/ExifTool/PanasonicRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Parrot.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PhaseOne.pm +4 -4
- package/bin/exiftool_files/lib/Image/ExifTool/PhotoCD.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Photoshop.pm +65 -4
- package/bin/exiftool_files/lib/Image/ExifTool/PostScript.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PrintIM.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Protobuf.pm +270 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Qualcomm.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +327 -88
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +199 -195
- package/bin/exiftool_files/lib/Image/ExifTool/README +12 -2
- package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +21 -6
- package/bin/exiftool_files/lib/Image/ExifTool/RSRC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/RTF.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Radiance.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Rawzor.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Real.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Reconyx.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Red.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Ricoh.pm +4 -4
- package/bin/exiftool_files/lib/Image/ExifTool/Samsung.pm +6 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Sanyo.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Scalado.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Shift.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Shortcuts.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Sigma.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/SigmaRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +6 -5
- package/bin/exiftool_files/lib/Image/ExifTool/SonyIDC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Stim.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/TagInfoXML.pm +6 -5
- package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +7028 -6968
- package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +12079 -11630
- package/bin/exiftool_files/lib/Image/ExifTool/Text.pm +4 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Theora.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Torrent.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Trailer.pm +318 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Unknown.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/VCard.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +6 -6
- package/bin/exiftool_files/lib/Image/ExifTool/Vorbis.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WPG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WTV.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WriteExif.pl +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/WriteIPTC.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WritePDF.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WritePNG.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WritePostScript.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +170 -79
- package/bin/exiftool_files/lib/Image/ExifTool/WriteRIFF.pl +17 -6
- package/bin/exiftool_files/lib/Image/ExifTool/WriteXMP.pl +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +89 -96
- package/bin/exiftool_files/lib/Image/ExifTool/XISF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +28 -13
- package/bin/exiftool_files/lib/Image/ExifTool/XMP2.pl +106 -3
- package/bin/exiftool_files/lib/Image/ExifTool/XMPStruct.pl +2 -3
- package/bin/exiftool_files/lib/Image/ExifTool/ZIP.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/ZISRAW.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/iWork.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool.pm +467 -228
- package/bin/exiftool_files/lib/Image/ExifTool.pod +118 -72
- package/bin/exiftool_files/windows_exiftool.txt +96 -51
- package/package.json +8 -8
|
@@ -15,6 +15,8 @@ my %movMap = (
|
|
|
15
15
|
QuickTime => 'ItemList', # (default location for QuickTime tags)
|
|
16
16
|
ItemList => 'Meta', # MOV-Movie-UserData-Meta-ItemList
|
|
17
17
|
Keys => 'Movie', # MOV-Movie-Meta-Keys !! (hack due to different Meta location)
|
|
18
|
+
AudioKeys => 'Track', # MOV-Movie-Track-Meta-Keys !!
|
|
19
|
+
VideoKeys => 'Track', # MOV-Movie-Track-Meta-Keys !!
|
|
18
20
|
Meta => 'UserData',
|
|
19
21
|
XMP => 'UserData', # MOV-Movie-UserData-XMP
|
|
20
22
|
Microsoft => 'UserData', # MOV-Movie-UserData-Microsoft
|
|
@@ -29,6 +31,8 @@ my %mp4Map = (
|
|
|
29
31
|
QuickTime => 'ItemList', # (default location for QuickTime tags)
|
|
30
32
|
ItemList => 'Meta', # MOV-Movie-UserData-Meta-ItemList
|
|
31
33
|
Keys => 'Movie', # MOV-Movie-Meta-Keys !! (hack due to different Meta location)
|
|
34
|
+
AudioKeys => 'Track', # MOV-Movie-Track-Meta-Keys !!
|
|
35
|
+
VideoKeys => 'Track', # MOV-Movie-Track-Meta-Keys !!
|
|
32
36
|
Meta => 'UserData',
|
|
33
37
|
UserData => 'Movie', # MOV-Movie-UserData
|
|
34
38
|
Microsoft => 'UserData', # MOV-Movie-UserData-Microsoft
|
|
@@ -339,7 +343,7 @@ sub FormatQTValue($$;$$)
|
|
|
339
343
|
$flags = 0x01; # UTF8
|
|
340
344
|
$$valPt = $et->Encode($$valPt, 'UTF8');
|
|
341
345
|
}
|
|
342
|
-
defined $$valPt or $et->
|
|
346
|
+
defined $$valPt or $et->Warn("Error converting value for $$tagInfo{Name}");
|
|
343
347
|
return $flags;
|
|
344
348
|
}
|
|
345
349
|
|
|
@@ -374,6 +378,9 @@ sub WriteNextbase($$$)
|
|
|
374
378
|
# Write Meta Keys to add/delete entries as necessary ('mdta' handler) (ref PH)
|
|
375
379
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
|
376
380
|
# Returns: updated keys box data
|
|
381
|
+
# Note: Residual entries may be left in the 'keys' directory when deleting tags
|
|
382
|
+
# with language codes because the language code(s) are not known until the
|
|
383
|
+
# corresponding ItemList entry(s) are processed
|
|
377
384
|
sub WriteKeys($$$)
|
|
378
385
|
{
|
|
379
386
|
my ($et, $dirInfo, $tagTablePtr) = @_;
|
|
@@ -383,13 +390,14 @@ sub WriteKeys($$$)
|
|
|
383
390
|
my $outfile = $$dirInfo{OutFile};
|
|
384
391
|
my ($tag, %done, %remap, %info, %add, $i);
|
|
385
392
|
|
|
393
|
+
my $keysGrp = $avType{$$et{MediaType}} ? "$avType{$$et{MediaType}}Keys" : 'Keys';
|
|
386
394
|
$dirLen < 8 and $et->Warn('Short Keys box'), $dirLen = 8, $$dataPt = "\0" x 8;
|
|
387
|
-
if ($$et{DEL_GROUP}{
|
|
395
|
+
if ($$et{DEL_GROUP}{$keysGrp}) {
|
|
388
396
|
$dirLen = 8; # delete all existing keys
|
|
389
397
|
# deleted keys are identified by a zero entry in the Remap lookup
|
|
390
398
|
my $n = Get32u($dataPt, 4);
|
|
391
399
|
for ($i=1; $i<=$n; ++$i) { $remap{$i} = 0; }
|
|
392
|
-
$et->VPrint(0, " [deleting $n
|
|
400
|
+
$et->VPrint(0, " [deleting $n $keysGrp entr".($n==1 ? 'y' : 'ies')."]\n");
|
|
393
401
|
++$$et{CHANGED};
|
|
394
402
|
}
|
|
395
403
|
my $pos = 8;
|
|
@@ -425,7 +433,7 @@ sub WriteKeys($$$)
|
|
|
425
433
|
}
|
|
426
434
|
unless ($dontDelete) {
|
|
427
435
|
# delete this key
|
|
428
|
-
$et->VPrint(1, "$$et{INDENT}\[deleting
|
|
436
|
+
$et->VPrint(1, "$$et{INDENT}\[deleting $keysGrp entry $index '${tag}']\n");
|
|
429
437
|
$pos += $len;
|
|
430
438
|
$remap{$index++} = 0;
|
|
431
439
|
++$$et{CHANGED};
|
|
@@ -455,7 +463,7 @@ sub WriteKeys($$$)
|
|
|
455
463
|
# add new entry to 'keys' data
|
|
456
464
|
my $val = $id =~ /^com\./ ? $id : "com.apple.quicktime.$id";
|
|
457
465
|
$newData .= Set32u(8 + length($val)) . 'mdta' . $val;
|
|
458
|
-
$et->VPrint(1, "$$et{INDENT}\[adding
|
|
466
|
+
$et->VPrint(1, "$$et{INDENT}\[adding $keysGrp entry $newIndex '${id}']\n");
|
|
459
467
|
$add{$newIndex++} = $tagInfo;
|
|
460
468
|
++$$et{CHANGED};
|
|
461
469
|
}
|
|
@@ -470,7 +478,7 @@ sub WriteKeys($$$)
|
|
|
470
478
|
# Info - Keys tag information, based on old index value
|
|
471
479
|
# Add - Keys items deleted, based on old index value
|
|
472
480
|
# Num - Number of items in edited Keys box
|
|
473
|
-
$$et{
|
|
481
|
+
$$et{$keysGrp} = { Remap => \%remap, Info => \%info, Add => \%add, Num => $num };
|
|
474
482
|
|
|
475
483
|
return $newData; # return updated Keys box
|
|
476
484
|
}
|
|
@@ -482,23 +490,26 @@ sub WriteKeys($$$)
|
|
|
482
490
|
sub WriteItemInfo($$$)
|
|
483
491
|
{
|
|
484
492
|
my ($et, $dirInfo, $outfile) = @_;
|
|
485
|
-
my $boxPos = $$dirInfo{BoxPos};
|
|
493
|
+
my $boxPos = $$dirInfo{BoxPos}; # hash of [position,length,irefVer(iref only)] for box in $outfile
|
|
486
494
|
my $raf = $$et{RAF};
|
|
487
495
|
my $items = $$et{ItemInfo};
|
|
488
|
-
my (%did, @mdatEdit, $name);
|
|
496
|
+
my (%did, @mdatEdit, $name, $tmap);
|
|
489
497
|
|
|
490
498
|
return () unless $items and $raf;
|
|
491
499
|
|
|
492
500
|
# extract information from EXIF/XMP metadata items
|
|
493
501
|
my $primary = $$et{PrimaryItem};
|
|
494
502
|
my $curPos = $raf->Tell();
|
|
503
|
+
my $lastID = 0;
|
|
495
504
|
my $id;
|
|
496
505
|
foreach $id (sort { $a <=> $b } keys %$items) {
|
|
506
|
+
$lastID = $id;
|
|
497
507
|
$primary = $id unless defined $primary; # assume primary is lowest-number item if pitm missing
|
|
498
508
|
my $item = $$items{$id};
|
|
499
509
|
# only edit primary EXIF/XMP metadata
|
|
500
510
|
next unless $$item{RefersTo} and $$item{RefersTo}{$primary};
|
|
501
511
|
my $type = $$item{ContentType} || $$item{Type} || next;
|
|
512
|
+
$tmap = $id if $type eq 'tmap'; # save ID of primary 'tmap' item (tone-mapped image)
|
|
502
513
|
# get ExifTool name for this item
|
|
503
514
|
$name = { Exif => 'EXIF', 'application/rdf+xml' => 'XMP' }->{$type};
|
|
504
515
|
next unless $name; # only care about EXIF and XMP
|
|
@@ -548,11 +559,12 @@ sub WriteItemInfo($$$)
|
|
|
548
559
|
$buff = $v2;
|
|
549
560
|
$wasDeflated = 1;
|
|
550
561
|
} else {
|
|
551
|
-
$et->
|
|
562
|
+
$et->Warn("Error inflating $name metadata");
|
|
552
563
|
next;
|
|
553
564
|
}
|
|
554
565
|
}
|
|
555
566
|
my ($hdr, $subTable, $proc);
|
|
567
|
+
my $strt = 0;
|
|
556
568
|
if ($name eq 'EXIF') {
|
|
557
569
|
if (not length $buff) {
|
|
558
570
|
# create EXIF from scratch
|
|
@@ -562,6 +574,7 @@ sub WriteItemInfo($$$)
|
|
|
562
574
|
$hdr = '';
|
|
563
575
|
} elsif (length($buff) >= 4 and length($buff) >= 4 + unpack('N',$buff)) {
|
|
564
576
|
$hdr = substr($buff, 0, 4 + unpack('N',$buff));
|
|
577
|
+
$strt = length $hdr;
|
|
565
578
|
} else {
|
|
566
579
|
$et->Warn('Invalid Exif header');
|
|
567
580
|
next;
|
|
@@ -575,8 +588,8 @@ sub WriteItemInfo($$$)
|
|
|
575
588
|
my %dirInfo = (
|
|
576
589
|
DataPt => \$buff,
|
|
577
590
|
DataLen => length $buff,
|
|
578
|
-
DirStart =>
|
|
579
|
-
DirLen => length($buff) -
|
|
591
|
+
DirStart => $strt,
|
|
592
|
+
DirLen => length($buff) - $strt,
|
|
580
593
|
);
|
|
581
594
|
my $changed = $$et{CHANGED};
|
|
582
595
|
my $newVal = $et->WriteDirectory(\%dirInfo, $subTable, $proc);
|
|
@@ -683,7 +696,7 @@ sub WriteItemInfo($$$)
|
|
|
683
696
|
# write compressed XMP if Compress option is set
|
|
684
697
|
if ($et->Options('Compress') and length $newVal) {
|
|
685
698
|
if (not eval { require Compress::Zlib }) {
|
|
686
|
-
$et->
|
|
699
|
+
$et->Warn('Install Compress::Zlib to write compressed metadata');
|
|
687
700
|
} else {
|
|
688
701
|
my $deflate = Compress::Zlib::deflateInit();
|
|
689
702
|
if ($deflate) {
|
|
@@ -700,8 +713,10 @@ sub WriteItemInfo($$$)
|
|
|
700
713
|
$type = "Exif\0";
|
|
701
714
|
$mime = '';
|
|
702
715
|
}
|
|
703
|
-
my $id =
|
|
704
|
-
|
|
716
|
+
my $id = ++$lastID; # use next highest available ID (so ID's in iinf are in order)
|
|
717
|
+
#[retracted] # create new item information hash to save infe box in case we need it for sorting
|
|
718
|
+
#[retracted] my $item = $$items{$id} = { };
|
|
719
|
+
# add new infe entry to iinf box
|
|
705
720
|
my $n = length($type) + length($mime) + length($enc) + 16;
|
|
706
721
|
if ($id < 0x10000) {
|
|
707
722
|
$add{iinf} .= pack('Na4CCCCnn', $n, 'infe', 2, 0, 0, 1, $id, 0) . $type . $mime . $enc;
|
|
@@ -709,11 +724,14 @@ sub WriteItemInfo($$$)
|
|
|
709
724
|
$n += 2;
|
|
710
725
|
$add{iinf} .= pack('Na4CCCCNn', $n, 'infe', 3, 0, 0, 1, $id, 0) . $type . $mime . $enc;
|
|
711
726
|
}
|
|
712
|
-
# add
|
|
727
|
+
#[retracted] $add{iinf} .= $$item{infe};
|
|
728
|
+
# add new cdsc to iref (also refer to primary 'tmap' if it exists)
|
|
713
729
|
if ($irefVer) {
|
|
714
|
-
$
|
|
730
|
+
my ($fmt, $siz, $num) = defined $tmap ? ('N', 22, 2) : ('', 18, 1);
|
|
731
|
+
$add{iref} .= pack('Na4NnN'.$fmt, $siz, 'cdsc', $id, $num, $primary, $tmap);
|
|
715
732
|
} else {
|
|
716
|
-
$
|
|
733
|
+
my ($fmt, $siz, $num) = defined $tmap ? ('n', 16, 2) : ('', 14, 1);
|
|
734
|
+
$add{iref} .= pack('Na4nnn'.$fmt, $siz, 'cdsc', $id, $num, $primary, $tmap);
|
|
717
735
|
}
|
|
718
736
|
# add new entry to iloc table (see ISO14496-12:2015 pg.79)
|
|
719
737
|
my $ilocVer = Get8u($outfile, $$boxPos{iloc}[0] + 8);
|
|
@@ -778,8 +796,9 @@ sub WriteItemInfo($$$)
|
|
|
778
796
|
my $added = 0;
|
|
779
797
|
my $tag;
|
|
780
798
|
foreach $tag (sort { $$boxPos{$a}[0] <=> $$boxPos{$b}[0] } keys %$boxPos) {
|
|
799
|
+
$$boxPos{$tag}[0] += $added;
|
|
781
800
|
next unless $add{$tag};
|
|
782
|
-
my $pos = $$boxPos{$tag}[0]
|
|
801
|
+
my $pos = $$boxPos{$tag}[0];
|
|
783
802
|
unless ($$boxPos{$tag}[1]) {
|
|
784
803
|
$tag eq 'iref' or $et->Error('Internal error adding iref box'), last;
|
|
785
804
|
# create new iref box
|
|
@@ -826,9 +845,34 @@ sub WriteItemInfo($$$)
|
|
|
826
845
|
}
|
|
827
846
|
# add new entries to this box (or add pitm after hdlr)
|
|
828
847
|
substr($$outfile, $pos + $$boxPos{$tag}[1], 0) = $add{$tag};
|
|
848
|
+
$$boxPos{$tag}[1] += length $add{$tag};
|
|
829
849
|
$added += length $add{$tag}; # positions are shifted by length of new entries
|
|
830
850
|
}
|
|
831
851
|
}
|
|
852
|
+
#[This sorting idea was retracted because just sorting 'iinf' wasn't sufficient to
|
|
853
|
+
# repair the problem where an out-of-order ID was added -- Apple Preview still
|
|
854
|
+
# ignores the gain-map image. It looks like either or both 'iref' and 'iloc' must
|
|
855
|
+
# also be sorted by ID, although the spec doesn't mention this]
|
|
856
|
+
#[retracted] # sort infe entries in iinf box if necessary
|
|
857
|
+
#[retracted] if ($$et{ItemsNotSorted}) {
|
|
858
|
+
#[retracted] if ($$boxPos{iinf}) {
|
|
859
|
+
#[retracted] my $iinfVer = Get8u($outfile, $$boxPos{iinf}[0] + 8);
|
|
860
|
+
#[retracted] my $off = $iinfVer == 0 ? 14 : 16; # offset to first infe item
|
|
861
|
+
#[retracted] my $sorted = ''; # sorted iinf payload
|
|
862
|
+
#[retracted] $sorted .= $$items{$_}{infe} || '' foreach sort { $a <=> $b } keys %$items;
|
|
863
|
+
#[retracted] if (length $sorted == $$boxPos{iinf}[1]-$off) {
|
|
864
|
+
#[retracted] # replace with sorted infe entries
|
|
865
|
+
#[retracted] substr($$outfile, $$boxPos{iinf}[0] + $off, length $sorted) = $sorted;
|
|
866
|
+
#[retracted] $et->Warn('Item info entries are out of order. Fixed.');
|
|
867
|
+
#[retracted] ++$$et{CHANGED};
|
|
868
|
+
#[retracted] } else {
|
|
869
|
+
#[retracted] $et->Warn('Error sorting item info entries');
|
|
870
|
+
#[retracted] }
|
|
871
|
+
#[retracted] } else {
|
|
872
|
+
#[retracted] $et->Warn('Item info entries are out of order');
|
|
873
|
+
#[retracted] }
|
|
874
|
+
#[retracted] delete $$et{ItemsNotSorted};
|
|
875
|
+
#[retracted] }
|
|
832
876
|
delete $$et{ItemInfo};
|
|
833
877
|
return @mdatEdit ? \@mdatEdit : undef;
|
|
834
878
|
}
|
|
@@ -847,7 +891,7 @@ sub WriteQuickTime($$$)
|
|
|
847
891
|
$et or return 1; # allow dummy access to autoload this package
|
|
848
892
|
my ($mdat, @mdat, @mdatEdit, $edit, $track, $outBuff, $co, $term, $delCount);
|
|
849
893
|
my (%langTags, $canCreate, $delGrp, %boxPos, %didDir, $writeLast, $err, $atomCount);
|
|
850
|
-
my ($tag, $lastTag, $lastPos, $errStr, $trailer, $buf2);
|
|
894
|
+
my ($tag, $lastTag, $lastPos, $errStr, $trailer, $buf2, $keysGrp, $keysPath);
|
|
851
895
|
my $outfile = $$dirInfo{OutFile} || return 0;
|
|
852
896
|
my $raf = $$dirInfo{RAF}; # (will be null for lower-level atoms)
|
|
853
897
|
my $dataPt = $$dirInfo{DataPt}; # (will be null for top-level atoms)
|
|
@@ -860,15 +904,10 @@ sub WriteQuickTime($$$)
|
|
|
860
904
|
my $createKeys = 0;
|
|
861
905
|
my ($rtnVal, $rtnErr) = $dataPt ? (undef, undef) : (1, 0);
|
|
862
906
|
|
|
863
|
-
# check for
|
|
907
|
+
# check for trailer at end of file
|
|
864
908
|
if ($raf) {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
substr($buf2, 8) eq '8db42d694ccc418790edff439fe026bf')
|
|
868
|
-
{
|
|
869
|
-
$trailer = [ 'Insta360', $raf->Tell() - unpack('V',$buf2) ];
|
|
870
|
-
}
|
|
871
|
-
$raf->Seek($pos, 0) or return 0;
|
|
909
|
+
$trailer = IdentifyTrailers($raf);
|
|
910
|
+
$trailer and not ref $trailer and $et->Error($trailer), return 1;
|
|
872
911
|
}
|
|
873
912
|
if ($dataPt) {
|
|
874
913
|
$raf = File::RandomAccess->new($dataPt);
|
|
@@ -881,15 +920,26 @@ sub WriteQuickTime($$$)
|
|
|
881
920
|
|
|
882
921
|
$raf->Seek($dirStart, 1) if $dirStart; # skip header if it exists
|
|
883
922
|
|
|
923
|
+
if ($avType{$$et{MediaType}}) {
|
|
924
|
+
# (note: these won't be correct now if we haven't yet processed the Media box,
|
|
925
|
+
# but in this case they won't be needed until after we set them properly below)
|
|
926
|
+
($keysGrp, $keysPath) = ("$avType{$$et{MediaType}}Keys", 'MOV-Movie-Track');
|
|
927
|
+
} else {
|
|
928
|
+
($keysGrp, $keysPath) = ('Keys', 'MOV-Movie');
|
|
929
|
+
}
|
|
884
930
|
my $curPath = join '-', @{$$et{PATH}};
|
|
885
931
|
my ($dir, $writePath) = ($dirName, $dirName);
|
|
886
932
|
$writePath = "$dir-$writePath" while defined($dir = $$et{DirMap}{$dir});
|
|
887
933
|
# hack to create Keys directories if necessary (its containing Meta is in a different location)
|
|
888
|
-
if ($$addDirs{Keys} and $curPath =~ /^MOV-Movie(-Meta)?$/) {
|
|
934
|
+
if (($$addDirs{Keys} and $curPath =~ /^MOV-Movie(-Meta)?$/)) {
|
|
889
935
|
$createKeys = 1; # create new Keys directories
|
|
890
|
-
} elsif ($curPath
|
|
936
|
+
} elsif (($$addDirs{AudioKeys} or $$addDirs{VideoKeys}) and $curPath =~ /^MOV-Movie-Track(-Meta)?$/) {
|
|
937
|
+
$createKeys = -1; # (must wait until MediaType is known)
|
|
938
|
+
} elsif (($curPath eq 'MOV-Movie-Meta-ItemList') or
|
|
939
|
+
($curPath eq 'MOV-Movie-Track-Meta-ItemList' and $avType{$$et{MediaType}}))
|
|
940
|
+
{
|
|
891
941
|
$createKeys = 2; # create new Keys tags
|
|
892
|
-
my $keys = $$et{
|
|
942
|
+
my $keys = $$et{$keysGrp};
|
|
893
943
|
if ($keys) {
|
|
894
944
|
# add new tag entries for existing Keys tags, now that we know their ID's
|
|
895
945
|
# - first make lookup to convert Keys tagInfo ref to index number
|
|
@@ -897,7 +947,7 @@ sub WriteQuickTime($$$)
|
|
|
897
947
|
foreach $index (keys %{$$keys{Info}}) {
|
|
898
948
|
$keysInfo{$$keys{Info}{$index}} = $index if $$keys{Remap}{$index};
|
|
899
949
|
}
|
|
900
|
-
my $keysTable = GetTagTable(
|
|
950
|
+
my $keysTable = GetTagTable("Image::ExifTool::QuickTime::$keysGrp");
|
|
901
951
|
my $newKeysTags = $et->GetNewTagInfoHash($keysTable);
|
|
902
952
|
foreach (keys %$newKeysTags) {
|
|
903
953
|
my $tagInfo = $$newKeysTags{$_};
|
|
@@ -926,7 +976,8 @@ sub WriteQuickTime($$$)
|
|
|
926
976
|
}
|
|
927
977
|
if ($curPath eq $writePath or $createKeys) {
|
|
928
978
|
$canCreate = 1;
|
|
929
|
-
|
|
979
|
+
# (must check the appropriate Keys delete flag if this is a Keys ItemList)
|
|
980
|
+
$delGrp = $$et{DEL_GROUP}{$createKeys ? $keysGrp : $dirName};
|
|
930
981
|
}
|
|
931
982
|
$atomCount = $$tagTablePtr{VARS}{ATOM_COUNT} if $$tagTablePtr{VARS};
|
|
932
983
|
|
|
@@ -973,7 +1024,7 @@ sub WriteQuickTime($$$)
|
|
|
973
1024
|
$et->Error('End of processing at large atom (LargeFileSupport not enabled)');
|
|
974
1025
|
last;
|
|
975
1026
|
} elsif ($et->Options('LargeFileSupport') eq '2') {
|
|
976
|
-
$et->
|
|
1027
|
+
$et->Warn('Processing large atom (LargeFileSupport is 2)');
|
|
977
1028
|
}
|
|
978
1029
|
}
|
|
979
1030
|
$size = $hi * 4294967296 + $lo - 16;
|
|
@@ -1010,6 +1061,10 @@ sub WriteQuickTime($$$)
|
|
|
1010
1061
|
$et->Error("Can't yet write compressed movie metadata");
|
|
1011
1062
|
return $rtnVal;
|
|
1012
1063
|
} elsif ($tag eq 'wide') {
|
|
1064
|
+
if ($size) {
|
|
1065
|
+
$et->Warn("Incorrect size for 'wide' atom ($size bytes)");
|
|
1066
|
+
$raf->Seek($size, 1) or $et->Error('Truncated wide atom');
|
|
1067
|
+
}
|
|
1013
1068
|
next; # drop 'wide' tag
|
|
1014
1069
|
}
|
|
1015
1070
|
|
|
@@ -1044,12 +1099,12 @@ sub WriteQuickTime($$$)
|
|
|
1044
1099
|
last;
|
|
1045
1100
|
}
|
|
1046
1101
|
}
|
|
1047
|
-
# save the handler type
|
|
1048
|
-
if ($tag eq 'hdlr' and length $buff >= 12
|
|
1049
|
-
|
|
1050
|
-
|
|
1102
|
+
# save the handler type of the track media
|
|
1103
|
+
if ($tag eq 'hdlr' and length $buff >= 12 and
|
|
1104
|
+
@{$$et{PATH}} and $$et{PATH}[-1] eq 'Media')
|
|
1105
|
+
{
|
|
1106
|
+
$$et{MediaType} = substr($buff,8,4);
|
|
1051
1107
|
}
|
|
1052
|
-
|
|
1053
1108
|
# if this atom stores offsets, save its location so we can fix up offsets later
|
|
1054
1109
|
# (are there any other atoms that may store absolute file offsets?)
|
|
1055
1110
|
if ($tag =~ /^(stco|co64|iloc|mfra|moof|sidx|saio|gps |CTBO|uuid)$/) {
|
|
@@ -1094,11 +1149,11 @@ sub WriteQuickTime($$$)
|
|
|
1094
1149
|
&{$$tagInfo{WriteHook}}($buff,$et) if $tagInfo and $$tagInfo{WriteHook};
|
|
1095
1150
|
|
|
1096
1151
|
# allow numerical tag ID's (ItemList entries defined by Keys)
|
|
1097
|
-
if (not $tagInfo and $dirName eq 'ItemList' and $$et{
|
|
1152
|
+
if (not $tagInfo and $dirName eq 'ItemList' and $$et{$keysGrp}) {
|
|
1098
1153
|
$keysIndex = unpack('N', $tag);
|
|
1099
|
-
my $newIndex = $$et{
|
|
1154
|
+
my $newIndex = $$et{$keysGrp}{Remap}{$keysIndex};
|
|
1100
1155
|
if (defined $newIndex) {
|
|
1101
|
-
$tagInfo = $$et{
|
|
1156
|
+
$tagInfo = $$et{$keysGrp}{Info}{$keysIndex};
|
|
1102
1157
|
unless ($newIndex) {
|
|
1103
1158
|
if ($tagInfo) {
|
|
1104
1159
|
$et->VPrint(1," - Keys:$$tagInfo{Name}");
|
|
@@ -1129,7 +1184,7 @@ sub WriteQuickTime($$$)
|
|
|
1129
1184
|
next;
|
|
1130
1185
|
}
|
|
1131
1186
|
}
|
|
1132
|
-
undef $tagInfo if $tagInfo and $$tagInfo{
|
|
1187
|
+
undef $tagInfo if $tagInfo and $$tagInfo{AddedUnknown};
|
|
1133
1188
|
|
|
1134
1189
|
if ($tagInfo and (not defined $$tagInfo{Writable} or $$tagInfo{Writable})) {
|
|
1135
1190
|
my $subdir = $$tagInfo{SubDirectory};
|
|
@@ -1138,7 +1193,7 @@ sub WriteQuickTime($$$)
|
|
|
1138
1193
|
if ($subdir) { # process atoms in this container from a buffer in memory
|
|
1139
1194
|
|
|
1140
1195
|
if ($tag eq 'trak') {
|
|
1141
|
-
|
|
1196
|
+
$$et{MediaType} = ''; # init media type for this track
|
|
1142
1197
|
delete $$et{AssumedDataRef};
|
|
1143
1198
|
}
|
|
1144
1199
|
my $subName = $$subdir{DirName} || $$tagInfo{Name};
|
|
@@ -1207,10 +1262,13 @@ sub WriteQuickTime($$$)
|
|
|
1207
1262
|
$$et{CHANGED} = $oldChanged;
|
|
1208
1263
|
undef $newData;
|
|
1209
1264
|
}
|
|
1210
|
-
if ($tag eq 'trak'
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1265
|
+
if ($tag eq 'trak') {
|
|
1266
|
+
$$et{MediaType} = ''; # reset media type at end of track
|
|
1267
|
+
if ($$et{AssumedDataRef}) {
|
|
1268
|
+
my $grp = $$et{CUR_WRITE_GROUP} || $dirName;
|
|
1269
|
+
$et->Error("Can't locate data reference to update offsets for $grp");
|
|
1270
|
+
delete $$et{AssumedDataRef};
|
|
1271
|
+
}
|
|
1214
1272
|
}
|
|
1215
1273
|
$$et{CUR_WRITE_GROUP} = $oldWriteGroup;
|
|
1216
1274
|
SetByteOrder('MM');
|
|
@@ -1506,7 +1564,7 @@ sub WriteQuickTime($$$)
|
|
|
1506
1564
|
}
|
|
1507
1565
|
if ($msg) {
|
|
1508
1566
|
# (allow empty sample description for non-audio/video handler types, eg. 'url ', 'meta')
|
|
1509
|
-
if ($$et{
|
|
1567
|
+
if ($$et{MediaType}) {
|
|
1510
1568
|
my $grp = $$et{CUR_WRITE_GROUP} || $parent;
|
|
1511
1569
|
$et->Error("$msg for $grp");
|
|
1512
1570
|
return $rtnErr;
|
|
@@ -1542,16 +1600,26 @@ sub WriteQuickTime($$$)
|
|
|
1542
1600
|
if (($lastTag eq 'mdat' or $lastTag eq 'moov') and not $dataPt and (not $$tagTablePtr{$tag} or
|
|
1543
1601
|
ref $$tagTablePtr{$tag} eq 'HASH' and $$tagTablePtr{$tag}{Unknown}))
|
|
1544
1602
|
{
|
|
1545
|
-
# identify other known trailers
|
|
1603
|
+
# identify other known trailers from their first bytes
|
|
1546
1604
|
$buf2 = '';
|
|
1547
1605
|
$raf->Seek($lastPos,0) and $raf->Read($buf2,8);
|
|
1606
|
+
my ($type, $len);
|
|
1548
1607
|
if ($buf2 eq 'CCCCCCCC') {
|
|
1549
|
-
$
|
|
1608
|
+
$type = 'Kenwood';
|
|
1550
1609
|
} elsif ($buf2 =~ /^(gpsa|gps0|gsen|gsea)...\0/s) {
|
|
1551
|
-
$
|
|
1610
|
+
$type = 'RIFF';
|
|
1552
1611
|
} else {
|
|
1553
|
-
$
|
|
1612
|
+
$type = 'Unknown';
|
|
1554
1613
|
}
|
|
1614
|
+
# determine length of this trailer
|
|
1615
|
+
if ($trailer) {
|
|
1616
|
+
$len = $$trailer[1] - $lastPos; # runs to start of next trailer
|
|
1617
|
+
} else {
|
|
1618
|
+
$raf->Seek(0, 2) or $et->Error('Seek error'), return $dataPt ? undef : 1;
|
|
1619
|
+
$len = $raf->Tell() - $lastPos; # runs to end of file
|
|
1620
|
+
}
|
|
1621
|
+
# add to start of linked list of trailers
|
|
1622
|
+
$trailer = [ $type, $lastPos, $len, $trailer ];
|
|
1555
1623
|
} else {
|
|
1556
1624
|
$et->Error($errStr);
|
|
1557
1625
|
return $dataPt ? undef : 1;
|
|
@@ -1559,7 +1627,16 @@ sub WriteQuickTime($$$)
|
|
|
1559
1627
|
}
|
|
1560
1628
|
$et->VPrint(0, " [deleting $delCount $dirName tag".($delCount==1 ? '' : 's')."]\n") if $delCount;
|
|
1561
1629
|
|
|
1562
|
-
|
|
1630
|
+
# can finally set necessary variables for creating Video/AudioKeys tags
|
|
1631
|
+
if ($createKeys < 0) {
|
|
1632
|
+
if ($avType{$$et{MediaType}}) {
|
|
1633
|
+
$createKeys = 1;
|
|
1634
|
+
($keysGrp, $keysPath) = ("$avType{$$et{MediaType}}Keys", 'MOV-Movie-Track');
|
|
1635
|
+
} else {
|
|
1636
|
+
$canCreate = 0;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
$createKeys &= ~0x01 unless $$addDirs{$keysGrp}; # (Keys may have been written)
|
|
1563
1640
|
|
|
1564
1641
|
# add new directories/tags at this level if necessary
|
|
1565
1642
|
if ($canCreate and (exists $$et{EDIT_DIRS}{$dirName} or $createKeys)) {
|
|
@@ -1570,13 +1647,13 @@ sub WriteQuickTime($$$)
|
|
|
1570
1647
|
my ($tag, $index);
|
|
1571
1648
|
# add Keys tags if necessary
|
|
1572
1649
|
if ($createKeys) {
|
|
1573
|
-
if ($curPath eq
|
|
1650
|
+
if ($curPath eq $keysPath) {
|
|
1574
1651
|
# add Meta for Keys if necessary
|
|
1575
1652
|
unless ($didDir{meta}) {
|
|
1576
1653
|
$$dirs{meta} = $Image::ExifTool::QuickTime::Movie{meta};
|
|
1577
1654
|
push @addTags, 'meta';
|
|
1578
1655
|
}
|
|
1579
|
-
} elsif ($curPath eq
|
|
1656
|
+
} elsif ($curPath eq "$keysPath-Meta") {
|
|
1580
1657
|
# special case for Keys Meta -- reset directories and start again
|
|
1581
1658
|
undef @addTags;
|
|
1582
1659
|
$dirs = { };
|
|
@@ -1585,10 +1662,10 @@ sub WriteQuickTime($$$)
|
|
|
1585
1662
|
$$dirs{$_} = $Image::ExifTool::QuickTime::Meta{$_};
|
|
1586
1663
|
push @addTags, $_;
|
|
1587
1664
|
}
|
|
1588
|
-
} elsif ($curPath eq
|
|
1589
|
-
foreach $index (sort { $a <=> $b } keys %{$$et{
|
|
1665
|
+
} elsif ($curPath eq "$keysPath-Meta-ItemList" and $$et{$keysGrp}) {
|
|
1666
|
+
foreach $index (sort { $a <=> $b } keys %{$$et{$keysGrp}{Add}}) {
|
|
1590
1667
|
my $id = Set32u($index);
|
|
1591
|
-
$$newTags{$id} = $$et{
|
|
1668
|
+
$$newTags{$id} = $$et{$keysGrp}{Add}{$index};
|
|
1592
1669
|
push @addTags, $id;
|
|
1593
1670
|
}
|
|
1594
1671
|
} else {
|
|
@@ -1600,8 +1677,7 @@ sub WriteQuickTime($$$)
|
|
|
1600
1677
|
foreach $tag (@addTags) {
|
|
1601
1678
|
my $tagInfo = $$dirs{$tag} || $$newTags{$tag};
|
|
1602
1679
|
next if defined $$tagInfo{CanCreate} and not $$tagInfo{CanCreate};
|
|
1603
|
-
next if defined $$tagInfo{
|
|
1604
|
-
(not $$et{HandlerType} or $$et{HandlerType} ne $$tagInfo{HandlerType});
|
|
1680
|
+
next if defined $$tagInfo{MediaType} and $$et{MediaType} ne $$tagInfo{MediaType};
|
|
1605
1681
|
my $subdir = $$tagInfo{SubDirectory};
|
|
1606
1682
|
unless ($subdir) {
|
|
1607
1683
|
my $nvHash = $et->GetNewValueHash($tagInfo);
|
|
@@ -1663,13 +1739,13 @@ sub WriteQuickTime($$$)
|
|
|
1663
1739
|
}
|
|
1664
1740
|
my $subName = $$subdir{DirName} || $$tagInfo{Name};
|
|
1665
1741
|
# QuickTime hierarchy is complex, so check full directory path before adding
|
|
1666
|
-
if ($createKeys and $curPath eq
|
|
1742
|
+
if ($createKeys and $curPath eq $keysPath and $subName eq 'Meta') {
|
|
1667
1743
|
$et->VPrint(0, " Creating Meta with mdta Handler and Keys\n");
|
|
1668
1744
|
# init Meta box for Keys tags with mdta Handler and empty Keys+ItemList
|
|
1669
1745
|
$buf2 = "\0\0\0\x20hdlr\0\0\0\0\0\0\0\0mdta\0\0\0\0\0\0\0\0\0\0\0\0" .
|
|
1670
1746
|
"\0\0\0\x10keys\0\0\0\0\0\0\0\0" .
|
|
1671
1747
|
"\0\0\0\x08ilst";
|
|
1672
|
-
} elsif ($createKeys and $curPath eq
|
|
1748
|
+
} elsif ($createKeys and $curPath eq "$keysPath-Meta") {
|
|
1673
1749
|
$buf2 = ($subName eq 'Keys' ? "\0\0\0\0\0\0\0\0" : '');
|
|
1674
1750
|
} elsif ($subName eq 'Meta' and $$et{OPTIONS}{QuickTimeHandler}) {
|
|
1675
1751
|
$et->VPrint(0, " Creating Meta with mdir Handler\n");
|
|
@@ -1718,8 +1794,8 @@ sub WriteQuickTime($$$)
|
|
|
1718
1794
|
}
|
|
1719
1795
|
}
|
|
1720
1796
|
# add only once (must delete _after_ call to WriteDirectory())
|
|
1721
|
-
# (Keys
|
|
1722
|
-
delete $$addDirs{$subName} unless $
|
|
1797
|
+
# (Keys tags are a special case, and are handled separately)
|
|
1798
|
+
delete $$addDirs{$subName} unless $createKeys;
|
|
1723
1799
|
}
|
|
1724
1800
|
}
|
|
1725
1801
|
# write HEIC metadata after top-level 'meta' box has been processed if editing this information
|
|
@@ -1745,9 +1821,9 @@ sub WriteQuickTime($$$)
|
|
|
1745
1821
|
# (could report a file if editing nothing when it contained an empty Meta atom)
|
|
1746
1822
|
# ++$$et{CHANGED};
|
|
1747
1823
|
}
|
|
1748
|
-
if ($curPath eq
|
|
1749
|
-
delete $$addDirs{
|
|
1750
|
-
delete $$et{
|
|
1824
|
+
if ($curPath eq "$keysPath-Meta") {
|
|
1825
|
+
delete $$addDirs{$keysGrp}; # prevent creation of another Meta for Keys tags
|
|
1826
|
+
delete $$et{$keysGrp};
|
|
1751
1827
|
}
|
|
1752
1828
|
}
|
|
1753
1829
|
|
|
@@ -2005,21 +2081,35 @@ sub WriteQuickTime($$$)
|
|
|
2005
2081
|
# write the stuff that must come last
|
|
2006
2082
|
Write($outfile, $writeLast) or $rtnVal = 0 if $writeLast;
|
|
2007
2083
|
|
|
2008
|
-
# copy
|
|
2009
|
-
|
|
2010
|
-
# are we deleting the
|
|
2084
|
+
# copy trailers if necessary
|
|
2085
|
+
while ($rtnVal and $trailer) {
|
|
2086
|
+
# are we deleting the trailers?
|
|
2011
2087
|
my $nvTrail = $et->GetNewValueHash($Image::ExifTool::Extra{Trailer});
|
|
2012
|
-
if ($$et{DEL_GROUP}{Trailer} or
|
|
2088
|
+
if ($$et{DEL_GROUP}{Trailer} or $$et{DEL_GROUP}{$$trailer[0]} or
|
|
2089
|
+
($nvTrail and not ($$nvTrail{Value} and $$nvTrail{Value}[0])))
|
|
2090
|
+
{
|
|
2013
2091
|
$et->Warn("Deleted $$trailer[0] trailer", 1);
|
|
2014
|
-
|
|
2015
|
-
$
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2092
|
+
++$$et{CHANGED};
|
|
2093
|
+
$trailer = $$trailer[3];
|
|
2094
|
+
next;
|
|
2095
|
+
}
|
|
2096
|
+
$raf->Seek($$trailer[1], 0) or $rtnVal = 0, last;
|
|
2097
|
+
if ($$trailer[0] eq 'MIE') {
|
|
2098
|
+
require Image::ExifTool::MIE;
|
|
2099
|
+
my %dirInfo = ( RAF => $raf, OutFile => $outfile );
|
|
2100
|
+
my $result = Image::ExifTool::MIE::ProcessMIE($et, \%dirInfo);
|
|
2101
|
+
$result > 0 or $et->Error('Error writing MIE trailer'), $rtnVal = 0, last;
|
|
2019
2102
|
} else {
|
|
2020
|
-
$
|
|
2103
|
+
$et->Warn(sprintf('Copying %s trailer from offset 0x%x (%d bytes)', @$trailer[0..2]), 1);
|
|
2104
|
+
my $len = $$trailer[2];
|
|
2105
|
+
while ($len) {
|
|
2106
|
+
my $n = $len > 65536 ? 65536 : $len;
|
|
2107
|
+
$raf->Read($buf2, $n) == $n and Write($outfile, $buf2) or $rtnVal = 0, last;
|
|
2108
|
+
$len -= $n;
|
|
2109
|
+
}
|
|
2110
|
+
$rtnVal or $et->Error("Error copying $$trailer[0] trailer"), last;
|
|
2021
2111
|
}
|
|
2022
|
-
$
|
|
2112
|
+
$trailer = $$trailer[3]; # step to next trailer in linked list
|
|
2023
2113
|
}
|
|
2024
2114
|
return $rtnVal;
|
|
2025
2115
|
}
|
|
@@ -2075,6 +2165,7 @@ sub WriteMOV($$)
|
|
|
2075
2165
|
$raf->Seek(0,0);
|
|
2076
2166
|
|
|
2077
2167
|
# write the file
|
|
2168
|
+
$$et{MediaType} = '';
|
|
2078
2169
|
$$dirInfo{Parent} = '';
|
|
2079
2170
|
$$dirInfo{DirName} = 'MOV';
|
|
2080
2171
|
$$dirInfo{ChunkOffset} = [ ]; # (just to be safe)
|
|
@@ -2100,7 +2191,7 @@ QuickTime-based file formats like MOV and MP4.
|
|
|
2100
2191
|
|
|
2101
2192
|
=head1 AUTHOR
|
|
2102
2193
|
|
|
2103
|
-
Copyright 2003-
|
|
2194
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
2104
2195
|
|
|
2105
2196
|
This library is free software; you can redistribute it and/or modify it
|
|
2106
2197
|
under the same terms as Perl itself.
|
|
@@ -34,6 +34,11 @@ my %webpMap = (
|
|
|
34
34
|
MakerNotes => 'ExifIFD',
|
|
35
35
|
);
|
|
36
36
|
|
|
37
|
+
my %deletableGroup = (
|
|
38
|
+
"XMP\0" => 'XMP', # delete incorrectly written "XMP\0" tag with XMP group
|
|
39
|
+
SEAL => 'SEAL', # delete SEAL tag with SEAL group
|
|
40
|
+
);
|
|
41
|
+
|
|
37
42
|
#------------------------------------------------------------------------------
|
|
38
43
|
# Write RIFF file (currently WebP-type only)
|
|
39
44
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref
|
|
@@ -46,6 +51,7 @@ sub WriteRIFF($$)
|
|
|
46
51
|
my $outfile = $$dirInfo{OutFile};
|
|
47
52
|
my $outsize = 0;
|
|
48
53
|
my $raf = $$dirInfo{RAF};
|
|
54
|
+
my $verbose = $et->Options('Verbose');
|
|
49
55
|
my ($buff, $err, $pass, %has, %dirDat, $imageWidth, $imageHeight);
|
|
50
56
|
|
|
51
57
|
# do this in 2 passes so we can set the size of the containing RIFF chunk
|
|
@@ -65,6 +71,7 @@ sub WriteRIFF($$)
|
|
|
65
71
|
SetByteOrder('II');
|
|
66
72
|
|
|
67
73
|
# determine which directories we must write for this file type
|
|
74
|
+
$et->Options(Verbose => 0) if $pass; # (avoid duplicate Verbose options here)
|
|
68
75
|
$et->InitWriteDirs(\%webpMap);
|
|
69
76
|
my $addDirs = $$et{ADD_DIRS};
|
|
70
77
|
my $editDirs = $$et{EDIT_DIRS};
|
|
@@ -73,6 +80,7 @@ sub WriteRIFF($$)
|
|
|
73
80
|
|
|
74
81
|
# write header
|
|
75
82
|
if ($pass) {
|
|
83
|
+
$et->Options(Verbose => $verbose);
|
|
76
84
|
my $needsVP8X = ($has{ANIM} or $has{'XMP '} or $has{EXIF} or
|
|
77
85
|
$has{ALPH} or $has{ICCP});
|
|
78
86
|
if ($has{VP8X} and not $needsVP8X and $$et{CHANGED}) {
|
|
@@ -146,13 +154,14 @@ sub WriteRIFF($$)
|
|
|
146
154
|
# RIFF chunks are padded to an even number of bytes
|
|
147
155
|
my $len2 = $len + ($len & 0x01);
|
|
148
156
|
# handle incorrect "XMP\0" chunk ID written by Google software
|
|
149
|
-
if ($tag
|
|
150
|
-
if ($$et{DEL_GROUP}{
|
|
151
|
-
# just ignore this chunk if deleting
|
|
157
|
+
if ($deletableGroup{$tag}) {
|
|
158
|
+
if ($$et{DEL_GROUP}{$deletableGroup{$tag}}) {
|
|
159
|
+
# just ignore this chunk if deleting the associated group
|
|
152
160
|
$raf->Seek($len2, 1) or $et->Error('Seek error'), last;
|
|
161
|
+
$et->VPrint(0, " Deleting $deletableGroup{$tag}\n") if $pass;
|
|
153
162
|
++$$et{CHANGED};
|
|
154
163
|
next;
|
|
155
|
-
}
|
|
164
|
+
} elsif ($tag eq "XMP\0") {
|
|
156
165
|
$et->Warn('Incorrect XMP tag ID',1) if $pass;
|
|
157
166
|
}
|
|
158
167
|
}
|
|
@@ -315,8 +324,10 @@ sub WriteRIFF($$)
|
|
|
315
324
|
$raf->Read($buff, 6) == 6 or $et->Error('Truncated VP8L chunk'), return 1;
|
|
316
325
|
$outsize += 6;
|
|
317
326
|
if ($buff =~ /^\x2f/s) {
|
|
327
|
+
my $word = Get32u(\$buff, 2);
|
|
318
328
|
$imageWidth = (Get16u(\$buff, 1) & 0x3fff) + 1;
|
|
319
|
-
$imageHeight = ((
|
|
329
|
+
$imageHeight = (($word >> 6) & 0x3fff) + 1;
|
|
330
|
+
$has{ALPH} = 1 if $word & 0x100000; # set alpha flag if necessary
|
|
320
331
|
}
|
|
321
332
|
$len2 -= 6;
|
|
322
333
|
}
|
|
@@ -363,7 +374,7 @@ Currently writes only WebP files.
|
|
|
363
374
|
|
|
364
375
|
=head1 AUTHOR
|
|
365
376
|
|
|
366
|
-
Copyright 2003-
|
|
377
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
367
378
|
|
|
368
379
|
This library is free software; you can redistribute it and/or modify it
|
|
369
380
|
under the same terms as Perl itself.
|