[ansel] Patch for loading EXIF data on image upload

Heath S. Hendrickson heath at outerspaceconsultants.com
Mon Mar 22 19:30:53 PST 2004


Attached is a super patch that patches the following files:

image.php  (NOTE: patch for watermark mods is also included in here...)
lib/Exif.php
templates/view/exif_image.inc
templates/image/exif.inc

Also included is a new file:

templates/image/exifFields.inc

The patches add the requested TODO capability of writing the EXIF data 
to the datatree backend on image upload...

I set an additional flag of "Exif" to signal that the images Exif data 
had already been processed and written... this way the system can 
automatically determine if the data is in datatree or if it needs to try 
and read it from the image.  At some point it may be worthwhile to write 
a CLI script to process all images in all galleries and write the EXIF 
data to the datatree, but it's not critical as I left in the ability to 
continue reading it from the file.  What may be more important is to 
have it write the data (if not already there) before committing any 
edits to the image file.  That would keep from losing the data before 
it's too late.

As an FYI, the EXIF fields that are written to the datatree are all 
maintained in the new template file (I stripped it out of lib/Exif.php 
to make it one file to maintain so it can be reused elsewhere if 
desired).  I tried to make it have scope over the entire Ansel_ImageData 
class, but you can't have assignments outside of a function (the getText 
stuff) and putting it in a constructor wasn't working.


