summaryrefslogtreecommitdiff
path: root/rapid/metadataxmp.py
diff options
context:
space:
mode:
authorJulien Valroff <julien@kirya.net>2012-01-08 07:54:47 +0100
committerJulien Valroff <julien@kirya.net>2012-01-08 07:54:47 +0100
commitc7b6cc09dc694f8f321c5c7365c1e6ca445291a0 (patch)
treed18525fdc87178ae9e6c497734ed40ea62e41e63 /rapid/metadataxmp.py
parent1e866ec41146b8c85b874eb09b605538823985a4 (diff)
parent05e7b52a1f94a40996f2619ad9db8bbdb1518497 (diff)
Merge commit 'upstream/0.4.3'
Diffstat (limited to 'rapid/metadataxmp.py')
-rwxr-xr-xrapid/metadataxmp.py198
1 files changed, 198 insertions, 0 deletions
diff --git a/rapid/metadataxmp.py b/rapid/metadataxmp.py
new file mode 100755
index 0000000..47321e3
--- /dev/null
+++ b/rapid/metadataxmp.py
@@ -0,0 +1,198 @@
+#!/usr/bin/python
+# -*- coding: latin1 -*-
+
+### Copyright (C) 2011-12 Damon Lynch <damonlynch@gmail.com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import subprocess
+
+import multiprocessing, logging
+logger = multiprocessing.get_logger()
+
+class XmpMetadataSidecar:
+
+ def __init__(self, filename):
+ self.filename = filename
+ self.keys = []
+
+ def _add_pair(self, key_value_pair):
+ self.keys.append(key_value_pair)
+ logger.debug(key_value_pair)
+
+ def _generate_exiv2_command_line(self):
+ # -f option: overwrites any existing xmp file
+ return ['exiv2', '-f'] + self.keys + ['-exX', self.filename]
+
+ def _generate_exiv2_contact_info(self, key, value):
+ return "-M set Xmp.iptc.CreatorContactInfo/Iptc4xmpCore:%s %s" % (key, value)
+
+ def _generate_exiv2_dc(self, key, value):
+ return "-M set Xmp.dc.%s %s" % (key, value)
+
+ def _generate_exiv2_photoshop(self, key, value):
+ return "-M set Xmp.photoshop.%s %s" % (key, value)
+
+ def _generate_exiv2_rights(self, key, value):
+ return "-M set Xmp.xmpRights.%s %s" % (key, value)
+
+ def _generate_exiv2_iptc(self, key, value):
+ return "-M set Xmp.iptc.%s %s" % (key, value)
+
+ def _generate_exiv2_exif(self, key, value):
+ return "-M set Xmp.exif.%s %s" % (key, value)
+
+ def set_location(self, location):
+ self._add_pair(self._generate_exiv2_iptc('Location', location))
+
+ def set_city(self, city):
+ self._add_pair(self._generate_exiv2_photoshop('City', city))
+
+ def set_state_province(self, state):
+ self._add_pair(self._generate_exiv2_photoshop('State', state))
+
+ def set_country(self, country):
+ self._add_pair(self._generate_exiv2_photoshop('Country', country))
+
+ def set_country_code(self, country_code):
+ self._add_pair(self._generate_exiv2_iptc('CountryCode', country_code))
+
+ def set_headline(self, headline):
+ self._add_pair(self._generate_exiv2_photoshop('Headline', headline))
+
+ def set_description_writer(self, writer):
+ """
+ Synonym: Caption writer
+ """
+ self._add_pair(self._generate_exiv2_photoshop('CaptionWriter', writer))
+
+ def set_description(self, description):
+ """A synonym for this in some older programs is 'Caption'"""
+ self._add_pair(self._generate_exiv2_dc('description', description))
+
+ def set_subject(self, subject):
+ """
+ You can call this more than once, to add multiple subjects
+
+ A synonym is 'Keywords'
+ """
+ self._add_pair(self._generate_exiv2_dc('subject', subject))
+
+ def set_creator(self, creator):
+ """
+ Sets the author (creator) field. Photo Mechanic calls this 'Photographer'.
+ """
+ self._add_pair(self._generate_exiv2_dc('creator', creator))
+
+ def set_creator_job_title(self, job_title):
+ self._add_pair(self._generate_exiv2_photoshop('AuthorsPosition', job_title))
+
+ def set_credit_line(self, credit_line):
+ self._add_pair(self._generate_exiv2_photoshop('Credit', credit_line))
+
+ def set_source(self, source):
+ """
+ original owner or copyright holder of the photograph
+ """
+ self._add_pair(self._generate_exiv2_photoshop('Source', source))
+
+ def set_copyright(self, copyright):
+ self._add_pair(self._generate_exiv2_dc('rights', copyright))
+
+ def set_copyright_url(self, copyright_url):
+ self._add_pair(self._generate_exiv2_rights('WebStatement', copyright_url))
+
+ def set_contact_city(self, city):
+ self._add_pair(self._generate_exiv2_contact_info('CiAdrCity', city))
+
+ def set_contact_country(self, country):
+ self._add_pair(self._generate_exiv2_contact_info('CiAdrCtry', country))
+
+ def set_contact_address(self, address):
+ """The contact information address part.
+ Comprises an optional company name and all required information
+ to locate the building or postbox to which mail should be sent."""
+ self._add_pair(self._generate_exiv2_contact_info('CiAdrExtadr', address))
+
+ def set_contact_postal_code(self, postal_code):
+ self._add_pair(self._generate_exiv2_contact_info('CiAdrPcode', postal_code))
+
+ def set_contact_region(self, region):
+ """State/Province"""
+ self._add_pair(self._generate_exiv2_contact_info('CiAdrRegion', region))
+
+ def set_contact_email(self, email):
+ """Multiple email addresses can be given, separated by a comma."""
+ self._add_pair(self._generate_exiv2_contact_info('CiEmailWork', email))
+
+ def set_contact_telephone(self, telephone):
+ """Multiple numbers can be given, separated by a comma."""
+ self._add_pair(self._generate_exiv2_contact_info('CiTelWork', telephone))
+
+ def set_contact_url(self, url):
+ """Multiple URLs can be given, separated by a comma."""
+ self._add_pair(self._generate_exiv2_contact_info('CiUrlWork', url))
+
+ def set_exif_value(self, key, value):
+ self._add_pair(self._generate_exiv2_exif(key, value))
+
+ def write_xmp_sidecar(self):
+ cmd = self._generate_exiv2_command_line()
+ if logger.getEffectiveLevel() == logging.DEBUG:
+ cmd_line = ''
+ for c in cmd:
+ cmd_line += c + ' '
+ cmd_line = cmd_line.strip()
+ logger.debug("XMP write command: %s", cmd_line)
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ return proc.communicate()[0].strip()
+
+
+if __name__ == '__main__':
+ import sys
+
+
+ if (len(sys.argv) != 2):
+ print 'Usage: ' + sys.argv[0] + ' path/to/photo/containing/metadata'
+
+ else:
+ x = XmpMetadataSidecar(sys.argv[1])
+ x.set_description("This is image is just a sample and is nothing serious. I used to test out writing XMP files in Rapid Photo Downloader.")
+ x.set_description_writer("Damon Lynch wrote caption")
+ x.set_headline("Sample image to test XMP")
+ x.set_subject("Keyword 1")
+ x.set_subject("Keyword 2")
+ x.set_city("Minneapolis")
+ x.set_location("University of Minnesota")
+ x.set_state_province("Minnesota")
+ x.set_country("United States of America")
+ x.set_country_code("USA")
+ x.set_creator("Damon Lynch")
+ x.set_creator_job_title("Photographer")
+ x.set_credit_line("Contact Damon for permission")
+ x.set_source("Damon Lynch is the original photographer")
+ x.set_copyright("© 2011 Damon Lynch, all rights reserved.")
+ x.set_copyright_url("http://www.damonlynch.net/license")
+ x.set_contact_address("Contact house number, street, apartment")
+ x.set_contact_city('Contact City')
+ x.set_contact_region('Contact State')
+ x.set_contact_postal_code('Contact Post code')
+ x.set_contact_telephone('+1 111 111 1111')
+ x.set_contact_country('Contact Country')
+ x.set_contact_address('Address\nApartment')
+ x.set_contact_url('http://www.sample.net')
+ x.set_contact_email('name@email1.com, name@email2.com')
+
+ x.write_xmp_sidecar()