Image-ExifTool
view release on metacpan or search on metacpan
lib/Image/ExifTool/WriteXMP.pl view on Meta::CPAN
}
#------------------------------------------------------------------------------
# Save information about resource containing blank node with nodeID
# Inputs: 0) reference to blank node information hash
# 1) reference to property list
# 2) property value
# 3) [optional] reference to attribute hash
# Notes: This routine and ProcessBlankInfo() are also used for reading information, but
# are uncommon so are put in this file to reduce compile time for the common case
sub SaveBlankInfo($$$;$)
{
my ($blankInfo, $propListPt, $val, $attrs) = @_;
my $propPath = join '/', @$propListPt;
my @ids = ($propPath =~ m{ #([^ /]*)}g);
my $id;
# split the property path at each nodeID
foreach $id (@ids) {
my ($pre, $prop, $post) = ($propPath =~ m{^(.*?)/([^/]*) #$id((/.*)?)$});
defined $pre or warn("internal error parsing nodeID's"), next;
# the element with the nodeID should be in the path prefix for subject
# nodes and the path suffix for object nodes
unless ($prop eq $rdfDesc) {
if ($post) {
$post = "/$prop$post";
} else {
$pre = "$pre/$prop";
}
}
$$blankInfo{Prop}{$id}{Pre}{$pre} = 1;
if ((defined $post and length $post) or (defined $val and length $val)) {
# save the property value and attributes for each unique path suffix
$$blankInfo{Prop}{$id}{Post}{$post} = [ $val, $attrs, $propPath ];
}
}
}
#------------------------------------------------------------------------------
# Process blank-node information
# Inputs: 0) ExifTool object ref, 1) tag table ref,
# 2) blank node information hash ref, 3) flag set for writing
sub ProcessBlankInfo($$$;$)
{
my ($et, $tagTablePtr, $blankInfo, $isWriting) = @_;
$et->VPrint(1, " [Elements with nodeID set:]\n") unless $isWriting;
my ($id, $pre, $post);
# handle each nodeID separately
foreach $id (sort keys %{$$blankInfo{Prop}}) {
my $path = $$blankInfo{Prop}{$id};
# flag all resource names so we can warn later if some are unused
my %unused;
foreach $post (keys %{$$path{Post}}) {
$unused{$post} = 1;
}
# combine property paths for all possible paths through this node
foreach $pre (sort keys %{$$path{Pre}}) {
# there will be no description for the object of a blank node
next unless $pre =~ m{/$rdfDesc/};
foreach $post (sort keys %{$$path{Post}}) {
my @propList = split m{/}, "$pre$post";
my ($val, $attrs) = @{$$path{Post}{$post}};
if ($isWriting) {
CaptureXMP($et, \@propList, $val, $attrs);
} else {
FoundXMP($et, $tagTablePtr, \@propList, $val);
}
delete $unused{$post};
}
}
# save information from unused properties (if RDF is malformed like f-spot output)
if (%unused) {
$et->Options('Verbose') and $et->Warn('An XMP resource is about nothing');
foreach $post (sort keys %unused) {
my ($val, $attrs, $propPath) = @{$$path{Post}{$post}};
my @propList = split m{/}, $propPath;
if ($isWriting) {
CaptureXMP($et, \@propList, $val, $attrs);
} else {
FoundXMP($et, $tagTablePtr, \@propList, $val);
}
}
}
}
}
#------------------------------------------------------------------------------
# Convert path to namespace used in file (this is a pain, but the XMP
# spec only suggests 'preferred' namespace prefixes...)
# Inputs: 0) ExifTool object reference, 1) property path
# Returns: conforming property path
sub ConformPathToNamespace($$)
{
my ($et, $path) = @_;
my @propList = split('/',$path);
my $nsUsed = $$et{XMP_NS};
my $prop;
foreach $prop (@propList) {
my ($ns, $tag) = $prop =~ /(.+?):(.*)/;
next if not defined $ns or $$nsUsed{$ns};
my $uri = $nsURI{$ns};
unless ($uri) {
warn "No URI for namespace prefix $ns!\n";
next;
}
my $ns2;
foreach $ns2 (keys %$nsUsed) {
next unless $$nsUsed{$ns2} eq $uri;
# use the existing namespace prefix instead of ours
$prop = "$ns2:$tag";
last;
}
}
return join('/',@propList);
}
#------------------------------------------------------------------------------
# Add necessary rdf:type element when writing structure
# Inputs: 0) ExifTool ref, 1) tag table ref, 2) capture hash ref, 3) path string
# 4) optional base path (already conformed to namespace) for elements in
# variable-namespace structures
sub AddStructType($$$$;$)
{
my ($et, $tagTablePtr, $capture, $path, $basePath) = @_;
my @props = split '/', $path;
my %doneID;
for (;;) {
pop @props;
last unless @props;
my $tagID = GetXMPTagID(\@props);
next if $doneID{$tagID};
$doneID{$tagID} = 1;
my $tagInfo = $$tagTablePtr{$tagID};
last unless ref $tagInfo eq 'HASH';
if ($$tagInfo{Struct}) {
my $type = $$tagInfo{Struct}{TYPE};
( run in 0.625 second using v1.01-cache-2.11-cpan-71847e10f99 )