aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Tilloy <olivier@tilloy.net>2009-04-21 09:23:46 +0200
committerOlivier Tilloy <olivier@tilloy.net>2009-04-21 09:23:46 +0200
commit279b974080eafb42af1f8da3920e2c4d04e63a0f (patch)
tree93588f4ab285712b8bae63e2f8c68d93088a4446
parent8ee4a60dcfd299331ba30992fc324aeeeba694ab (diff)
downloadpyexiv2-279b974080eafb42af1f8da3920e2c4d04e63a0f.tar.gz
Unlike IPTC tags, XMP tags are not repeatable.
-rw-r--r--src/exiv2wrapper.cpp79
-rw-r--r--src/exiv2wrapper.hpp9
-rw-r--r--src/pyexiv2.py37
-rw-r--r--unittest/metadata.py8
4 files changed, 91 insertions, 42 deletions
diff --git a/src/exiv2wrapper.cpp b/src/exiv2wrapper.cpp
index 18eff7d..4c37fd6 100644
--- a/src/exiv2wrapper.cpp
+++ b/src/exiv2wrapper.cpp
@@ -344,39 +344,70 @@ boost::python::list Image::xmpKeys()
boost::python::tuple Image::getXmpTag(std::string key)
{
- if(_dataRead)
+ if(!_dataRead)
{
- Exiv2::XmpKey xmpKey = Exiv2::XmpKey(key);
- boost::python::list values;
- unsigned int occurences = 0;
- for (Exiv2::XmpMetadata::iterator i = _xmpData.begin();
- i != _xmpData.end();
- ++i)
- {
- if (i->key() == key)
- {
- values.append(i->toString());
- ++occurences;
- }
- }
- if (occurences > 0)
+ throw Exiv2::Error(METADATA_NOT_READ);
+ }
+
+ Exiv2::XmpKey xmpKey = Exiv2::XmpKey(key);
+
+ if(_xmpData.findKey(xmpKey) == _xmpData.end())
+ {
+ throw Exiv2::Error(KEY_NOT_FOUND, key);
+ }
+
+ Exiv2::Xmpdatum xmpDatum = _xmpData[key];
+ std::string sTagName = xmpKey.tagName();
+ std::string sTagLabel = xmpKey.tagLabel();
+ std::string sTagDesc(Exiv2::XmpProperties::propertyDesc(xmpKey));
+ std::string sTagType(Exiv2::XmpProperties::propertyInfo(xmpKey)->xmpValueType_);
+ std::string sTagValue = xmpDatum.toString();
+ return boost::python::make_tuple(key, sTagName, sTagLabel, sTagDesc, sTagType, sTagValue);
+}
+
+/*void Image::setXmpTagValues(std::string key, boost::python::tuple values)
+{
+ if (!_dataRead)
+ {
+ throw Exiv2::Error(METADATA_NOT_READ);
+ }
+
+ Exiv2::XmpKey xmpKey = Exiv2::XmpKey(key);
+ unsigned int index = 0;
+ unsigned int max = len(values);
+ Exiv2::XmpMetadata::iterator dataIterator = _xmpData.findKey(xmpKey);
+ while (index < max)
+ {
+ std::string value = boost::python::extract<std::string>(values[index++]);
+ if (dataIterator != _xmpData.end())
{
- std::string sTagName = xmpKey.tagName();
- std::string sTagLabel = xmpKey.tagLabel();
- std::string sTagDesc(Exiv2::XmpProperties::propertyDesc(xmpKey));
- std::string sTagType(Exiv2::XmpProperties::propertyInfo(xmpKey)->xmpValueType_);
- return boost::python::make_tuple(key, sTagName, sTagLabel, sTagDesc, sTagType, values);
+ // Override an existing value
+ dataIterator->setValue(value);
+ dataIterator = std::find_if(++dataIterator, _xmpData.end(),
+ Exiv2::FindMetadatumById::FindMetadatumById(xmpKey.tag(),
+ xmpKey.record()));
}
else
{
- throw Exiv2::Error(KEY_NOT_FOUND, key);
+ // Append a new value
+ Exiv2::Iptcdatum iptcDatum(iptcKey);
+ iptcDatum.setValue(value);
+ int state = _iptcData.add(iptcDatum);
+ if (state == 6)
+ {
+ throw Exiv2::Error(NON_REPEATABLE);
+ }
}
}
- else
+ // Erase the remaining values if any
+ while (dataIterator != _iptcData.end())
{
- throw Exiv2::Error(METADATA_NOT_READ);
+ _iptcData.erase(dataIterator);
+ dataIterator = std::find_if(dataIterator, _iptcData.end(),
+ Exiv2::FindMetadatumById::FindMetadatumById(iptcKey.tag(),
+ iptcKey.record()));
}
-}
+}*/
/*
boost::python::tuple Image::getThumbnailData()
diff --git a/src/exiv2wrapper.hpp b/src/exiv2wrapper.hpp
index 3dfd850..0e66f50 100644
--- a/src/exiv2wrapper.hpp
+++ b/src/exiv2wrapper.hpp
@@ -95,13 +95,8 @@ public:
// tagvalue (list)
boost::python::tuple getIptcTag(std::string key);
- // Set the IPTC tag's value. If the tag was not previously set, it is
+ // Set the IPTC tag's values. If the tag was not previously set, it is
// created.
- // If the key references a repeatable tag, the parameter index (starting
- // from 0 like a list index) is used to determine which of the
- // repetitions is to be set. In case of an index greater than the
- // highest existing one, adds a repetition of the tag.
- //void setIptcTag(std::string key, std::string value, unsigned int index);
void setIptcTagValues(std::string key, boost::python::tuple values);
// Delete (all the repetitions of) the required IPTC tag.
@@ -118,6 +113,8 @@ public:
// tagvalue (list)
boost::python::tuple getXmpTag(std::string key);
+ void setXmpTagValues(std::string key, boost::python::tuple values);
+
// Read and write access to the thumbnail embedded in the image.
// Return a tuple containing the format of the thumbnail ("TIFF" or
diff --git a/src/pyexiv2.py b/src/pyexiv2.py
index 63202da..65bcce7 100644
--- a/src/pyexiv2.py
+++ b/src/pyexiv2.py
@@ -541,8 +541,8 @@ class IptcTag(MetadataTag):
def _set_values(self, new_values):
if self.metadata is not None:
- raw_value = map(lambda x: IptcTag._convert_to_string(x, self.xtype), new_values)
- self.metadata._set_iptc_tag_values(self.key, raw_value)
+ raw_values = map(lambda x: IptcTag._convert_to_string(x, self.xtype), new_values)
+ self.metadata._set_iptc_tag_values(self.key, raw_values)
self._values = new_values
def _del_values(self):
@@ -720,12 +720,30 @@ class XmpTag(MetadataTag):
_time_re = r'(?P<hours>\d{2})(:(?P<minutes>\d{2})(:(?P<seconds>\d{2})(.(?P<decimal>\d+))?)?(?P<tzd>%s))?' % _time_zone_re
_date_re = re.compile(r'(?P<year>\d{4})(-(?P<month>\d{2})(-(?P<day>\d{2})(T(?P<time>%s))?)?)?' % _time_re)
- def __init__(self, key, name, label, description, xtype, values):
+ def __init__(self, key, name, label, description, xtype, value):
"""
Constructor.
"""
- super(XmpTag, self).__init__(key, name, label, description, xtype, values)
- self.values = map(lambda x: XmpTag._convert_to_python(x, xtype), values)
+ super(XmpTag, self).__init__(key, name, label, description, xtype, value)
+ self._value = XmpTag._convert_to_python(value, xtype)
+
+ def _get_value(self):
+ return self._value
+
+ def _set_value(self, new_value):
+ if self.metadata is not None:
+ raw_value = XmpTag._convert_to_string(new_value, self.xtype)
+ self.metadata._set_xmp_tag_value(self.key, raw_value)
+ self._value = new_value
+
+ def _del_value(self):
+ if self.metadata is not None:
+ self.metadata._delete_xmp_tag(self.key)
+ del self._value
+
+ # DOCME
+ value = property(fget=_get_value, fset=_set_value, fdel=_del_value,
+ doc=None)
@staticmethod
def _convert_to_python(value, xtype):
@@ -1132,10 +1150,13 @@ class ImageMetadata(object):
self._image.setIptcTagValues(key, values)
def _set_xmp_tag(self, tag):
- # TODO
- raise NotImplementedError()
+ if type(tag) is not XmpTag:
+ raise TypeError('Expecting an XmpTag')
+ self._image.setXmpTagValue(tag.key, tag.to_string())
+ self._tags['xmp'][tag.key] = tag
+ tag.metadata = self
- def _set_xmp_tag_values(self, key, values):
+ def _set_xmp_tag_value(self, key, value):
# Overwrite the tag value for an already existing tag.
# The tag is already in cache.
# Warning: this is not meant to be called directly as it doesn't update
diff --git a/unittest/metadata.py b/unittest/metadata.py
index ade5599..fa56de2 100644
--- a/unittest/metadata.py
+++ b/unittest/metadata.py
@@ -119,21 +119,21 @@ class TestImageMetadata(unittest.TestCase):
('Xmp.dc.format', 'format', 'Format', 'The file format used when ' \
'saving the resource. Tools and applications should set this ' \
'property to the save format of the data. It may include ' \
- 'appropriate qualifiers.', 'MIMEType', ['image/jpeg'])
+ 'appropriate qualifiers.', 'MIMEType', 'image/jpeg')
tags['Xmp.dc.subject'] = \
('Xmp.dc.subject', 'subject', 'Subject', 'An unordered array of ' \
'descriptive phrases or keywords that specify the topic of the ' \
- 'content of the resource.', 'bag Text', ['image, test, pyexiv2'])
+ 'content of the resource.', 'bag Text', 'image, test, pyexiv2')
tags['Xmp.xmp.CreateDate'] = \
('Xmp.xmp.CreateDate', 'CreateDate', 'Create Date',
'The date and time the resource was originally created.', 'Date',
- ['2005-09-07T15:07:40-07:00'])
+ '2005-09-07T15:07:40-07:00')
tags['Xmp.xmpMM.DocumentID'] = \
('Xmp.xmpMM.DocumentID', 'DocumentID', 'Document ID',
'The common identifier for all versions and renditions of a ' \
'document. It should be based on a UUID; see Document and ' \
'Instance IDs below.', 'URI',
- ['uuid:9A3B7F52214211DAB6308A7391270C13'])
+ 'uuid:9A3B7F52214211DAB6308A7391270C13')
self.metadata._image.tags['xmp'] = tags
######################