2022-10-08 17:37:59 +08:00
|
|
|
# Before "make install", this script should be runnable with "make test".
|
|
|
|
# After "make install" it should work as "perl t/XMP.t".
|
|
|
|
|
|
|
|
BEGIN {
|
|
|
|
$| = 1; print "1..54\n"; $Image::ExifTool::configFile = '';
|
|
|
|
require './t/TestLib.pm'; t::TestLib->import();
|
|
|
|
}
|
|
|
|
END {print "not ok 1\n" unless $loaded;}
|
|
|
|
|
|
|
|
# definitions for user-defined tag test (#26)
|
|
|
|
%Image::ExifTool::UserDefined = (
|
|
|
|
'Image::ExifTool::XMP::Main' => {
|
|
|
|
myXMPns => {
|
|
|
|
SubDirectory => {
|
|
|
|
TagTable => 'Image::ExifTool::UserDefined::myXMPns',
|
|
|
|
# (see the definition of this table below)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
);
|
|
|
|
use vars %Image::ExifTool::UserDefined::myXMPns; # avoid "typo" warning
|
|
|
|
%Image::ExifTool::UserDefined::myXMPns = (
|
|
|
|
GROUPS => { 0 => 'XMP', 1 => 'XMP-myXMPns'},
|
|
|
|
NAMESPACE => { 'myXMPns' => 'http://ns.exiftool.org/t/XMP.t' },
|
|
|
|
WRITABLE => 'string',
|
|
|
|
ATestTag => { List => 'Bag', Resource => 1 },
|
|
|
|
BTestTag => {
|
|
|
|
Struct => {
|
|
|
|
TYPE => 'myXMPns:SomeFunnyType',
|
|
|
|
Field1 => { Writable => 'lang-alt', List => 'Bag' },
|
|
|
|
}
|
|
|
|
},
|
|
|
|
BTestTagField1 => { Name => 'Renamed', Flat => 1 },
|
|
|
|
);
|
|
|
|
|
|
|
|
# test 1: Load the module(s)
|
|
|
|
use Image::ExifTool 'ImageInfo';
|
|
|
|
use Image::ExifTool::XMP;
|
|
|
|
$loaded = 1;
|
|
|
|
print "ok 1\n";
|
|
|
|
|
|
|
|
my $testname = 'XMP';
|
|
|
|
my $testnum = 1;
|
|
|
|
|
|
|
|
# test 2: Extract information from XMP.jpg
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $info = $exifTool->ImageInfo('t/images/XMP.jpg', {Duplicates => 1});
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 3: Test rewriting everything with slightly different values
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
$exifTool->Options(Duplicates => 1, Binary => 1, ListJoin => undef);
|
|
|
|
my $info = $exifTool->ImageInfo('t/images/XMP.jpg');
|
|
|
|
my $tag;
|
|
|
|
foreach $tag (keys %$info) {
|
|
|
|
my $group = $exifTool->GetGroup($tag);
|
|
|
|
my $val = $$info{$tag};
|
|
|
|
if (ref $val eq 'ARRAY') {
|
|
|
|
push @$val, 'v2';
|
|
|
|
} elsif (ref $val eq 'SCALAR') {
|
|
|
|
$val = 'v2';
|
|
|
|
} elsif ($val =~ /^\d+(\.\d*)?$/) {
|
|
|
|
# (add extra .001 to avoid problem with aperture of 4.85
|
|
|
|
# getting rounded to 4.8 or 4.9 and causing failed tests)
|
|
|
|
$val += ($val / 10) + 1.001;
|
|
|
|
$1 or $val = int($val);
|
|
|
|
} else {
|
|
|
|
$val .= '-v2';
|
|
|
|
}
|
|
|
|
# eat return values so warning don't get printed
|
|
|
|
my @x = $exifTool->SetNewValue($tag, $val, Group=>$group, Replace=>1);
|
|
|
|
}
|
|
|
|
# also try writing a few specific tags
|
|
|
|
$exifTool->SetNewValue(CreatorCountry => 'Canada');
|
|
|
|
$exifTool->SetNewValue(CodedCharacterSet => 'UTF8', Protected => 1);
|
|
|
|
undef $info;
|
|
|
|
my $image;
|
|
|
|
my $ok = writeInfo($exifTool,'t/images/XMP.jpg',\$image);
|
|
|
|
# this is effectively what the RHEL 3 UTF8 LANG problem does:
|
|
|
|
# $image = pack("U*", unpack("C*", $image));
|
|
|
|
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool2 = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
$exifTool2->Options(Duplicates => 1);
|
|
|
|
$info = $exifTool2->ImageInfo(\$image);
|
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.jpg";
|
|
|
|
if (check($exifTool2, $info, $testname, $testnum) and $ok) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
|
|
|
# save bad file
|
|
|
|
open(TESTFILE,">$testfile");
|
|
|
|
binmode(TESTFILE);
|
|
|
|
print TESTFILE $image;
|
|
|
|
close(TESTFILE);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# tests 4/5: Test extracting then reading XMP data as a block
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $info = $exifTool->ImageInfo('t/images/XMP.jpg','XMP');
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless $$info{XMP};
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
|
|
|
|
++$testnum;
|
|
|
|
my $pass;
|
|
|
|
if ($$info{XMP}) {
|
|
|
|
$info = $exifTool->ImageInfo($$info{XMP});
|
|
|
|
$pass = check($exifTool, $info, $testname, $testnum);
|
|
|
|
}
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless $pass;
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 6: Test copying information to a new XMP data file
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
$exifTool->SetNewValuesFromFile('t/images/XMP.jpg');
|
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
my $ok = writeInfo($exifTool,undef,$testfile);
|
|
|
|
my $info = $exifTool->ImageInfo($testfile);
|
|
|
|
if (check($exifTool, $info, $testname, $testnum) and $ok) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 7: Test rewriting CS2 XMP information
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValue(Label => 'Blue');
|
|
|
|
$exifTool->SetNewValue(Rating => 3);
|
|
|
|
$exifTool->SetNewValue(Subject => q{char test: & > < ' "}, AddValue => 1);
|
|
|
|
$exifTool->SetNewValue('Rights' => "\xc2\xa9 Copyright Someone Else");
|
|
|
|
my $ok = writeInfo($exifTool,'t/images/XMP.xmp',$testfile);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/XMP_$testnum.out",$testfile,$testnum) and $ok;
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 8-11: Test reading/writing XMP with blank nodes and some problems that need correcting
|
|
|
|
{
|
|
|
|
my $file;
|
|
|
|
foreach $file ('XMP2.xmp', 'XMP3.xmp') {
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $info = $exifTool->ImageInfo("t/images/$file", {Duplicates => 1});
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
|
|
|
|
++$testnum;
|
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValue('XMP:Creator' => 'Phil', AddValue => 1);
|
|
|
|
$exifTool->SetNewValue('manifestplacedXResolution' => 1);
|
|
|
|
$exifTool->SetNewValue('attributionname' => 'something else');
|
|
|
|
$exifTool->WriteInfo("t/images/$file", $testfile);
|
|
|
|
my $err = $exifTool->GetValue('Error');
|
|
|
|
warn "\n $err\n" if $err;
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/XMP_$testnum.out",$testfile,$testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# tests 12-17: Test writing/deleting XMP alternate languages
|
|
|
|
{
|
|
|
|
my @writeList = (
|
|
|
|
[ ['Rights-x-default' => "\xc2\xa9 Copyright Another One"] ], # should overwrite x-default only
|
|
|
|
[ ['Rights-de-DE' => "\xc2\xa9 Urheberrecht Phil Harvey"] ], # should create de-DE only
|
|
|
|
[ ['Rights-x-default' => undef] ], # should delete x-default only
|
|
|
|
[ ['Rights-fr' => undef] ], # should delete fr only
|
|
|
|
[ ['Title-fr' => 'Test fr title'] ],# should not create x-default
|
|
|
|
[ ['Title-fr' => 'Test fr title'],
|
|
|
|
['Title-x-default' => 'dTitle'] ],# should create x-default before fr
|
|
|
|
);
|
|
|
|
my $writeListRef;
|
|
|
|
foreach $writeListRef (@writeList) {
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless writeCheck($writeListRef, $testname, $testnum,
|
2022-10-08 17:37:59 +08:00
|
|
|
't/images/XMP.xmp', ['XMP-dc:*']);
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 18: Delete some family 1 XMP groups
|
|
|
|
{
|
|
|
|
++$testnum;
|
|
|
|
my @writeInfo = (
|
|
|
|
[ 'xmp-xmpmm:all' => undef ],
|
|
|
|
[ 'XMP-PHOTOSHOP:all' => undef ],
|
|
|
|
);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless writeCheck(\@writeInfo, $testname, $testnum,
|
2022-10-08 17:37:59 +08:00
|
|
|
't/images/XMP.jpg', ['XMP:all']);
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 19-20: Copy from XMP to EXIF with and without PrintConv enabled
|
|
|
|
{
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
while ($testnum < 20) {
|
|
|
|
++$testnum;
|
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.jpg";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValue();
|
|
|
|
$exifTool->SetNewValuesFromFile('t/images/XMP.xmp', 'XMP:all>EXIF:all');
|
|
|
|
my $ok = writeInfo($exifTool, "t/images/Writer.jpg", $testfile);
|
|
|
|
my $info = $exifTool->ImageInfo($testfile, 'EXIF:all');
|
|
|
|
if (check($exifTool, $info, $testname, $testnum) and $ok) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
$exifTool->Options(PrintConv => 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 21-22: Copy from EXIF to XMP with and without PrintConv enabled
|
|
|
|
{
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
while ($testnum < 22) {
|
|
|
|
++$testnum;
|
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValue();
|
|
|
|
$exifTool->SetNewValuesFromFile('t/images/Canon.jpg', 'EXIF:* > XMP:*');
|
|
|
|
my $ok = writeInfo($exifTool, undef, $testfile);
|
|
|
|
my $info = $exifTool->ImageInfo($testfile, 'XMP:*');
|
|
|
|
if (check($exifTool, $info, $testname, $testnum) and $ok) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
$exifTool->Options(PrintConv => 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 23: Delete all tags except two specific XMP family 1 groups
|
|
|
|
{
|
|
|
|
++$testnum;
|
|
|
|
my @writeInfo = (
|
|
|
|
[ 'all' => undef ],
|
|
|
|
[ 'xmp-dc:all' => undef, Replace => 2 ],
|
|
|
|
[ 'xmp-xmprights:all' => undef, Replace => 2 ],
|
|
|
|
);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless writeCheck(\@writeInfo, $testname, $testnum,
|
2022-10-08 17:37:59 +08:00
|
|
|
't/images/XMP.jpg', ['XMP:all'], undef, 1);
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 24: Delete all tags except XMP
|
|
|
|
{
|
|
|
|
++$testnum;
|
|
|
|
my @writeInfo = (
|
|
|
|
[ 'all' => undef ],
|
|
|
|
[ 'xmp:all' => undef, Replace => 2 ],
|
|
|
|
);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless writeCheck(\@writeInfo, $testname, $testnum,
|
2022-10-08 17:37:59 +08:00
|
|
|
't/images/XMP.jpg', ['-file:all'], undef, 1);
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 25: Extract information from SVG image
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $info = $exifTool->ImageInfo('t/images/XMP.svg', {Duplicates => 1});
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 26: Test creating a variety of XMP information
|
|
|
|
# (including x:xmptk, rdf:about and rdf:resource attributes)
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
my @writeInfo = (
|
|
|
|
[ 'XMP-x:XMPToolkit' => "What's this?", Protected => 1 ],
|
|
|
|
[ 'XMP-rdf:About' => "http://www.exiftool.org/t/$testname.t#$testnum", Protected => 1 ],
|
|
|
|
[ 'XMP:ImageType' => 'Video' ],
|
|
|
|
[ 'LicenseeImageNotes-en' => 'english notes' ],
|
|
|
|
[ 'LicenseeImageNotes-de' => 'deutsche anmerkungen' ],
|
|
|
|
[ 'LicenseeImageNotes' => 'default notes' ],
|
|
|
|
[ 'LicenseeName' => 'Phil' ],
|
|
|
|
[ 'CopyrightStatus' => 'public' ],
|
|
|
|
[ 'Custom1-en' => 'a' ],
|
|
|
|
[ 'Custom1-en' => 'b' ],
|
|
|
|
[ 'ATestTag' => "http://www.exiftool.org/t/$testname.t#$testnum-one" ],
|
|
|
|
[ 'ATestTag' => "http://www.exiftool.org/t/$testname.t#$testnum-two" ],
|
|
|
|
);
|
|
|
|
$exifTool->SetNewValue(@$_) foreach @writeInfo;
|
|
|
|
my $ok = writeInfo($exifTool, undef, $testfile);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/XMP_$testnum.out",$testfile,$testnum) and $ok;
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 27: Extract information from exiftool RDF/XML output file
|
2024-07-09 10:17:06 +08:00
|
|
|
# (file created by application with this command line:
|
|
|
|
# "exiftool -X -D t/images/Nikon.jpg > t/image/XMP.xml")
|
2022-10-08 17:37:59 +08:00
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $info = $exifTool->ImageInfo('t/images/XMP.xml', {Duplicates => 1});
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 28: Write information to exiftool RDF/XML output file
|
|
|
|
{
|
|
|
|
++$testnum;
|
|
|
|
my @writeInfo = (
|
|
|
|
[ 'all' => undef ],
|
|
|
|
[ 'ifd0:all' => undef, Replace => 2 ],
|
|
|
|
[ 'XML-file:all' => undef, Replace => 2 ],
|
|
|
|
[ 'author' => 'Phil' ],
|
|
|
|
);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless writeCheck(\@writeInfo, $testname, $testnum, 't/images/XMP.xml');
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 29: Rewrite extended XMP segment
|
|
|
|
{
|
|
|
|
++$testnum;
|
|
|
|
my @writeInfo = ( [ 'author' => 'Test' ] );
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless writeCheck(\@writeInfo, $testname, $testnum, 't/images/ExtendedXMP.jpg');
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 30: Test mass copy with deletion of specific XMP family 1 groups in shorthand format
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
$exifTool->Options(XMPShorthand => 1);
|
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.out";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValuesFromFile('t/images/XMP.jpg');
|
|
|
|
$exifTool->SetNewValue('xmp-exif:all');
|
|
|
|
$exifTool->SetNewValue('XMP-TIFF:*');
|
|
|
|
$exifTool->WriteInfo(undef,$testfile,'XMP'); #(also test output file type option)
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/XMP_$testnum.out",$testfile,$testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 31: Extract structured information
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $info = $exifTool->ImageInfo('t/images/XMP4.xmp', {Struct => 1});
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# tests 32-34: Conditionally add XMP lang-alt tag
|
|
|
|
{
|
|
|
|
# write title only if it doesn't exist
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.jpg";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValue('XMP-dc:Title-de' => '', DelValue => 1);
|
|
|
|
$exifTool->SetNewValue('XMP-dc:Title-de' => 'A');
|
|
|
|
my $ok = writeInfo($exifTool,'t/images/Writer.jpg',$testfile);
|
|
|
|
my $info = $exifTool->ImageInfo($testfile,'XMP:*');
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum) and $ok;
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
|
|
|
|
# try again when title already exists
|
|
|
|
++$testnum;
|
|
|
|
my $testfile2 = "t/${testname}_${testnum}_failed.jpg";
|
|
|
|
unlink $testfile2;
|
|
|
|
$exifTool->SetNewValue('XMP-dc:Title-de' => 'B');
|
|
|
|
$exifTool->WriteInfo($testfile,$testfile2);
|
|
|
|
$info = $exifTool->ImageInfo($testfile2,'XMP:*');
|
|
|
|
if (check($exifTool, $info, $testname, $testnum, 32)) {
|
|
|
|
unlink $testfile2
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
|
|
|
|
# one final time replacing an existing title
|
|
|
|
++$testnum;
|
|
|
|
$testfile2 = "t/${testname}_${testnum}_failed.jpg";
|
|
|
|
unlink $testfile2;
|
|
|
|
$exifTool->SetNewValue('XMP-dc:Title-de' => 'A', DelValue => 1);
|
|
|
|
$exifTool->SetNewValue('XMP-dc:Title-de' => 'C');
|
|
|
|
$ok = writeInfo($exifTool,$testfile,$testfile2);
|
|
|
|
$info = $exifTool->ImageInfo($testfile2,'XMP:*');
|
|
|
|
if (check($exifTool, $info, $testname, $testnum) and $ok) {
|
|
|
|
unlink $testfile;
|
|
|
|
unlink $testfile2
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 35: Test various features of writing structured information
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
my @writeInfo = (
|
|
|
|
# write as flattened string
|
|
|
|
[ HierarchicalKeywords => '{keyWORD=A-1,childREN={keyword=A-2}}' ],
|
|
|
|
# write as HASH reference
|
|
|
|
[ HierarchicalKeywords => [{kEyWoRd=>'B-1', cHiLdReN=>{keyword=>'B-2'}},{keyword=>'C-1'}] ],
|
|
|
|
# write a type'd structure
|
|
|
|
[ licensee => {licenseename=>'Phil'} ],
|
|
|
|
# write a region, including a 'seeAlso' resource
|
|
|
|
[ 'RegionList', {
|
|
|
|
Area => {X=>0,Y=>0,W=>8,H=>8},
|
|
|
|
Name => 'Region 1',
|
|
|
|
type => 'Face',
|
|
|
|
seeAlso => 'plus:Licensee',
|
|
|
|
}],
|
|
|
|
# write alternate language structure elements
|
|
|
|
[ ArtworkOrObject => "{AOTitle=test,aotitle-de=pr\xc3\xbcfung,AOTitle_FR=\xc3\xa9preuve}" ],
|
|
|
|
# disable print conversion for a single structure element
|
|
|
|
[ 'XMP:Flash' => '{Return=no,mode#=2}' ],
|
|
|
|
# write a complex user-defined lang-alt structure
|
|
|
|
[ BTestTag => "{Field1-en-CA=[eh?],Field1-en-US=[huh?,groovy],Field1-fr=[,ing\xc3\xa9nieux]}" ],
|
|
|
|
# write some dynamic structure elements
|
|
|
|
[ RegionList => { Extensions => {
|
|
|
|
# may mix-and-match flattened and structured tags when writing!...
|
|
|
|
'XMP-exif:FlashReturn' => 'not', # flattened tag with group name
|
|
|
|
Flash => { 'Mode#' => 1 }, # structured tag with disabled conversion
|
|
|
|
'UsageTerms-fr' => 'libre', # lang-alt tag
|
|
|
|
'ArtworkTitle-de' => "verf\xc3\xa4nglich", # renamed lang-alt tag in a list
|
|
|
|
Renamed => 'this is wild', # user-defined renamed flattened tag with TYPE
|
|
|
|
}}],
|
|
|
|
);
|
|
|
|
$exifTool->SetNewValue(@$_) foreach @writeInfo;
|
|
|
|
my $ok = writeInfo($exifTool,undef,$testfile);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/images/XMP5.xmp",$testfile,$testnum) and $ok;
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# tests 36-37: Test reading structures with and without the Struct option
|
|
|
|
{
|
|
|
|
my $i;
|
|
|
|
for ($i=0; $i<2; ++$i) {
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
$exifTool->Options(Struct => 1 - $i);
|
|
|
|
$exifTool->Options(Escape => 'HTML'); # test escaping of structure fields too
|
|
|
|
my $info = $exifTool->ImageInfo("t/images/XMP5.xmp");
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 38: Copy complex structured information
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValuesFromFile('t/images/XMP5.xmp', 'xmp:all');
|
|
|
|
my $ok = writeInfo($exifTool,undef,$testfile);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/images/XMP5.xmp",$testfile,$testnum) and $ok;
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 39: Extract information from an INX file
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $info = $exifTool->ImageInfo('t/images/XMP.inx', {Duplicates => 1});
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 40: Copy by flattened tag name and structure at the same time
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValuesFromFile('t/images/XMP5.xmp', 'HierarchicalKeywords1', 'Licensee');
|
|
|
|
my $ok = writeInfo($exifTool,undef,$testfile);
|
|
|
|
my $info = $exifTool->ImageInfo($testfile, 'XMP:*');
|
|
|
|
if (check($exifTool, $info, $testname, $testnum) and $ok) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 41: Rest writing/reading all DarwinCore tags
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValue('xmp-dwc:*' => 2013);
|
|
|
|
my $ok = writeInfo($exifTool, undef, $testfile);
|
|
|
|
my $info = $exifTool->ImageInfo($testfile, {Duplicates => 1});
|
|
|
|
if (check($exifTool, $info, $testname, $testnum) and $ok) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 42: Read extended XMP
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $info = $exifTool->ImageInfo('t/images/ExtendedXMP.jpg', 'xmp:all');
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 43: Read XMP with unusual namespace prefixes
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $info = $exifTool->ImageInfo('t/images/XMP6.xmp', 'xmp:all');
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless check($exifTool, $info, $testname, $testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 44: Write XMP with unusual namespace prefixes
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValue('xmp-dc:subject' => 'changed');
|
|
|
|
$exifTool->WriteInfo("t/images/XMP6.xmp", $testfile);
|
|
|
|
my $err = $exifTool->GetValue('Error');
|
|
|
|
warn "\n $err\n" if $err;
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/XMP_$testnum.out",$testfile,$testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 45: Write empty structures
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
my $testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValue('regioninfo' => '{RegionList=[,]}');
|
|
|
|
$exifTool->SetNewValue('xmp:flash' => '{}');
|
|
|
|
$exifTool->WriteInfo(undef, $testfile);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/XMP_$testnum.out",$testfile,$testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
2024-07-09 10:17:06 +08:00
|
|
|
# test 46: Test the advanced-formatting '@' feature and "All" in the source group
|
2022-10-08 17:37:59 +08:00
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
$exifTool->Options(ListSplit => ', ');
|
2024-07-09 10:17:06 +08:00
|
|
|
my $subj = 'subject<${subject@;/^Test/ ? $_=undef : s/Tool$//}';
|
|
|
|
my $keyw = 'creator<${Adobe:all:all@;s/n/N/;$_=undef if /Y/}';
|
|
|
|
# (exclude Adobe tag because the Adobe segment would be extracted as a block when copying)
|
|
|
|
$exifTool->SetNewValuesFromFile('t/images/XMP.jpg', $subj, '-adobe', $keyw);
|
2022-10-08 17:37:59 +08:00
|
|
|
$testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
writeInfo($exifTool, undef, $testfile);
|
|
|
|
$exifTool->Options(ListSep => ' // ');
|
2024-07-09 10:17:06 +08:00
|
|
|
my $info = $exifTool->ImageInfo($testfile, 'Subject', 'Creator');
|
2022-10-08 17:37:59 +08:00
|
|
|
if (check($exifTool, $info, $testname, $testnum)) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# tests 47-49: Test replacing specific elements in list of structures
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
$exifTool->Options(ListSplit => ',');
|
|
|
|
$exifTool->Options(Struct => 1);
|
|
|
|
$exifTool->SetNewValue('LocationShownCity' => 'Manchester,Lyon,Frankfurt');
|
|
|
|
$testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
writeInfo($exifTool, 't/images/XMP7.xmp', $testfile);
|
|
|
|
my $info = $exifTool->ImageInfo($testfile, 'XMP:all');
|
|
|
|
if (check($exifTool, $info, $testname, $testnum)) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
|
|
|
|
++$testnum;
|
|
|
|
$exifTool->SetNewValue();
|
|
|
|
$exifTool->SetNewValue('LocationShownCity' => 'London,Berlin', DelValue => 1);
|
|
|
|
$exifTool->SetNewValue('LocationShownCity' => 'Oxford,Munich');
|
|
|
|
$testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
writeInfo($exifTool, 't/images/XMP7.xmp', $testfile);
|
|
|
|
$info = $exifTool->ImageInfo($testfile, 'XMP:all');
|
|
|
|
if (check($exifTool, $info, $testname, $testnum)) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
|
|
|
|
++$testnum;
|
|
|
|
$exifTool->SetNewValue();
|
|
|
|
$exifTool->SetNewValue('AboutCvTermName' => 'one,three', DelValue => 1);
|
|
|
|
$exifTool->SetNewValue('AboutCvTermName' => 'a,b,c');
|
|
|
|
$testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
writeInfo($exifTool, 't/images/XMP8.xmp', $testfile);
|
|
|
|
$info = $exifTool->ImageInfo($testfile, 'XMP:all');
|
|
|
|
if (check($exifTool, $info, $testname, $testnum)) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 50-53: Test replacing/creating elements in nested lang-alt list
|
|
|
|
{
|
|
|
|
++$testnum;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
$exifTool->SetNewValuesFromFile('t/images/XMP9.xmp', '*:*');
|
|
|
|
$testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->WriteInfo('t/images/XMP9.xmp', $testfile);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/XMP_$testnum.out",$testfile,$testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
|
|
|
|
++$testnum;
|
|
|
|
$testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->WriteInfo(undef, $testfile);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare('t/XMP_50.out',$testfile,$testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
|
|
|
|
++$testnum;
|
|
|
|
$testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->SetNewValue();
|
|
|
|
$exifTool->SetNewValue(Custom1 => 'test', DelValue => 1);
|
|
|
|
$exifTool->SetNewValue(Custom1 => 'new');
|
|
|
|
$exifTool->WriteInfo('t/images/XMP9.xmp', $testfile);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/XMP_$testnum.out",$testfile,$testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
|
|
|
|
++$testnum;
|
|
|
|
$testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
|
|
|
$exifTool->Options(ListSplit => ',');
|
|
|
|
$exifTool->SetNewValue();
|
|
|
|
$exifTool->SetNewValue(Custom1 => 'a,b,c', AddValue => 1);
|
|
|
|
$exifTool->SetNewValue('Custom1-fr' => 'a-fr,,c-fr,d-fr,,f-fr', AddValue => 1);
|
|
|
|
$exifTool->WriteInfo('t/images/XMP9.xmp', $testfile);
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK() unless testCompare("t/XMP_$testnum.out",$testfile,$testnum);
|
2022-10-08 17:37:59 +08:00
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# test 54: Write flattened tag and extension in a variable-namespace structure
|
|
|
|
{
|
|
|
|
++$testnum;
|
|
|
|
$testfile = "t/${testname}_${testnum}_failed.xmp";
|
|
|
|
unlink $testfile;
|
2024-07-09 10:17:06 +08:00
|
|
|
my $exifTool = Image::ExifTool->new;
|
2022-10-08 17:37:59 +08:00
|
|
|
$exifTool->SetNewValue(ImageRegionCtypeIdentifier => 'x');
|
|
|
|
$exifTool->SetNewValue(ImageRegion => '{Flash={Fired=True,Return#=3}}');
|
|
|
|
$exifTool->WriteInfo(undef, $testfile);
|
|
|
|
$exifTool->Options(Struct => 1);
|
|
|
|
my $info = $exifTool->ImageInfo($testfile, 'XMP-iptcExt:all');
|
|
|
|
if (check($exifTool, $info, $testname, $testnum)) {
|
|
|
|
unlink $testfile;
|
|
|
|
} else {
|
2024-07-09 10:17:06 +08:00
|
|
|
notOK();
|
2022-10-08 17:37:59 +08:00
|
|
|
}
|
|
|
|
print "ok $testnum\n";
|
|
|
|
}
|
|
|
|
|
2024-07-09 10:17:06 +08:00
|
|
|
done(); # end
|