h
-------------- next part --------------
Index: lib/Exif.php
===================================================================
RCS file: /usr/local/horde/cvs/ansel/lib/Exif.php,v
retrieving revision 1.7
diff -u -r1.7 Exif.php
--- lib/Exif.php	25 Jan 2004 04:32:33 -0000	1.7
+++ lib/Exif.php	23 Mar 2004 03:14:04 -0000
@@ -5,45 +5,18 @@
  * $Horde: ansel/lib/Exif.php,v 1.6 2004/01/19 22:37:54 chuck Exp $
  */
 class Ansel_ImageData {
-
+    
     function readAttributes(&$image)
     {
+        require ANSEL_TEMPLATES . '/image/exifFields.inc';
+
         $imageFile = $image->toFile();
         $result = get_exif_data($imageFile);
+        $output = array();
         if ($result) {
-            // Array of EXIF fields to populate. 
-            // The key is the Exif field name, the value is the display name.
-            $ExifFields = array('Make' => _('Camera Make'), 
-                                'Model' => _('Camera Model'),  
-                                'ImageType' => _('Image Type'),
-                                'FileSize' => _('File Size'),
-                                'DateTime' => _('Image Taken'), 
-                                'ExifImageWidth' => _('Width'), 
-                                'ExifImageLength' => _('Height'), 
-                                'XResolution' => _('X Resolution'),
-                                'YResolution' => _('Y Resolution'),    
-                                'ShutterSpeedValue' => _('Shutter Speed'), 
-                                'ExposureTime' => _('Exposure'), 
-                                'FocalLength' => _('Focal Length'), 
-                                'ApertureValue' => _('Aperture'),
-                                'FNumber' => _('F-Number'), 
-                                'ISOSpeedRatings' => _('ISO Setting'), 
-                                'ExposureBiasValue' => _('Exposure Bias'), 
-                                'ExposureMode' => _('Exposure Mode'),
-                                'MeteringMode' => _('Metering Mode'), 
-                                'Flash' => _('Flash Setting'),
-                                'UserComment' => _('User Comment'), 
-                                'ColorSpace' => _('Color Space'), 
-                                'SensingMethod' => _('Sensing Method'), 
-                                'WhiteBalance' => _('White Balance'), 
-                                'Orientation' => _('Camera Orientation'),
-                                'Copyright' => _('Copyright')
-                                );
 
-            $output = array();
-            $keys = array();
             foreach ($ExifFields as $field => $desc) {
-                array_key_exists($field, $result) ? $data = $result[$field] : $data = '';
+                $data = array_key_exists($field, $result) ? $result[$field] : '';
                 if (trim($data) == '') {
                     continue;
                 }
@@ -56,6 +29,72 @@
         return $output;
     }
 
+    /**
+     * Get the image attributes from the datatree backend.
+     *
+     * @param object DataTreeObject_Image &$image   a reference to the image
+     *
+     * @return array $output    the formated output of the EXIF data
+     */
+    function getAttributes(&$image)
+    {
+        // get the EXIF fields to handle
+        require ANSEL_TEMPLATES . '/image/exifFields.inc';
+        $output = array();
+        
+        foreach ($ExifFields as $field => $desc) {
+            $data = $image->get($field);
+            // make sure it's not an empty field, as this does happen
+            if (trim($data) == '') {
+                continue;
+            }
+            $output[] = "<td class='item'><b>$desc</b>:</td<td class='item'>$data</td>";
+        }
+        return $output;
+    }
+
+    /**
+     * Write the image EXIF data to the datatree backend as a series
+     * of attributes.  The EXIF data being handled is driven by the
+     * multi-dimensional array set up in templates/image/exifFields.inc.
+     *
+     * @param object DataTreeObject_Image &$image  a reference to the image
+     *
+     */
+    function setExifData(&$image)
+    {
+        // get the EXIF fields to handle
+        require ANSEL_TEMPLATES . '/image/exifFields.inc';
+
+        // Unfortunately, the PHP function requires a file, not a stream
+        $imageFile = $image->toFile();
+        $result = get_exif_data($imageFile);
+
+        // see if we got anything from the image file
+        if ($result) {
+
+            // it's easier and faster to work from the fields we know
+            // about instead of all the possible fields stored in the
+            // image file
+            foreach ($ExifFields as $field => $desc) {
+                $data = array_key_exists($field, $result) ? $result[$field] : '';
+                // make sure it's not an empty field, as this does happen
+                if (trim($data) == '') {
+                    continue;
+                }
+                // convert the data to something meaningful
+                if (function_exists('exif_read_data')) {
+                    $data = convert_exif_data($field, $data);
+                }
+                // write it to the datatree backend, forcing the update
+                $image->set($field, $data, true);
+            }
+            // set a marker that we have the EXIF data available in the
+            // datatree backend so we don't have to read it from the file
+            // again.
+            $image->set('Exif', 1, true);
+        }
+    }
 }
 
 //================================================================================================
Index: templates/view/exif-image.inc
===================================================================
RCS file: /usr/local/horde/cvs/ansel/templates/view/exif-image.inc,v
retrieving revision 1.3
diff -u -r1.3 exif-image.inc
--- templates/view/exif-image.inc	25 Jan 2004 19:11:32 -0000	1.3
+++ templates/view/exif-image.inc	23 Mar 2004 03:15:22 -0000
@@ -1,5 +1,11 @@
 <?php
-$output = @Ansel_ImageData::readAttributes($image);
+// see of the EXIF data is in the datatree backend, otherwise
+// we have to read it from the file itself.
+if ($image->get('Exif')) {
+    $output = @Ansel_ImageData::getAttributes($image);
+} else {
+    $output = @Ansel_ImageData::readAttributes($image);
+}
 if (count($output)) {
     $newout = array_chunk($output, 3);
     echo '<br /><div align="center"><table border="0" cellpadding="2" cellspacing="0" class="item">';
Index: templates/image/exif.inc
===================================================================
RCS file: /usr/local/horde/cvs/ansel/templates/image/exif.inc,v
retrieving revision 1.6
diff -u -r1.6 exif.inc
--- templates/image/exif.inc	25 Jan 2004 19:11:31 -0000	1.6
+++ templates/image/exif.inc	23 Mar 2004 03:15:34 -0000
@@ -6,7 +6,13 @@
 </table>
 
 <?php
-$output = @Ansel_ImageData::readAttributes($image);
+// see of the EXIF data is in the datatree backend, otherwise
+// we have to read it from the file itself.
+if ($image->get('Exif')) {
+    $output = @Ansel_ImageData::getAttributes($image);
+} else {
+    $output = @Ansel_ImageData::readAttributes($image);
+}
 if (!count($output)) {
     $out = '<td colspan="2" class="text"><i>' . _("No embedded information found.") . '</i></td>';
 } else {
Index: image.php
===================================================================
RCS file: /usr/local/horde/cvs/ansel/image.php,v
retrieving revision 1.68
diff -u -r1.68 image.php
--- image.php	16 Mar 2004 02:51:17 -0000	1.68
+++ image.php	22 Mar 2004 22:10:05 -0000
@@ -10,6 +10,7 @@
 
 define('ANSEL_BASE', dirname(__FILE__));
 require_once ANSEL_BASE . '/lib/base.php';
+require_once ANSEL_BASE . '/lib/Exif.php';
 require_once HORDE_LIBS . 'Horde/Form.php';
 require_once HORDE_LIBS . 'Horde/Form/Renderer.php';
 require_once HORDE_LIBS . 'Horde/Text.php';
@@ -100,6 +101,23 @@
 
         $w = &$this->addVariable(_("Custom Watermark"), 'watermark', 'text', false, false, null);
         $w->setDefault($prefs->getValue('watermark'));
+
+        $fonts = array('tiny' => _("Tiny"),'small' => _("Small"),'medium' => _("Medium"),'large' => _("Large"),'giant' => _("Giant"));
+        $f = &$this->addVariable(_("Watermark Font"), 'font', 'enum', false, false, null, array($fonts));
+        if ($prefs->getValue('font')) {
+            $default_font = $prefs->getValue('font');
+        } else {
+            $default_font = 'small';
+        }
+        $f->setDefault($default_font);
+
+        $ha = array( 'left' => _('Left'), 'center' => _("Center"), 'right' => _("Right") );
+        $wha = &$this->addVariable(_("Horizontal Alignment"), 'whalign', 'enum', false, false, null, array($ha));
+        $wha->setDefault('right');
+
+        $va = array( 'top' => _('Top'), 'middle' => _("Middle"), 'bottom' => _("Bottom") );
+        $wva = &$this->addVariable(_("Vertical Alignment"), 'wvalign', 'enum', false, false, null, array($va));
+        $wva->setDefault('bottom');
     }
 
 }
@@ -108,7 +126,24 @@
 $gallery_id = Util::getFormData('gallery');
 $image_id = Util::getFormData('image');
 $watermark = Util::getFormData('watermark', $prefs->getValue('watermark'));
+$watermark_halign = Util::getFormData('whalign');
+$watermark_valign = Util::getFormData('wvalign');
+//$watermark_transp = Util::getFormData('wtransp');
+if (isset($watermark)) {
+    require_once HORDE_LIBS . 'Horde/Identity.php';
+    $identity = &Identity::singleton();
+    $name = $identity->getValue('fullname');
+    if (empty($name)) {
+        $name = Auth::getAuth();
+    }
+    // set up array of possible substitutions
+    $watermark_array = array('%N' => $name,   // Users fullname
+                            '%L' => Auth::getAuth());   // user login
+    $watermark = strftime( $watermark );
+    $watermark = str_replace(array_keys($watermark_array), array_values($watermark_array), $watermark);
+}
 $page = Util::getFormData('page', 0);
+$watermark_font = Util::getFormData('font');
 
 /* Redirect to the image list if no action has been requested. */
 if (is_null($actionID)) {
@@ -240,6 +275,8 @@
                                                    );
                                     $image_id = $gallery->addImage($image);
                                     if (!is_a($image_id, 'PEAR_Error')) {
+                                        $tmp = &$ansel_shares->getImage($image_id);
+                                        @Ansel_ImageData::setExifData($tmp);
                                         $success++;
                                     } else {
                                         $notification->push(sprintf(_("There was a problem saving the image: %s"), $image_id), 'horde.error');
@@ -269,6 +306,8 @@
 
                                 $image_id = $gallery->addImage($image);
                                 if (!is_a($image_id, 'PEAR_Error')) {
+                                    $tmp = &$ansel_shares->getImage($image_id);
+                                    @Ansel_ImageData::setExifData($tmp);
                                     $notification->push(_("The image was saved."), 'horde.success');
                                     if ($vars->get('image_default')) {
                                         $gallery->set('default', $image_id, true);
@@ -369,7 +408,7 @@
             break;
 
         case 'watermark':
-            $image->watermark($watermark);
+            $image->watermark($watermark, $watermark_halign, $watermark_valign, $watermark_font);
             break;
         }
 
@@ -405,6 +444,9 @@
     $imageurl = Util::addParameter($imageurl, 'image', $image_id);
     $imageurl = Util::addParameter($imageurl, 'page', $page);
     $imageurl = Util::addParameter($imageurl, 'watermark', $watermark);
+    $imageurl = Util::addParameter($imageurl, 'font', $watermark_font);
+    $imageurl = Util::addParameter($imageurl, 'whalign', $watermark_halign);
+    $imageurl = Util::addParameter($imageurl, 'wvalign', $watermark_valign);
     $url = Horde::applicationUrl(Util::addParameter($imageurl, 'actionID', 'previewwatermark'));
     $url = str_replace( '&amp;', '&', $url);
     Util::closeWindowJS('window.opener.location.href = "' . $url . '";');
@@ -468,7 +510,7 @@
 
 case 'imagewatermark':
     $image = &$ansel_shares->getImageById($image_id);
-    $image->watermark($watermark);
+    $image->watermark($watermark, $watermark_halign, $watermark_valign, $watermark_font);
     $image->display();
     exit;
 
-------------- next part --------------
<?php
$ExifFields = array('Make' => _('Camera Make'), 
                    'Model' => _('Camera Model'),  
                    'ImageType' => _('Image Type'),
                    'FileSize' => _('File Size'),
                    'DateTime' => _('Image Taken'), 
                    'ExifImageWidth' => _('Width'), 
                    'ExifImageLength' => _('Height'), 
                    'XResolution' => _('X Resolution'),
                    'YResolution' => _('Y Resolution'),    
                    'ShutterSpeedValue' => _('Shutter Speed'), 
                    'ExposureTime' => _('Exposure'), 
                    'FocalLength' => _('Focal Length'), 
                    'ApertureValue' => _('Aperture'),
                    'FNumber' => _('F-Number'), 
                    'ISOSpeedRatings' => _('ISO Setting'), 
                    'ExposureBiasValue' => _('Exposure Bias'), 
                    'ExposureMode' => _('Exposure Mode'),
                    'MeteringMode' => _('Metering Mode'), 
                    'Flash' => _('Flash Setting'),
                    'UserComment' => _('User Comment'), 
                    'ColorSpace' => _('Color Space'), 
                    'SensingMethod' => _('Sensing Method'), 
                    'WhiteBalance' => _('White Balance'), 
                    'Orientation' => _('Camera Orientation'),
                    'Copyright' => _('Copyright')
                   );
?>


More information about the ansel mailing list