apps/web/imgsrv/exif.php

Go to the documentation of this file.
00001 #!/usr/local/sbin/php -q
00002 <?php
00003 /*
00004 *! FILE NAME  : exif.php
00005 *! DESCRIPTION: This program collects information about the camera (version, software, sensor)
00006 *! and combines it with the Exif template (default is /etc/Exif_template.xml) to prepare generation
00007 *! of Exif headers.
00008 *! It works in a command line with a single optional parameter - location of the template file and
00009 *! trough the CGI interface. In that case it accepts the following parameter
00010 *! init           - program Exif with default /etc/Exif_template.xml
00011 *! init=path      - program Exif with alternative file
00012 *! noGPS          - don't include GPS-related fields
00013 *! nocompass      - don't include compass-related fields
00014 *! template       - print currently loaded template data (hex dump)
00015 *! metadir        - print currently loaded meta directory that matches variable Exif fields with the template
00016 *! exif=0         - print current Exif page (updated in real time)
00017 *! exif=NNN       - print one of the Exif pages in the buffer (debug feature, current buffer pointer is not known here)
00018 *!
00019 *! Copyright (C) 2007-2008 Elphel, Inc
00020 *! -----------------------------------------------------------------------------**
00021 *!
00022 *!  This program is free software: you can redistribute it and/or modify
00023 *!  it under the terms of the GNU General Public License as published by
00024 *!  the Free Software Foundation, either version 3 of the License, or
00025 *!  (at your option) any later version.
00026 *!
00027 *!  This program is distributed in the hope that it will be useful,
00028 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00029 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00030 *!  GNU General Public License for more details.
00031 *!
00032 *!  You should have received a copy of the GNU General Public License
00033 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00034 *! -----------------------------------------------------------------------------**
00035 *!  $Log: exif.php,v $
00036 *!  Revision 1.1  2008/04/07 09:12:14  elphel
00037 *!  New Exif template generation
00038 *!
00039 *!  $Log: exif.php,v $
00040 *!  Revision 1.1  2008/04/07 09:12:14  elphel
00041 *!  New Exif template generation
00042 *!
00043 *!  Revision 1.1.1.1  2007/10/03 19:05:53  elphel
00044 *!  This is a fresh tree based on elphel353-2.10
00045 *!
00046 *!  Revision 1.6  2007/10/03 19:05:53  elphel
00047 *!  cosmetic
00048 *!
00049 *!  Revision 1.5  2007/10/03 18:37:53  elphel
00050 *!  Made nice html output to see the result data
00051 *!
00052 *!  Revision 1.4  2007/10/03 06:33:31  elphel
00053 *!  fixed wrong copyright year
00054 *!
00055 *!  Revision 1.3  2007/10/02 19:44:03  elphel
00056 *!  minor bug fixes, added "manufacturer note" field for raw frame metadata (36 bytes - /include/asm-cris/c313.h frame_params_t)
00057 *!
00058 *!  Revision 1.2  2007/09/25 23:34:02  elphel
00059 *!  Fixed time strings to the right length
00060 *!
00061 *!  Revision 1.1  2007/09/24 07:27:57  elphel
00062 *!  Started php script that prepares Exif header information for serving images by imgsrv
00063 *!
00064 */
00065 //TODO: Decide with the start sequence, more data is availble after the sensor is initialized.
00066 // Or leave it to imgsrv (it still needs sensor to start first), just put placeholders
00067 // use http://www.exiv2.org/tags.html  for reference of the Exif fields if you need to add modify
00068 // the data below
00069 
00070 $ExifDeviceTemplateFilename="/dev/exif_template";
00071 $ExifDeviceMetadirFilename= "/dev/exif_metadir";
00072 $ExifDeviceExifFilename=    "/dev/exif_exif";
00073 $ExifDeviceMetaFilename=    "/dev/exif_meta";
00074 
00075 
00078 
00079 $ExifXMLName="/etc/Exif_template.xml";
00080 $init=false;
00081 if ($_SERVER['REQUEST_METHOD']=="GET") {
00082   if ($_GET["init"]!==NULL) {
00083     if ($_GET["init"]) $ExifXMLName=$_GET["init"];
00084     $init=true; // in any case - filename specified or not
00085     $noGPS=     ($_GET["noGPS"]!==NULL);
00086     $nocompass= ($_GET["nocompass"]!==NULL);
00087   }
00088 } else {
00089   foreach ($_SERVER['argv'] as $param) if (substr($param,0,4)=="init") {
00090     $param=substr($param,5);
00091     if (strlen($param)>0) $ExifXMLName=$param;
00092     $init=true; //
00093     break;
00094   }
00095   if ($init) {
00096     $noGPS=     in_array  ('noGPS'    , $_SERVER['argv']);
00097     $nocompass= in_array  ('nocompass', $_SERVER['argv']);
00098   } else {
00099     echo <<<USAGE
00100 
00101 Usage: {$_SERVER['argv'][0]} [init[=filename.xml] [noGPS] [nocompass]]
00102 
00103 
00104 USAGE;
00105     exit (0);
00106   }
00107 }
00108 
00109 define("EXIF_BYTE",      1);
00110 define("EXIF_ASCII",     2);
00111 define("EXIF_SHORT",     3);
00112 define("EXIF_LONG",      4);
00113 define("EXIF_RATIONAL",  5);
00114 define("EXIF_SBYTE",     6);
00115 define("EXIF_UNDEFINED", 7);
00116 define("EXIF_SSHORT",    8); //obsolete?
00117 define("EXIF_SLONG",     9);
00118 define("EXIF_SRATIONAL",10);
00119 
00120 define("EXIF_LSEEK_ENABLE", 2); // rebuild buffer
00121 
00123  if ($init) { // configure Exif data
00124    $exif_head= array (
00125           0xff, 0xe1, // APP1 marker
00126 // offset=2 - start of Exif header
00127           0x00, 0x00, // - length of the Exif header (including this length bytes) - we'll fill it later, we do not know it yet
00128           0x45,0x78,0x69,0x66,0x00,0x00); // Exif header
00129    $Exif_length_offset= 2; // put total length here (big endian, 2 bytes)
00130 
00131    $exif_data= array (// start of TIFF Header, data offsets will match indexes in this array
00132           0x4d,0x4d, // (MM) Big endian, MSB goes first in multi-byte data
00133           0x00,0x2a,  // Tag Mark
00134           0x00,0x00,0x00,0x08); //offset to first IDF (from the beginning of the TIFF header, so 8 is minimum)
00135    $xml_exif = simplexml_load_file($ExifXMLName);
00136    if ($xml_exif->GPSInfo) {
00138      if ($nocompass) {
00139         $tounset=array();
00140         foreach ($xml_exif->GPSInfo->children() as $entry) if (strpos  ($entry->getName()  , "Compass" )!==false) $tounset[]=$entry->getName();
00141         foreach ($tounset as $entry) unset ($xml_exif->GPSInfo->{$entry});
00142      }
00143      if ($noGPS) {
00144        unset($xml_exif->GPSInfo);
00145        unset($xml_exif->Image->GPSTag);
00146      }
00147    }
00148 
00149    $IFD_offset=      count($exif_data);
00150    $SUB_IFD_offset=  12*count($xml_exif->Image->children())+2+4+$IFD_offset;
00151    $GPSInfo_offset=  12*count($xml_exif->Photo->children())+2+4+$SUB_IFD_offset;
00152    $data_offset=     $GPSInfo_offset+(($xml_exif->GPSInfo)?(12*count($xml_exif->GPSInfo->children())+2+4):0); //$GPSInfo is optional
00153    if ($_SERVER['REQUEST_METHOD']) {
00154       echo "<pre>";
00155       printf ("IFD_offset=0x%x\n",$IFD_offset);
00156       printf ("SUB_IFD_offset=0x%x\n",$SUB_IFD_offset);
00157       printf ("GPSInfo_offset=0x%x\n",$GPSInfo_offset);
00158       printf ("data_offset=0x%x\n",$data_offset);
00159    }
00160 
00162    foreach ($xml_exif->Image->children()   as $entry) substitute_value($entry);
00163    foreach ($xml_exif->Photo->children()   as $entry) substitute_value($entry);
00164    if ($xml_exif->GPSInfo) {
00165      foreach ($xml_exif->GPSInfo->children() as $entry) substitute_value($entry);
00166    }
00167    $ifd_pointer=$IFD_offset;
00168    $data_pointer=$data_offset;
00169    start_ifd(count($xml_exif->Image->children()));
00170    foreach ($xml_exif->Image->children() as $entry) process_ifd_entry($entry,0);
00171    finish_ifd();
00172 
00173    $ifd_pointer=$SUB_IFD_offset;
00174    start_ifd(count($xml_exif->Photo->children()));
00175    foreach ($xml_exif->Photo->children() as $entry) process_ifd_entry($entry,1);
00176    finish_ifd();
00177 
00178    if ($xml_exif->GPSInfo) {
00179      $ifd_pointer=$GPSInfo_offset;
00180      start_ifd(count($xml_exif->GPSInfo->children()));
00181      foreach ($xml_exif->GPSInfo->children() as $entry) process_ifd_entry($entry,2);
00182      finish_ifd();
00183    }
00184    $exif_len=count($exif_head)+count($exif_data)-$Exif_length_offset;
00185    $exif_head[$Exif_length_offset]=  ($exif_len >> 8) & 0xff;
00186    $exif_head[$Exif_length_offset+1]= $exif_len       & 0xff;
00187 
00188    $Exif_str="";
00189    for ($i=0; $i<count($exif_head);$i++) $Exif_str.= chr ($exif_head[$i]);
00190    for ($i=0; $i<count($exif_data);$i++) $Exif_str.= chr ($exif_data[$i]);
00191 
00192    $Exif_file  = fopen($ExifDeviceTemplateFilename, 'w');
00193    fwrite ($Exif_file,$Exif_str); 
00194    fclose($Exif_file);
00195 
00197    $dir_sequence=array();
00198    $dir_entries=array();
00199 
00200    foreach ($xml_exif->Image->children()   as $entry) addDirEntry($entry);
00201    foreach ($xml_exif->Photo->children()   as $entry) addDirEntry($entry);
00202    if ($xml_exif->GPSInfo) {
00203      foreach ($xml_exif->GPSInfo->children() as $entry) addDirEntry($entry);
00204    }
00205    array_multisort($dir_sequence,$dir_entries);
00206 
00207    $frame_meta_size=0;
00208    for ($i=0;$i<count($dir_entries);$i++) {
00209      $dir_entries[$i]["src"]=$frame_meta_size;
00210      $frame_meta_size+=$dir_entries[$i]["len"];
00211    }
00212 
00213    $Exif_str="";
00214    foreach ($dir_entries as $entry) $Exif_str.=pack("V*",$entry["ltag"],$entry["len"],$entry["src"],$entry["dst"]);
00215    $Exif_meta_file  = fopen($ExifDeviceMetadirFilename, 'w');
00216    fwrite ($Exif_meta_file,$Exif_str); 
00217    fclose($Exif_meta_file);
00218 
00220 
00221    $Exif_file  = fopen($ExifDeviceTemplateFilename, 'w');
00222    fseek ($Exif_file, EXIF_LSEEK_ENABLE, SEEK_END) ;
00223    fclose($Exif_file);
00224 
00225    if ($_SERVER['REQUEST_METHOD']) {
00226      echo "</pre>";
00227    }
00228    if ($_SERVER['REQUEST_METHOD']) {
00229      echo "<hr/>\n";
00230      test_print_header();
00231      echo "<hr/>\n";
00232      test_print_directory();
00233    }
00234  } //if ($init) // configure Exif data
00237     if ($_GET["description"]!==NULL) {
00238 
00240 
00241       $Exif_file  = fopen($ExifDeviceMetadirFilename, 'r');
00242       fseek ($Exif_file, 0, SEEK_END) ;
00243       fseek ($Exif_file, 0, SEEK_SET) ;
00244       $metadir=fread ($Exif_file, 4096);
00245       fclose($Exif_file);
00246       $dir_entries=array();
00247       for ($i=0; $i<strlen($metadir);$i+=16) {
00248         $dir_entries[]=unpack("V*",substr($metadir,$i,16));
00249       }
00250       foreach ($dir_entries as $entry) 
00251         if ($entry[1]==0x010e) {
00252            $descr=$_GET["description"];
00253            $Exif_file  = fopen($ExifDeviceMetaFilename, 'w+');
00254            fseek ($Exif_file, $entry[3], SEEK_SET) ;
00255            $descr_was=fread ($Exif_file, $entry[2]);
00256            $zero=strpos($descr_was,chr(0));
00257            if ($zero!==false) $descr_was=substr($descr_was,0, $zero);
00258            if ($descr) {
00259              $descr= str_pad($descr, $entry[2], chr(0));
00260              fseek ($Exif_file, $entry[3], SEEK_SET) ;
00261              fwrite($Exif_file, $descr,$entry[2]);
00262            }
00263            fclose($Exif_file);
00264            var_dump($descr_was); echo "<br/>\n";
00265            break;
00266         }
00267     }
00269     if ($_GET["template"]!==NULL) {
00270       $Exif_file  = fopen($ExifDeviceTemplateFilename, 'r');
00271       fseek ($Exif_file, 0, SEEK_END) ;
00272       echo "<hr/>\n";
00273       echo "ftell()=".ftell($Exif_file).", ";
00274       fseek ($Exif_file, 0, SEEK_SET) ;
00275       $template=fread ($Exif_file, 4096);
00276       fclose($Exif_file);
00277       echo "read ".strlen($template)." bytes<br/>\n";
00278       hexdump($template);
00279     }
00281     if ($_GET["metadir"]!==NULL) {
00282       $Exif_file  = fopen($ExifDeviceMetadirFilename, 'r');
00283       fseek ($Exif_file, 0, SEEK_END) ;
00284       echo "<hr/>\n";
00285       echo "ftell()=".ftell($Exif_file).", ";
00286       fseek ($Exif_file, 0, SEEK_SET) ;
00287       $metadir=fread ($Exif_file, 4096);
00288       fclose($Exif_file);
00289       echo "read ".strlen($metadir)." bytes<br/>\n";
00290       $dir_entries=array();
00291       for ($i=0; $i<strlen($metadir);$i+=16) {
00292         $dir_entries[]=unpack("V*",substr($metadir,$i,16));
00293       }
00294       print_directory($dir_entries);
00295     }
00297     if ($_GET["exif"]!==NULL) {
00298       $frame=$_GET["exif"]+0;
00299       echo "<hr/>\n";
00300       printf ("Reading frame %d, ",$frame);
00301       $Exif_file  = fopen($ExifDeviceExifFilename, 'r');
00302       fseek ($Exif_file, 1, SEEK_END) ;
00303       $exif_size=ftell($Exif_file);
00304       if ($frame) fseek ($Exif_file, $frame, SEEK_END) ;
00305       else        fseek ($Exif_file, 0, SEEK_SET) ;
00306       echo "ftell()=".ftell($Exif_file).", ";
00307       $exif_data=fread ($Exif_file, $exif_size);
00308       fclose($Exif_file);
00309       echo "read ".strlen($exif_data)." bytes<br/>\n";
00310       hexdump($exif_data);
00311     }
00312  exit(0);
00314 function hexdump($data) {
00315  global $exif_head, $exif_data;
00316    $l=strlen($data);
00317    printf ("<h2>Exif size=%d bytes</h2>\n",$l);
00318    printf ("<table border=\"0\">\n");
00319     for ($i=0; $i<$l;$i=$i+16) {
00320       printf("<tr><td>%03x</td><td>|</td>\n",$i);
00321       for ($j=$i; $j<$i+16;$j++) {
00322         printf("<td>");
00323         if ($j<$l) {
00324           $d=ord($data[$j]);
00325           printf(" %02x",$d);
00326         } else printf ("   ");
00327         printf("</td>");
00328       }
00329       printf("<td>|</td>");
00330       for ($j=$i; $j< ($i+16);$j++) {
00331         printf("<td>");
00332         if ($j<$l) {
00333           $d=ord($data[$j]);
00334           if ($d<32 or $d>126) printf(".");
00335           else printf ("%c",$d);
00336         } else printf (" ");
00337         printf("</td>");
00338 
00339       }
00340       printf("</tr>\n");
00341     }
00342    printf ("</table>");
00343 }
00344 
00345 function print_directory($dir_entries) {
00346    $meta_size=0;
00347    foreach ($dir_entries as $entry)  if (($entry[3]+$entry[2])>$meta_size) $meta_size=$entry[3]+$entry[2];
00348    printf ("<h2>Frame meta data size=%d bytes</h2>\n",$meta_size);
00349    printf ("<table border=\"1\">\n");
00350    printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n");
00351    foreach ($dir_entries as $entry) {
00352      printf ("<tr><td>0x%x</td><td>0x%x</td><td>0x%x</td><td>0x%x</td></tr>\n",$entry[1],$entry[3],$entry[4],$entry[2]);
00353    }
00354    printf ("</table>");
00355 }
00356 
00357 function test_print_header() {
00358  global $exif_head, $exif_data;
00359     $lh=count($exif_head);
00360     $ld=count($exif_data);
00361    printf ("<h2>Exif size=%d bytes (head=%d, data=%d)</h2>\n",$lh+$ld,$lh,$ld);
00362    printf ("<table border=\"0\">\n");
00363     for ($i=0; $i<$lh+$ld;$i=$i+16) {
00364       printf("<tr><td>%03x</td><td>|</td>\n",$i);
00365       for ($j=$i; $j<$i+16;$j++) {
00366         printf("<td>");
00367         if ($j<($lh+$ld)) {
00368           $d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh];
00369           printf(" %02x",$d);
00370         } else printf ("   ");
00371         printf("</td>");
00372       }
00373       printf("<td>|</td>");
00374       for ($j=$i; $j< ($i+16);$j++) {
00375         printf("<td>");
00376         if ($j<($lh+$ld)) {
00377           $d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh];
00378           if ($d<32 or $d>126) printf(".");
00379           else printf ("%c",$d);
00380         } else printf (" ");
00381         printf("</td>");
00382 
00383       }
00384       printf("</tr>\n");
00385     }
00386    printf ("</table>");
00387 }
00388 
00389 function test_print_directory() {
00390   global $dir_entries,$frame_meta_size;
00391    printf ("<h2>Frame meta data size=%d bytes</h2>\n",$frame_meta_size);
00392    printf ("<table border=\"1\">\n");
00393    printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n");
00394    foreach ($dir_entries as $entry)
00395      printf ("<tr><td>0x%x</td><td>0x%x</td><td>0x%x</td><td>0x%x</td></tr>\n",$entry["ltag"],$entry["src"],$entry["dst"],$entry["len"]);
00396    printf ("</table>");
00397 }
00398 
00399 
00400 
00401 
00402 function start_ifd($count) {
00403  global $exif_data, $ifd_pointer;
00404 // printf("start_ifd: ifd_pointer=0x%04x \n", $ifd_pointer);
00405  $exif_data[$ifd_pointer++]= ($count >> 8) & 0xff;
00406  $exif_data[$ifd_pointer++]= $count & 0xff; // may apply & 0xff in the end to all elements
00407 }
00408 function finish_ifd() { // we do not have additional IFDs
00409  global $exif_data, $ifd_pointer;
00410 // printf("finish_ifd: ifd_pointer=0x%04x \n", $ifd_pointer);
00411    $exif_data[$ifd_pointer++]=0;
00412    $exif_data[$ifd_pointer++]=0;
00413    $exif_data[$ifd_pointer++]=0;
00414    $exif_data[$ifd_pointer++]=0;
00415 }
00416 
00417 
00418 //pass2 - building map from frame meta to Exif template
00419 function addDirEntry($ifd_entry) {
00420   global $dir_sequence,$dir_entries,$exif_head;
00421   $lh=count($exif_head);
00422 
00423   $attrs = $ifd_entry->attributes();
00424 //  var_dump($attrs);
00425 //  if  (array_key_exists  ( "seq"  , $attrs  )) {
00426   if  ($attrs["seq"]) {
00427 //     echo $attrs["seq"].;
00428      $dir_sequence[]=((string) $attrs["seq"])+0;
00429      $len= (integer) $ifd_entry->value_length;
00430      $offs=$lh+(integer) $ifd_entry->value_offest;
00431 //     if (array_key_exists  ( "dlen"  , $attrs  )) 
00432      if  ($attrs["dlen"])  $len=min($len,((string) $attrs["dlen"])+0);
00433      $dir_entries[]=array("ltag"=>((integer)$ifd_entry->ltag),"dst"=>$offs,"len"=>$len);
00434   }
00435 }
00436 
00437 function substitute_value($ifd_entry) {
00438  global $SUB_IFD_offset,$GPSInfo_offset;
00439  $attrs = $ifd_entry->attributes();
00440  switch ($attrs["function"]) {
00441    case "BRAND":
00442       $ifd_entry->addChild ('value',exec("bootblocktool -x BRAND"));
00443      break;
00444    case "MODEL":
00445       $ifd_entry->addChild ('value',exec("bootblocktool -x MODEL").exec("bootblocktool -x REVISION"));
00446      break;
00447    case "SOFTWARE":
00448       $ifd_entry->addChild ('value',exec("ls /usr/html/docs/")); // filter
00449      break;
00450    case "SERIAL":
00451       $s=exec("bootblocktool -x SERNO");
00452       $ifd_entry->addChild ('value',substr($s,0,2).":".substr($s,2,2).":".substr($s,4,2).":".substr($s,6,2).":".substr($s,8,2).":".substr($s,10,2));
00453      break;
00454    case "EXIFTAG":
00455       $ifd_entry->addChild ('value',$SUB_IFD_offset);
00456      break;
00457    case "GPSTAG":
00458       $ifd_entry->addChild ('value',$GPSInfo_offset);
00459     break;
00460  }
00461 }
00462 
00463 
00464 function process_ifd_entry($ifd_entry, $group) {
00465  global $exif_data, $ifd_pointer, $data_pointer,$SUB_IFD_offset,$GPSInfo_offset;
00466  $attrs = $ifd_entry->attributes();
00467  $ifd_tag=   ((string) $attrs["tag"])+0;
00468  $ifd_format=constant("EXIF_".$attrs["format"]);
00469  $ifd_count= $attrs["count"];
00470 // echo "\nifd_tag=$ifd_tag, entry=";print_r($ifd_entry);
00471 // echo "\nifd_count=$ifd_count";
00472 // echo "\nifd_bytes:";var_dump($ifd_bytes);
00473  if (!$ifd_count) {
00474    if($ifd_format==EXIF_ASCII) $ifd_count=strlen($ifd_entry->value)+1;
00475    else $ifd_count=1 ; 
00476  }
00477 //echo "\nifd_count=$ifd_count";
00478  $exif_data[$ifd_pointer++]= ($ifd_tag    >>  8)  & 0xff;
00479  $exif_data[$ifd_pointer++]=  $ifd_tag            & 0xff;
00480  $exif_data[$ifd_pointer++]= ($ifd_format >>  8 ) & 0xff;
00481  $exif_data[$ifd_pointer++]=  $ifd_format         & 0xff;
00482  $exif_data[$ifd_pointer++]= ($ifd_count >> 24)  & 0xff;
00483  $exif_data[$ifd_pointer++]= ($ifd_count >> 16)  & 0xff;
00484  $exif_data[$ifd_pointer++]= ($ifd_count >>  8)   & 0xff;
00485  $exif_data[$ifd_pointer++]=  $ifd_count          & 0xff;
00486 
00487  $ifd_bytes=0;
00488  switch ($ifd_format) {
00489   case EXIF_SHORT:
00490   case EXIF_SSHORT:    $ifd_bytes=2; break;
00491   case EXIF_LONG:
00492   case EXIF_SLONG:     $ifd_bytes=4; break;
00493   case EXIF_RATIONAL:
00494   case EXIF_SRATIONAL: $ifd_bytes=8; break;
00495   default: $ifd_bytes=1; //1,2,6,7
00496  }
00497  $ifd_bytes=$ifd_bytes*$ifd_count;
00498 // now prepare ifd_data - array of bytes
00499  switch ($ifd_format) {
00500   case EXIF_BYTE:
00501   case EXIF_SBYTE:
00502           $ifd_data= array ();
00503           foreach ($ifd_entry->value as $a) $ifd_data[]= $a & 0xff;
00504           break;
00505   case EXIF_ASCII:
00506           $ifd_data= str_split($ifd_entry->value);
00507           foreach($ifd_data as &$d) $d=ord($d);
00508           break;
00509   case EXIF_SHORT:
00510   case EXIF_SSHORT:
00511           $ifd_data= array ();
00512           foreach ($ifd_entry->value as $a) $ifd_data=array_merge($ifd_data,array(($a >> 8) & 0xff, $a & 0xff));
00513           break;
00514   case EXIF_LONG:
00515   case EXIF_SLONG:
00516           $ifd_data= array ();
00517           foreach ($ifd_entry->value as $a) $ifd_data=array_merge($ifd_data,array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff));
00518           break;
00519   case EXIF_RATIONAL:
00520   case EXIF_SRATIONAL:
00521           $nom= array ();
00522           foreach ($ifd_entry->nominator as $a)   $nom[]=  array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff);
00523           $denom= array ();
00524           foreach ($ifd_entry->denominator as $a) $denom[]=array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff);
00525           $ifd_data= array ();
00526 /*
00527 var_dump($nom);
00528 echo "\n";
00529 var_dump($denom);
00530 echo "\n";
00531 //exit(0);
00532 */
00533           for ($i=0;$i<count($nom);$i++) {
00534 //            echo "i=$i\n";
00535   //          echo "\nnom=";var_dump($nom[$i]);
00536     //        echo "\ndenom=";var_dump($denom[$i]);
00537             $ifd_data=array_merge($ifd_data,$nom[$i],$denom[$i]);
00538           }
00539           break; // rational, (un)signed
00540 
00541   case EXIF_UNDEFINED: // undefined
00542        $ifd_data= array_fill(0,$ifd_bytes,0); // will just fill with "0"-s
00543        break; 
00544  }
00545 // echo "\nifd_tag=$ifd_tag, entry=";print_r($i=$ifd_entry->value);
00546 // echo "\nifd_data:";var_dump($ifd_data);
00547 // echo "\nifd_bytes:";var_dump($ifd_bytes);
00548 
00549  $ifd_data=array_pad($ifd_data,$ifd_bytes,0); 
00550 
00551  $ifd_entry->addChild ('value_length',count($ifd_data));
00552 // if  (array_key_exists  ( "ltag"  , $attrs  )) $ltag= ((string) $attrs["ltag"])+0;
00553  if  ($attr["ltag"]) $ltag= ((string) $attrs["ltag"])+0;
00554  else  $ltag= $ifd_tag+($group<<16) ;
00555  $ifd_entry->addChild ("ltag",$ltag );
00556  if (count($ifd_data) <=4) {
00557      $ifd_entry->addChild ('value_offest',$ifd_pointer);
00558      $ifd_data= array_pad($ifd_data,-4,0); // add leading zeroes if <4 bytes
00559      for ($i=0;$i<4;$i++)   $exif_data[$ifd_pointer++]=$ifd_data[$i];
00560  } else { //pointer, not data
00561      $ifd_entry->addChild ('value_offest',$data_pointer);
00562      $exif_data[$ifd_pointer++]= ($data_pointer >> 24)  & 0xff;
00563      $exif_data[$ifd_pointer++]= ($data_pointer >> 16)  & 0xff;
00564      $exif_data[$ifd_pointer++]= ($data_pointer >>  8)  & 0xff;
00565      $exif_data[$ifd_pointer++]=  $data_pointer         & 0xff;
00566      for ($i=0;$i<count($ifd_data);$i++)  {
00567        $exif_data[$data_pointer++]=$ifd_data[$i];
00568      }
00569  }
00570 }
00571 
00572 ?> 

Generated on Thu Aug 7 16:18:59 2008 for elphel by  doxygen 1.5.1