From 4ad6d1ad64e70691e83142ba98b79647d96caba4 Mon Sep 17 00:00:00 2001 From: Silvio Date: Mon, 26 Apr 2010 12:35:47 -0300 Subject: Initial code for XMP data import --- exif.class.php | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- exif.install | 15 ++++++- exif.module | 3 +- 3 files changed, 129 insertions(+), 13 deletions(-) diff --git a/exif.class.php b/exif.class.php index 967066d..5ff9a52 100644 --- a/exif.class.php +++ b/exif.class.php @@ -35,7 +35,7 @@ Class Exif { * @return array a list of exif tags to read for this image */ public function getExifFields($arCckFields=array()) { - $arSections = array('exif', 'file', 'computed', 'ifd0', 'gps', 'winxp', 'iptc'); + $arSections = array('exif', 'file', 'computed', 'ifd0', 'gps', 'winxp', 'iptc', 'xmp'); $arExif = array(); foreach ($arCckFields as $field) { @@ -116,6 +116,111 @@ Class Exif { return $info; } + /** + * Read XMP data from an image file. + * + * @param $file + * File path. + * + * @param $arTagNames + * Available metadata fields. + * + * @return + * XMP image metadata. + * + * @todo + * Support for different array keys. + */ + public function readXMPTags($file, $arTagNames=array()) { + // Get a CCK-XMP mapping. + $map = $this->getXMPFields(); + $xmp = $this->openXMP($file); + + // Iterate over XMP fields defined by CCK. + foreach ($arTagNames as $tagName) { + if ($tagName['section'] == "xmp") { + // Get XMP field. + $config = $map[$tagName['tag']]; + $field = $this->readXMPItem($xmp, $config); + $info[$tagName['section'] .'_'. $tagName['tag']] = $field; + } + } + + $this->closeXMP($xmp); + return $info; + } + + /** + * Open an image file for XMP data extraction. + * + * @param $file + * File path. + * + * @return + * Array with XMP file and metadata. + */ + function openXMP($file) { + // Setup + $xmpfiles = new SXMPFiles(); + $xmpmeta = new SXMPMeta(); + + // Open + $xmpfiles->OpenFile($file); + $xmpfiles->GetXMP($xmpmeta); + + return array('files' => $xmpfiles, 'meta' => $xmpmeta); + } + + /** + * Close a file opened for XMP data extraction. + * + * @param $xmp + * XMP array as returned from openXMP(). + */ + function closeXMP($xmp) { + $xmp['files']->CloseFile(); + } + + /** + * Read a single item from an image file. + * + * @param $xmp + * XMP array as returned from openXMP(). + * + * @param $config + * XMP field configuration. + * + * @param $key + * In case of array field type, the numeric field key. + * + * @return + * Field value. + */ + public function readXMPItem($xmp, $config, $key = 0) { + // Setup. + $xmpfiles = $xmp['files']; + $xmpmeta = $xmp['meta']; + + // Sort. + $xmpmeta->Sort(); + + // Get namespace. + $ns = $xmpmeta->GetNamespaceURI($config['ns']); + + // Read XMP data. + if ($config['type'] == 'property') { + $value = $xmpmeta->GetProperty($config['name'], $ns); + } + elseif ($config['type' == 'array') { + $value = $xmpmeta->GetArrayItem($config['name', $key, $ns); + } + elseif ($config['type'] == 'struct') { + $value = $xmpmeta->GetStructField($ns, $config['struct'], $ns, $config['name']); + } + + return $value; + } + /** * Just some little helper function to get the iptc fields * @return array @@ -184,17 +289,17 @@ Class Exif { } /** - * WMP fields mapper. As we're dealing with a mapper between RDF + * XMP fields mapper. As we're dealing with a mapper between RDF * elements and CCK fields, we have to define custom keys that * both on the field name and the namespace used. * - * And, as the WMP specs also defines some datatypes like properties, + * And, as the XMP specs also defines some datatypes like properties, * arrays and structures, we have to deal with those as well. * * @return array - * Mapping between CCK and WMP fields. + * Mapping between CCK and XMP fields. */ - public function getWMPFields() { + public function getXMPFields() { return array( 'headline' => array( 'name' => 'Headline', @@ -235,16 +340,19 @@ Class Exif { 'name' => 'CiAdrExtadr', 'ns' => 'Iptc4XmpCore', 'type' => 'struct', + 'struct' => 'CreatorContactInfo', ), 'ciemailwork' => array( 'name' => 'CiEmailWork', 'ns' => 'Iptc4XmpCore', 'type' => 'struct', + 'struct' => 'CreatorContactInfo', ), 'ciurlwork' => array( 'name' => 'CiUrlWork', 'ns' => 'Iptc4XmpCore', 'type' => 'struct', + 'struct' => 'CreatorContactInfo', ), 'scene' => array( 'name' => 'Scene', @@ -263,10 +371,4 @@ Class Exif { ), ); } - - /** - * Read WMP data from an image file. - */ - public function readWMPTags($file, $arTagNames=array()) { - } } diff --git a/exif.install b/exif.install index 0071310..f0f9fbd 100755 --- a/exif.install +++ b/exif.install @@ -22,5 +22,18 @@ function exif_requirements($phase) { ); } } + + if ($phase == 'runtime' || $phase == 'install') { + $xmp = class_exists('SXMPFiles'); + $requirements['xmp'] = array( + 'title' => $t('XMP'), + 'value' => $xmp, + ); + if (!$xmp) { + $requirements['xmp']['description'] = $t("You don't have XMP Toolkit installed in your system."); + $requirements['xmp']['severity'] = REQUIREMENT_ERROR; + } + } + return $requirements; -} \ No newline at end of file +} diff --git a/exif.module b/exif.module index cdbcd23..324512c 100755 --- a/exif.module +++ b/exif.module @@ -108,7 +108,8 @@ function exif_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { $data1 = _exif_reformat($exif->readExifTags($file, $ar_exif_fields)); $data2 = $exif->readIPTCTags($file, $ar_exif_fields); - $data = array_merge($data1, $data2); + $data3 = $exif->readXMPTags($file, $ar_exif_fields); + $data = array_merge($data1, $data2, $data3); // Loop through every exif enabled field and set its value to the // corresponding exif value. If no exif value was found, set the field -- cgit v1.2.3