diff options
Diffstat (limited to 'exif.module')
| -rwxr-xr-x | exif.module | 566 | 
1 files changed, 299 insertions, 267 deletions
| diff --git a/exif.module b/exif.module index 7d955f1..2f41afb 100755 --- a/exif.module +++ b/exif.module @@ -1,61 +1,50 @@  <?php -// $Id: exif.module,v 1.9.2.18 2010/07/23 17:47:46 rapsli Exp $: +// $Id: exif.module,v 1.9 2008/04/05 23:22:05 davidlesieur Exp $  /** - * @file implementing the drupal api - */ -/** - * @author: Raphael Schär - www.rapsli.ch + * Implementation of hook_menu().   */ +function exif_menu($may_cache) { +  $items = array(); + +  if ($may_cache) { +    $items[] = array( +      'path' => 'admin/settings/exif', +      'title' => t('Exif'), +      'callback' => 'drupal_get_form', +      'callback arguments' => array('exif_admin_settings_form'), +      'access' => user_access('administer site configuration'), +      'description' => t('Configure what Exif tags to display.'), +    ); +  } -function exif_menu() { -  $items['admin/settings/exif'] = array( -    'title' => 'Exif', -    'page callback' => 'exif_admin_settings', -    'access arguments' => array('administer site configuration'), -    'description' => t('Display available fields'), -    'access callback' => 'user_access', -    'file' => 'exif.admin.inc', -    'type' => MENU_NORMAL_ITEM, -  ); -  $items['admin/settings/exif/general'] = array( -    'title' => 'Exif', -    'page callback' => 'exif_admin_settings', -    'access arguments' => array('administer site configuration'), -    'description' => t('Display available fields'), -    'access callback' => 'user_access', -    'file' => 'exif.admin.inc', -    'type' => MENU_DEFAULT_LOCAL_TASK, -  ); -  $items['admin/settings/exif/config'] = array( -    'title' => 'Config', -    'page callback' => 'drupal_get_form', -    'page arguments' => array('exif_admin_settings_form'), -    'access arguments' => array('administer site configuration'), -    'description' => t('Some Settings'), -    'access callback' => 'user_access', -    'file' => 'exif.admin.inc', -    'type' => MENU_LOCAL_TASK, -  );    return $items;  }  /** - * implementation of hook_nodeapi + * Implementation of hook_nodeapi().   */ -function exif_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { - -  if ($teaser) { +function exif_nodeapi(&$node, $op, $teaser) { +  if ($teaser || $node->type != 'image') {      return;    }    switch ($op) { - +    case 'insert':      case 'update': -      //we are only going to update if we have said so -      if (!variable_get('exif_update', TRUE)) { -        break; +      $fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $node->images[IMAGE_ORIGINAL])); +      $file = file_create_path($node->images[IMAGE_ORIGINAL]); +      $data = _exif_read_exif($file); +      db_query('DELETE FROM {exif} WHERE fid = %d', $fid); + +      // Cache data in db. +      foreach ($data as $ifd => $tags) { +        foreach ($tags as $tag => $value) { +          db_query("INSERT INTO {exif} (fid, ifd, tag, value) VALUES (%d, %d, %d, '%s')", +            $fid, $ifd, $tag, $value); +        }        } +<<<<<<< exif.module      case 'insert':        if (! _exif_check_for_exif_data($node->type)) {          return; @@ -67,282 +56,325 @@ function exif_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {        //get all the fields that will be filled with exif data        $ar_exif_fields = $exif->getExifFields($fields); - -      //get the path to the image -      $image_path = _exif_get_image_path($fields, $node); - -      $fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $image_path)); -      $file = file_create_path($image_path); - -      $data1 = _exif_reformat($exif->readExifTags($file, $ar_exif_fields)); -      $data2 = $exif->readIPTCTags($file, $ar_exif_fields); - -      if (class_exists('SXMPFiles')) { -        $data3 = $exif->readXMPTags($file, $ar_exif_fields); -        $data = array_merge($data1, $data2, $data3); -      } -      else { -        $data = array_merge($data1, $data2); -      } - -      // Loop through every exif enabled field and set its value to the -      // corresponding exif value. If no exif value was found, set the field -      // value to NULL, to avoid strange behaviour in other field modules -      // (date). -      foreach ($ar_exif_fields as $ar_exif_field) { -        $exif_name = $ar_exif_field['section'] .'_'. $ar_exif_field['tag']; -        $exif_value = isset($data[$exif_name]) ? $data[$exif_name] : NULL; - -        $field_name = 'field_'. $exif_name; -        if (! $exif_value) { -          if (variable_get('exif_empty_values', TRUE)) { -            $node->{$field_name}[0]['value'] = NULL; -          } -          continue; -        } -        $field = $fields[$field_name]; - -        // Setup the field value array for delta = 0. -        switch ($exif_name) { -          case 'exif_datetimeoriginal': -          case 'exif_datetimedigitized': -          case 'ifd0_datetime': -            $first_delta = _exif_date_handler($field, $exif_value); -            break; -          default: -            $first_delta = array('value' => $data[$exif_name]); -            break; -        } -        $node->{$field_name}[0] = $first_delta; -      } +======= +      break; +>>>>>>> 1.9 + +    case 'load': +      $fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $node->images[IMAGE_ORIGINAL])); +      return  array('exif_data' => _exif_get_exif($fid)); +    case 'view': +      $node->content['exif'] = array( +        '#value' => theme('exif_table', $node), +        '#weight' => 10, +      );        break;    }  }  /** - * Date API hook. - * - * Make exif a date format in Date API. This makes it possible to alter the - * format exif dates is parsed as. + * Administration page callback.   */ -function exif_date_format_types() { -  return array('exif' => 'EXIF'); -} - -/** - * Date API hook. - * - * Make the EXIF date format default for the 'exif' date type. - */ -function exif_date_formats() { -  return array( -  array( -      'type' => 'exif', -      'format' => 'Y:m:d H:i:s', -  ), +function exif_admin_settings_form() { +  _exif_bootstrap(); +  $tags = exif_load_settings(); +  foreach ($tags as $tag) { +    $form['tags']["{$tag->ifd}_{$tag->tag}"]['type'] = array( +      '#type' => 'markup', +      '#value' => PelIfd::getTypeName($tag->ifd), +    ); +    $form['tags']["{$tag->ifd}_{$tag->tag}"]['ifd'] = array( +      '#type' => 'hidden', +      '#value' => $tag->ifd, +    ); +    $form['tags']["{$tag->ifd}_{$tag->tag}"]['tag'] = array( +      '#type' => 'hidden', +      '#value' => $tag->tag, +    ); +    $form['tags']["{$tag->ifd}_{$tag->tag}"]['status'] = array( +      '#type' => 'checkbox', +      '#title' => utf8_encode(PelTag::getTitle($tag->ifd, $tag->tag)), +      '#default_value' => $tag->status, +    ); +    $form['tags']["{$tag->ifd}_{$tag->tag}"]['weight'] = array( +      '#type' => 'weight', +      '#delta' => 10, +      '#default_value' => $tag->weight, +    ); +    $form['tags']["{$tag->ifd}_{$tag->tag}"]['#tree'] = TRUE; +    $form['tags']["{$tag->ifd}_{$tag->tag}"]['#weight'] = $tag->weight; +  } +  $form['buttons']['submit'] = array( +    '#type' => 'submit', +    '#value' => t('Save configuration') +  ); +  $form['buttons']['reset'] = array( +    '#type' => 'submit', +    '#value' => t('Reset to defaults')    ); + +  return $form;  } -/** - * Helper function to handle all date values from exif header. This is - * designed for the date_api and date modules, but is compatible if these - * aren't enabled. - * - * @param array $field - *   The field definition for the matcing exif date - * @param string $exif_date - *   The date extracted from exif header. - * @return array - *   The field value array for delta = 0 - */ -function _exif_date_handler($field, $exif_date) { -  if (! module_exists('date_api')) { -    // Don't bother doing anything if the webmaster doesn't ... -    return array('value' => $exif_date); -  } +function exif_admin_settings_form_submit($form_id, $values) { +  $op = isset($_POST['op']) ? $_POST['op'] : ''; -  require_once drupal_get_path('module', 'date_api') .'/date_api_elements.inc'; -  $date_datetime = date_convert_from_custom($exif_date, variable_get('date_format_exif', 'Y:m:d H:i:s')); -  if (! in_array($field['type'], array('date', 'datetime', 'datestamp'))) { -    // Field is not a date field type, so we return a ISO-8601 representation -    return array('value' => date_convert($date_datetime, DATE_DATETIME, DATE_ISO)); +  if ($op == t('Reset to defaults')) { +    exif_reset_settings(); +    drupal_set_message(t('The configuration options have been reset to their default values.')); +  } +  elseif ($op == t('Save configuration')) { +    exif_save_settings($values); +    drupal_set_message(t('The configuration options have been saved.'));    } - -  // Exif doesn't handles timezones, so we assume the exif date is in the -  // timezone configured for this date field.  This means the exif date needs -  // to be converted to UTC before it's stored. -  $timezone = date_get_timezone($field['tz_handling']); -  $date = date_make_date($date_datetime, $timezone, DATE_DATETIME, $field['granularity']); - -  // Store date offset before converting to UTC as this is lost when setting -  // timezone to 'UTC'. -  $offset = date_offset_get($date); -  date_timezone_set($date, timezone_open('UTC')); - -  // Finally, convert the date object in UTC to a date according to the field -  // type: DATE_ISO, DATE_DATETIME or DATE_UNIX. -  $date_field = date_convert($date, DATE_OBJECT, $field['type']); -  return array( -    'value' => $date_field, -    'value2' => $date_field, -    'timezone' => $timezone, -    'offset' => $offset, -    'offset2' => $offset, -  );  }  /** - * Let's check if this node type contains an image field. - * - * @param $fields fields from this content type - * @return boolean + * Fetch exif data.   */ -function _exif_check_for_exif_data($node_type) { - -  $new_types = array(); -  //fill up array with checked nodetypes -  foreach (variable_get('exif_nodetypes', array()) as $type) { -    if ($type != "0" ) { -      $new_types[] = $type; +function _exif_get_exif($fid) { +  $data = array(); +  if ($result = db_query('SELECT * FROM {exif} WHERE fid = %d', $fid)) { +    while ($row = db_fetch_object($result)) { +      $data[$row->ifd][$row->tag] = $row->value;      }    } -  if (in_array($node_type, $new_types)) { -    return TRUE; -  } -  return FALSE; + +  return $data;  }  /** - * From a given node we are going to get the imagepath of the image. if it's an image node - * it's just going to be images[IMAGE_ORIGINAL]. If it's an imagefield node, we have to go - * through the fields and look if there is an imagefield and then return the path - * - * @param $fields - * @param $node - * @return unknown_type + * Reads exif data from a file.   */ -function _exif_get_image_path($fields, &$node) { -  if ($node->type == 'image') { -    return $node->images[IMAGE_ORIGINAL]; +function _exif_read_exif($file) { +  _exif_bootstrap(); +  $data = array(); +  if (!file_exists($file)) { +    watchdog('exif', t('Image %file not found.', array('%file' => $file)), WATCHDOG_WARNING); +    return $exif;    } - -  foreach ($fields as $field) { -    if ($field['type'] == 'filefield') { -      $tmp = $node->$field['field_name']; -      return $tmp[0]['filepath']; +  if (exif_imagetype($file) != IMAGETYPE_JPEG) { +    return $data; +  } +  $jpeg = new PelJpeg($file); +  $exif = $jpeg->getExif(); +  if (!$exif) { +    return $data; +  } +  $tiff = $exif->getTiff(); +  if (!$tiff) { +    return $data; +  } +  $ifd0 = $tiff->getIfd(); +  if (!$ifd0) { +    return $data; +  } +  $ifds[PelIfd::IFD0] = $ifd0; +  if ($exif = $ifd0->getSubIfd(PelIfd::EXIF)) { +    $ifds[PelIfd::EXIF] = $exif; +  } +  if ($gps = $ifd0->getSubIfd(PelIfd::GPS)) { +    $ifds[PelIfd::GPS] = $gps; +  } +  $tags = exif_get_enabled_tags(); +  $data = array(); +  foreach ($tags as $tag) { +    $entry = $ifds[$tag->ifd]->getEntry($tag->tag); +    if ($entry) { +      $row = array(); +      switch($tag->tag) { +        case PelTag::DATE_TIME: +        case PelTag::DATE_TIME_ORIGINAL: +        case PelTag::DATE_TIME_DIGITIZED: +          // Return a unixtimestamp. Theme will handle date formating. +          $data[$tag->ifd][$tag->tag] = $entry->getValue(); +          break; + +        default: +          $data[$tag->ifd][$tag->tag] = utf8_encode($entry->getText()); +      }      }    } -  return NULL; +  return $data;  } -  /** - * Helper function to reformat fields where required. - * - * Some values (lat/lon) break down into structures, not strings. + * Return an array containing only the tags that were enabled.   */ -function _exif_reformat($data) { -  $date_array = array('datetimeoriginal', 'datetime', 'datetimedigitized'); +function exif_get_enabled_tags() { +  static $tags = array(); -  // Make the key lowercase as CCK field names must be -  $data = array_change_key_case($data, CASE_LOWER); - -  foreach ($data as $key => &$value) { -    if (is_array($value))  { -      $value = array_change_key_case($value, CASE_LOWER); +  if (!count($tags)) { +    $result = db_query('SELECT * FROM {exif_tags} WHERE status = 1'); +    while ($tag = db_fetch_object($result)) { +      $tags[] = $tag;      } - -    // Check for individual keys -    switch ($key) { -      case 'gpslatitude': -        $value = _exif_DMS2D($value, $data['gpslatituderef']); -        break; - -      case 'gpslongitude': -        $value = _exif_DMS2D($value, $data['gpslongituderef']); -        break; - -      case 'gps_gpslatitude': -        $value = _exif_DMS2D($value, $data['gps_gpslatituderef']); -        break; - -      case 'gps_gpslongitude': -        $value = _exif_DMS2D($value, $data['gps_gpslongituderef']); -        break; -          +    if (!count($tags)) { +      // Table is empty, get some defaults +      $tags = exif_get_default_settings(); +      foreach ($tags as $key => $tag) { +        if (!$tag->status) { +          unset($tags[$key]); +        } +      }      } +    usort($tags, '_exif_compare_tags');    } -  return $data; + +  return $tags;  }  /** - * Helper function to change GPS co-ords into decimals. + * Return an array with all the valid tags and their settings.   */ -function _exif_DMS2D($value, $ref) { -  $parts = split('/', $value[0]); -  $dec = (float) ((float) $parts[0] /  (float) $parts[1]); +function exif_load_settings() { +  $tags = exif_get_default_settings(); -  $parts = split('/', $value[1]); -  $dec += (float) (((float) $parts[0] /  (float) $parts[1]) / 60); +  $result = db_query('SELECT * FROM {exif_tags}'); +  while ($tag = db_fetch_object($result)) { +    $tags["{$tag->ifd}_{$tag->tag}"] = $tag; +  } +  usort($tags, '_exif_compare_tags'); -  $parts = split('/', $value[2]); -  $dec += (float) (((float) $parts[0] /  (float) $parts[1]) / 3600); +  return $tags; +} + +function exif_save_settings($values) { +  db_lock_table('exif_tags'); +  foreach ($values as $tag) { +    if (!is_array($tag) || !isset($tag['ifd'])) { +      continue; // Save only appropriate form values +    } +    db_query('DELETE FROM {exif_tags} WHERE ifd = %d AND tag = %d', $tag['ifd'], $tag['tag']); +    db_query('INSERT INTO {exif_tags} (ifd, tag, status, weight) VALUES (%d, %d, %d, %d)', $tag['ifd'], $tag['tag'], $tag['status'], $tag['weight']); +  } +  db_unlock_tables(); +} -  if ($ref == 'S' || $ref == 'W') $dec *= -1; -  return $dec; +function exif_reset_settings() { +  db_query('DELETE FROM {exif_tags}');  }  /** - * Helper function to get the exif class - * @return Exif + * Return an array with all the valid tags, with some useful default settings.   */ -function _exif_get_class() { -  include_once drupal_get_path('module', 'exif') .'/exif.class.php'; -  $exif = Exif::getInstance(); -  return $exif; +function exif_get_default_settings() { +  $tags = exif_get_valid_tags(); +  $tags[PelIfd::EXIF .'_'. PelTag::DATE_TIME_ORIGINAL]->status = 1; +  $tags[PelIfd::EXIF .'_'. PelTag::DATE_TIME_ORIGINAL]->weight = -10; +  $tags[PelIfd::IFD0 .'_'. PelTag::MODEL]->status = 1; +  $tags[PelIfd::IFD0 .'_'. PelTag::MODEL]->weight = -8; +  $tags[PelIfd::EXIF .'_'. PelTag::FOCAL_LENGTH]->status = 1; +  $tags[PelIfd::EXIF .'_'. PelTag::FOCAL_LENGTH]->weight = -6; +  $tags[PelIfd::EXIF .'_'. PelTag::APERTURE_VALUE]->status = 1; +  $tags[PelIfd::EXIF .'_'. PelTag::APERTURE_VALUE]->weight = -4; +  $tags[PelIfd::EXIF .'_'. PelTag::EXPOSURE_TIME]->status = 1; +  $tags[PelIfd::EXIF .'_'. PelTag::EXPOSURE_TIME]->weight = -2; +  $tags[PelIfd::EXIF .'_'. PelTag::ISO_SPEED_RATINGS]->status = 1; +  $tags[PelIfd::EXIF .'_'. PelTag::ISO_SPEED_RATINGS]->weight = 0; +  return $tags;  }  /** - * Implementation of hook_hoken_list - * @param array $type + * Helper function to return all the valid tags (well, at least those this module cares about). + * + * For convenience, each tag has a key in the form: "ifd_tag", where ifd and tag + * are standard Exif ids. Those ids can be found in PelIfd.php and PelTag.php.   */ -function fast_gallery_token_list($type = 'node') { -  if ($type == 'node') { -    $exif = _exif_get_class(); -    $ar_iptc = $exif->getHumanReadableIPTCkey(); -    foreach ($ar_iptc as $iptc) { -      $tokens['iptc']['iptc_' . $iptc] = 'IPTC Field: ' . $iptc; +function exif_get_valid_tags() { +  $valid_tags = array(); +  $valid_tags = array_merge($valid_tags, _exif_get_valid_ifd_tags(PelIfd::IFD0, new PelIfd(PelIfd::IFD0))); +  $valid_tags = array_merge($valid_tags, _exif_get_valid_ifd_tags(PelIfd::EXIF, new PelIfd(PelIfd::EXIF))); +  $valid_tags = array_merge($valid_tags, _exif_get_valid_ifd_tags(PelIfd::GPS, new PelIfd(PelIfd::GPS))); +  return $valid_tags; +} + +function _exif_get_valid_ifd_tags($ifd_id, $ifd) { +  $tags = array(); +  $pel_tags = $ifd->getValidTags(); +  foreach ($pel_tags as $pel_tag) { +    $tag = new StdClass(); +    $tag->ifd = $ifd_id; +    $tag->tag = $pel_tag; +    $tags["{$tag->ifd}_{$tag->tag}"] = $tag; +  } +  return $tags; +} + +function _exif_compare_tags($a, $b) { +  $status = $b->status - $a->status; +  // Separate enabled from disabled. +  if ($status) { +    return $status; +  } +  // Enabled tags +  if ($a->status) { +    $weight = $a->weight - $b->weight; +    if ($weight) { +      return $weight;      } -    return $tokens; +    return $a->ifd - $b->ifd; +  } +  // Disabled tags +  else { +    return $a->ifd - $b->ifd;    }  } -/** - * implementation of hook_token_values - * @param unknown_type $type - * @param unknown_type $object - * @param unknown_type $options - */ -function fast_gallery_token_values($type, $object = NULL, $options = array()) { -  if ($type == 'node') { -    $node = $object; -    $exif = _exif_get_class(); -    $ar_iptc = $exif->getHumanReadableIPTCkey(); - -    $info = content_types($node->type); -    $fields = $info['fields']; -    //get the path to the image -    $image_path = _exif_get_image_path($fields, $node); -     -    //dsm("start reading"); -    $iptc_values = $exif->readIPTCTags($image_path, array(), array('style' => 'fullSmall')); -    //dsm($iptc_values); - -    // TODO: needs to be finished -    foreach ($iptc_values as $key => $iptc) { -      $tokens['iptc_' . $key] = 'IPTC Field: ' . utf8_encode($iptc); +function theme_exif_table($node) { +  _exif_bootstrap(); +  // Retrieve the desired tag values from the file +  $tags = exif_get_enabled_tags(); +  $rows = array(); +  $data = $node->exif_data; + +  foreach ($tags as $tag) { +    if (!empty($data[$tag->ifd][$tag->tag])) { +      $row = array(); +      $row[] = array('data' => check_plain(utf8_encode(PelTag::getTitle($tag->ifd, $tag->tag))), 'class' => 'exif-title'); +      $val = $data[$tag->ifd][$tag->tag]; +      switch($tag->tag) { +        case PelTag::DATE_TIME: +        case PelTag::DATE_TIME_ORIGINAL: +        case PelTag::DATE_TIME_DIGITIZED: +          // Use Drupal's date formatting instead of Pel's +          $row[] = array('data' => format_date($val, 'medium', '', 0), 'class' => 'exif-value'); +          break; + +        default: +          $row[] = array('data' => check_plain($val), 'class' => 'exif-value'); +      } +      $rows[] = $row;      } -    //dsm($tokens); -    return $tokens;    } +<<<<<<< exif.module +} +======= + +  if (empty($rows)) { +    return ''; +  } +  $header = array(array('data' => t('Image information'), 'colspan' => 2)); +  return theme('table', $header, $rows, array('class' => 'exif'));  } + +function theme_exif_admin_settings_form($form) { +  $header = array(t('Tag'), t('Weight'), t('Type')); +  $rows = array(); +  foreach (element_children($form['tags']) as $key) { +    $row = array(); +    $row[] = drupal_render($form['tags'][$key]['status']); +    $row[] = drupal_render($form['tags'][$key]['weight']); +    $row[] = drupal_render($form['tags'][$key]['type']); +    $rows[] = $row; +  } +  $output .= theme('table', $header, $rows, array('class' => 'admin-settings-exif')); +  $output .= drupal_render($form); +  return $output; +} + +function _exif_bootstrap() { +  include_once drupal_get_path('module', 'exif') .'/pel/PelJpeg.php'; +} + +>>>>>>> 1.9 | 
