Commit a3eb9430 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Edit two Exif fields

HostComputer exif field containing serial number was replaced with more
suitable CameraSerialNumber. IPTCNAA field containing frame number was
replaced with ImageNumber.
parent 6393936e
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
dlen: length of a variable data field, stored in frame buffer dlen: length of a variable data field, stored in frame buffer
ltag: Exif_tag+(group<<16). If specified, is used by the software, while the Exif output will still have tag ltag: Exif_tag+(group<<16). If specified, is used by the software, while the Exif output will still have tag
SubSecTimeOriginal should go immediately after DateTimeOriginal (in the sequence numbers, not in the Exif templete) SubSecTimeOriginal should go immediately after DateTimeOriginal (in the sequence numbers, not in the Exif templete)
Update, June 2016: PageNumber field is used as sensor port number, HostComputer field is replaced with CameraSerialNumber and
FrameNumber field (which actually was IPTCNAA field) is replaced with standart ImageNumber field.
--> -->
<Exif> <Exif>
<Image> <Image>
...@@ -22,8 +25,8 @@ ...@@ -22,8 +25,8 @@
<DateTime tag="0x0132" format="ASCII" count="20" seq="1" dlen="20"> <DateTime tag="0x0132" format="ASCII" count="20" seq="1" dlen="20">
<value>2001:06:21 12:00:00</value> <value>2001:06:21 12:00:00</value>
</DateTime> </DateTime>
<HostComputer tag="0x013c" format="ASCII" function="SERIAL"/> <CameraSerialNumber tag="0xc62f" format="ASCII" function="SERIAL"/>
<FrameNumber tag="0x83bb" format="LONG" count="1" seq="25" dlen="4"/> <ImageNumber tag="0x9211" format="LONG" count="1" seq="25" dlen="4"/>
<Orientation tag="0x112" format="SHORT" count="1" seq="27" dlen="2"/> <Orientation tag="0x112" format="SHORT" count="1" seq="27" dlen="2"/>
<PageNumber tag="0x129" format="SHORT" count="1" seq="28" dlen="2"/> <PageNumber tag="0x129" format="SHORT" count="1" seq="28" dlen="2"/>
<ExifTag tag="0x8769" format="LONG" function="EXIFTAG"/> <ExifTag tag="0x8769" format="LONG" function="EXIFTAG"/>
......
#!/usr/local/sbin/php -q #!/usr/bin/env php
<?php <?php
/*! /*!
*! FILE NAME : exif.php *! FILE NAME : exif.php
*! DESCRIPTION: This program collects information about the camera (version, software, sensor) *! DESCRIPTION: This program collects information about the camera (version, software, sensor)
*! and combines it with the Exif template (default is /etc/Exif_template.xml) to prepare generation *! and combines it with the Exif template (default is /etc/Exif_template.xml) to prepare generation
*! of Exif headers. *! of Exif headers.
*! It works in a command line with a single optional parameter - location of the template file and *! It works in a command line with a single optional parameter - location of the template file and
*! trough the CGI interface. In that case it accepts the following parameter *! trough the CGI interface. In that case it accepts the following parameter
*! init - program Exif with default /etc/Exif_template.xml *! init - program Exif with default /etc/Exif_template.xml
*! init=path - program Exif with alternative file *! init=path - program Exif with alternative file
*! noGPS - don't include GPS-related fields *! noGPS - don't include GPS-related fields
*! nocompass - don't include compass-related fields *! nocompass - don't include compass-related fields
*! template - print currently loaded template data (hex dump) *! template - print currently loaded template data (hex dump)
*! metadir - print currently loaded meta directory that matches variable Exif fields with the template *! metadir - print currently loaded meta directory that matches variable Exif fields with the template
*! exif=0 - print current Exif page (updated in real time) *! exif=0 - print current Exif page (updated in real time)
*! exif=NNN - print one of the Exif pages in the buffer (debug feature, current buffer pointer is not known here) *! exif=NNN - print one of the Exif pages in the buffer (debug feature, current buffer pointer is not known here)
*! *!
*! Copyright (C) 2007-2008 Elphel, Inc *! Copyright (C) 2007-2016 Elphel, Inc
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! This program is free software: you can redistribute it and/or modify *! 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 *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! $Log: exif.php,v $ *! $Log: exif.php,v $
*! Revision 1.2 2010/08/10 21:14:31 elphel *! Revision 1.2 2010/08/10 21:14:31 elphel
*! 8.0.8.39 - added EEPROM support for multiplexor and sensor boards, so autocampars.php uses application-specific defaults. Exif Orientation tag support, camera Model reflects application and optional mode (i.e. camera number in Eyesis) *! 8.0.8.39 - added EEPROM support for multiplexor and sensor boards, so autocampars.php uses application-specific defaults. Exif Orientation tag support, camera Model reflects application and optional mode (i.e. camera number in Eyesis)
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.2 2008/08/11 19:11:32 elphel *! Revision 1.2 2008/08/11 19:11:32 elphel
*! comments *! comments
*! *!
*! Revision 1.1 2008/04/07 09:12:14 elphel *! Revision 1.1 2008/04/07 09:12:14 elphel
*! New Exif template generation *! New Exif template generation
*! *!
*! $Log: exif.php,v $ *! $Log: exif.php,v $
*! Revision 1.2 2010/08/10 21:14:31 elphel *! Revision 1.2 2010/08/10 21:14:31 elphel
*! 8.0.8.39 - added EEPROM support for multiplexor and sensor boards, so autocampars.php uses application-specific defaults. Exif Orientation tag support, camera Model reflects application and optional mode (i.e. camera number in Eyesis) *! 8.0.8.39 - added EEPROM support for multiplexor and sensor boards, so autocampars.php uses application-specific defaults. Exif Orientation tag support, camera Model reflects application and optional mode (i.e. camera number in Eyesis)
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.2 2008/08/11 19:11:32 elphel *! Revision 1.2 2008/08/11 19:11:32 elphel
*! comments *! comments
*! *!
*! Revision 1.1 2008/04/07 09:12:14 elphel *! Revision 1.1 2008/04/07 09:12:14 elphel
*! New Exif template generation *! New Exif template generation
*! *!
*! Revision 1.1.1.1 2007/10/03 19:05:53 elphel *! Revision 1.1.1.1 2007/10/03 19:05:53 elphel
*! This is a fresh tree based on elphel353-2.10 *! This is a fresh tree based on elphel353-2.10
*! *!
*! Revision 1.6 2007/10/03 19:05:53 elphel *! Revision 1.6 2007/10/03 19:05:53 elphel
*! cosmetic *! cosmetic
*! *!
*! Revision 1.5 2007/10/03 18:37:53 elphel *! Revision 1.5 2007/10/03 18:37:53 elphel
*! Made nice html output to see the result data *! Made nice html output to see the result data
*! *!
*! Revision 1.4 2007/10/03 06:33:31 elphel *! Revision 1.4 2007/10/03 06:33:31 elphel
*! fixed wrong copyright year *! fixed wrong copyright year
*! *!
*! Revision 1.3 2007/10/02 19:44:03 elphel *! Revision 1.3 2007/10/02 19:44:03 elphel
*! minor bug fixes, added "manufacturer note" field for raw frame metadata (36 bytes - /include/asm-cris/c313.h frame_params_t) *! minor bug fixes, added "manufacturer note" field for raw frame metadata (36 bytes - /include/asm-cris/c313.h frame_params_t)
*! *!
*! Revision 1.2 2007/09/25 23:34:02 elphel *! Revision 1.2 2007/09/25 23:34:02 elphel
*! Fixed time strings to the right length *! Fixed time strings to the right length
*! *!
*! Revision 1.1 2007/09/24 07:27:57 elphel *! Revision 1.1 2007/09/24 07:27:57 elphel
*! Started php script that prepares Exif header information for serving images by imgsrv *! Started php script that prepares Exif header information for serving images by imgsrv
*! *!
*/ */
//TODO: Decide with the start sequence, more data is availble after the sensor is initialized. //TODO: Decide with the start sequence, more data is availble after the sensor is initialized.
// Or leave it to imgsrv (it still needs sensor to start first), just put placeholders // Or leave it to imgsrv (it still needs sensor to start first), just put placeholders
// use http://www.exiv2.org/tags.html for reference of the Exif fields if you need to add modify // use http://www.exiv2.org/tags.html for reference of the Exif fields if you need to add modify
...@@ -90,6 +90,10 @@ $ExifDeviceMetadirFilename= "/dev/exif_metadir"; ...@@ -90,6 +90,10 @@ $ExifDeviceMetadirFilename= "/dev/exif_metadir";
$ExifDeviceExifFilename= "/dev/exif_exif"; $ExifDeviceExifFilename= "/dev/exif_exif";
$ExifDeviceMetaFilename= "/dev/exif_meta"; $ExifDeviceMetaFilename= "/dev/exif_meta";
$DeviceSNFilename = "/sys/devices/soc0/elphel393-init/serial";
$DeviceRevisionFilename = "/sys/devices/soc0/elphel393-init/revision";
$DeviceBrand = "Elphel";
$DeviceModel = "Elphel393";
//! if called from the command line - accepts just one parameter - configuration file, //! if called from the command line - accepts just one parameter - configuration file,
//! through CGI - accepts more parameters //! through CGI - accepts more parameters
...@@ -97,31 +101,31 @@ $ExifDeviceMetaFilename= "/dev/exif_meta"; ...@@ -97,31 +101,31 @@ $ExifDeviceMetaFilename= "/dev/exif_meta";
$ExifXMLName="/etc/Exif_template.xml"; $ExifXMLName="/etc/Exif_template.xml";
$init=false; $init=false;
if ($_SERVER['REQUEST_METHOD']=="GET") { if ($_SERVER['REQUEST_METHOD']=="GET") {
if ($_GET["init"]!==NULL) { if ($_GET["init"]!==NULL) {
if ($_GET["init"]) $ExifXMLName=$_GET["init"]; if ($_GET["init"]) $ExifXMLName=$_GET["init"];
$init=true; // in any case - filename specified or not $init=true; // in any case - filename specified or not
$noGPS= ($_GET["noGPS"]!==NULL); $noGPS= ($_GET["noGPS"]!==NULL);
$nocompass= ($_GET["nocompass"]!==NULL); $nocompass= ($_GET["nocompass"]!==NULL);
} }
} else { } else {
foreach ($_SERVER['argv'] as $param) if (substr($param,0,4)=="init") { foreach ($_SERVER['argv'] as $param) if (substr($param,0,4)=="init") {
$param=substr($param,5); $param=substr($param,5);
if (strlen($param)>0) $ExifXMLName=$param; if (strlen($param)>0) $ExifXMLName=$param;
$init=true; // $init=true; //
break; break;
} }
if ($init) { if ($init) {
$noGPS= in_array ('noGPS' , $_SERVER['argv']); $noGPS= in_array ('noGPS' , $_SERVER['argv']);
$nocompass= in_array ('nocompass', $_SERVER['argv']); $nocompass= in_array ('nocompass', $_SERVER['argv']);
} else { } else {
echo <<<USAGE echo <<<USAGE
Usage: {$_SERVER['argv'][0]} [init[=filename.xml] [noGPS] [nocompass]] Usage: {$_SERVER['argv'][0]} [init[=filename.xml] [noGPS] [nocompass]]
USAGE; USAGE;
exit (0); exit (0);
} }
} }
define("EXIF_BYTE", 1); define("EXIF_BYTE", 1);
...@@ -138,464 +142,468 @@ define("EXIF_SRATIONAL",10); ...@@ -138,464 +142,468 @@ define("EXIF_SRATIONAL",10);
define("EXIF_LSEEK_ENABLE", 2); // rebuild buffer define("EXIF_LSEEK_ENABLE", 2); // rebuild buffer
/// ===== init/init= CGI parameters or command line mode ======= /// ===== init/init= CGI parameters or command line mode =======
if ($init) { // configure Exif data if ($init) { // configure Exif data
$exif_head= array ( $exif_head= array (
0xff, 0xe1, // APP1 marker 0xff, 0xe1, // APP1 marker
// offset=2 - start of Exif header // offset=2 - start of Exif header
0x00, 0x00, // - length of the Exif header (including this length bytes) - we'll fill it later, we do not know it yet 0x00, 0x00, // - length of the Exif header (including this length bytes) - we'll fill it later, we do not know it yet
0x45,0x78,0x69,0x66,0x00,0x00); // Exif header 0x45,0x78,0x69,0x66,0x00,0x00); // Exif header
$Exif_length_offset= 2; // put total length here (big endian, 2 bytes) $Exif_length_offset= 2; // put total length here (big endian, 2 bytes)
$exif_data= array (// start of TIFF Header, data offsets will match indexes in this array $exif_data= array (// start of TIFF Header, data offsets will match indexes in this array
0x4d,0x4d, // (MM) Big endian, MSB goes first in multi-byte data 0x4d,0x4d, // (MM) Big endian, MSB goes first in multi-byte data
0x00,0x2a, // Tag Mark 0x00,0x2a, // Tag Mark
0x00,0x00,0x00,0x08); //offset to first IDF (from the beginning of the TIFF header, so 8 is minimum) 0x00,0x00,0x00,0x08); //offset to first IDF (from the beginning of the TIFF header, so 8 is minimum)
$xml_exif = simplexml_load_file($ExifXMLName); $xml_exif = simplexml_load_file($ExifXMLName);
if ($xml_exif->GPSInfo) { if ($xml_exif->GPSInfo) {
/// remove all tags named "Compass..." /// remove all tags named "Compass..."
if ($nocompass) { if ($nocompass) {
$tounset=array(); $tounset=array();
foreach ($xml_exif->GPSInfo->children() as $entry) if (strpos ($entry->getName() , "Compass" )!==false) $tounset[]=$entry->getName(); foreach ($xml_exif->GPSInfo->children() as $entry) if (strpos ($entry->getName() , "Compass" )!==false) $tounset[]=$entry->getName();
foreach ($tounset as $entry) unset ($xml_exif->GPSInfo->{$entry}); foreach ($tounset as $entry) unset ($xml_exif->GPSInfo->{$entry});
} }
if ($noGPS) { if ($noGPS) {
unset($xml_exif->GPSInfo); unset($xml_exif->GPSInfo);
unset($xml_exif->Image->GPSTag); unset($xml_exif->Image->GPSTag);
} }
} }
$IFD_offset= count($exif_data); $IFD_offset= count($exif_data);
$SUB_IFD_offset= 12*count($xml_exif->Image->children())+2+4+$IFD_offset; $SUB_IFD_offset= 12*count($xml_exif->Image->children())+2+4+$IFD_offset;
$GPSInfo_offset= 12*count($xml_exif->Photo->children())+2+4+$SUB_IFD_offset; $GPSInfo_offset= 12*count($xml_exif->Photo->children())+2+4+$SUB_IFD_offset;
$data_offset= $GPSInfo_offset+(($xml_exif->GPSInfo)?(12*count($xml_exif->GPSInfo->children())+2+4):0); //$GPSInfo is optional $data_offset= $GPSInfo_offset+(($xml_exif->GPSInfo)?(12*count($xml_exif->GPSInfo->children())+2+4):0); //$GPSInfo is optional
if ($_SERVER['REQUEST_METHOD']) { if ($_SERVER['REQUEST_METHOD']) {
echo "<pre>"; echo "<pre>";
printf ("IFD_offset=0x%x\n",$IFD_offset); printf ("IFD_offset=0x%x\n",$IFD_offset);
printf ("SUB_IFD_offset=0x%x\n",$SUB_IFD_offset); printf ("SUB_IFD_offset=0x%x\n",$SUB_IFD_offset);
printf ("GPSInfo_offset=0x%x\n",$GPSInfo_offset); printf ("GPSInfo_offset=0x%x\n",$GPSInfo_offset);
printf ("data_offset=0x%x\n",$data_offset); printf ("data_offset=0x%x\n",$data_offset);
} }
/// Now modify variable fields substituting values /// Now modify variable fields substituting values
foreach ($xml_exif->Image->children() as $entry) substitute_value($entry); foreach ($xml_exif->Image->children() as $entry) substitute_value($entry);
foreach ($xml_exif->Photo->children() as $entry) substitute_value($entry); foreach ($xml_exif->Photo->children() as $entry) substitute_value($entry);
if ($xml_exif->GPSInfo) { if ($xml_exif->GPSInfo) {
foreach ($xml_exif->GPSInfo->children() as $entry) substitute_value($entry); foreach ($xml_exif->GPSInfo->children() as $entry) substitute_value($entry);
} }
$ifd_pointer=$IFD_offset; $ifd_pointer=$IFD_offset;
$data_pointer=$data_offset; $data_pointer=$data_offset;
start_ifd(count($xml_exif->Image->children())); start_ifd(count($xml_exif->Image->children()));
foreach ($xml_exif->Image->children() as $entry) process_ifd_entry($entry,0); foreach ($xml_exif->Image->children() as $entry) process_ifd_entry($entry,0);
finish_ifd(); finish_ifd();
$ifd_pointer=$SUB_IFD_offset; $ifd_pointer=$SUB_IFD_offset;
start_ifd(count($xml_exif->Photo->children())); start_ifd(count($xml_exif->Photo->children()));
foreach ($xml_exif->Photo->children() as $entry) process_ifd_entry($entry,1); foreach ($xml_exif->Photo->children() as $entry) process_ifd_entry($entry,1);
finish_ifd(); finish_ifd();
if ($xml_exif->GPSInfo) { if ($xml_exif->GPSInfo) {
$ifd_pointer=$GPSInfo_offset; $ifd_pointer=$GPSInfo_offset;
start_ifd(count($xml_exif->GPSInfo->children())); start_ifd(count($xml_exif->GPSInfo->children()));
foreach ($xml_exif->GPSInfo->children() as $entry) process_ifd_entry($entry,2); foreach ($xml_exif->GPSInfo->children() as $entry) process_ifd_entry($entry,2);
finish_ifd(); finish_ifd();
} }
$exif_len=count($exif_head)+count($exif_data)-$Exif_length_offset; $exif_len=count($exif_head)+count($exif_data)-$Exif_length_offset;
$exif_head[$Exif_length_offset]= ($exif_len >> 8) & 0xff; $exif_head[$Exif_length_offset]= ($exif_len >> 8) & 0xff;
$exif_head[$Exif_length_offset+1]= $exif_len & 0xff; $exif_head[$Exif_length_offset+1]= $exif_len & 0xff;
$Exif_str=""; $Exif_str="";
for ($i=0; $i<count($exif_head);$i++) $Exif_str.= chr ($exif_head[$i]); for ($i=0; $i<count($exif_head);$i++) $Exif_str.= chr ($exif_head[$i]);
for ($i=0; $i<count($exif_data);$i++) $Exif_str.= chr ($exif_data[$i]); for ($i=0; $i<count($exif_data);$i++) $Exif_str.= chr ($exif_data[$i]);
$Exif_file = fopen($ExifDeviceTemplateFilename, 'w'); $Exif_file = fopen($ExifDeviceTemplateFilename, 'w');
fwrite ($Exif_file,$Exif_str); /// will disable and invalidate Exif data fwrite ($Exif_file,$Exif_str); /// will disable and invalidate Exif data
fclose($Exif_file); fclose($Exif_file);
///Exif template is done, now we need a directory to map frame meta data to fields in the template. ///Exif template is done, now we need a directory to map frame meta data to fields in the template.
$dir_sequence=array(); $dir_sequence=array();
$dir_entries=array(); $dir_entries=array();
foreach ($xml_exif->Image->children() as $entry) addDirEntry($entry); foreach ($xml_exif->Image->children() as $entry) addDirEntry($entry);
foreach ($xml_exif->Photo->children() as $entry) addDirEntry($entry); foreach ($xml_exif->Photo->children() as $entry) addDirEntry($entry);
if ($xml_exif->GPSInfo) { if ($xml_exif->GPSInfo) {
foreach ($xml_exif->GPSInfo->children() as $entry) addDirEntry($entry); foreach ($xml_exif->GPSInfo->children() as $entry) addDirEntry($entry);
} }
array_multisort($dir_sequence,$dir_entries); array_multisort($dir_sequence,$dir_entries);
$frame_meta_size=0; $frame_meta_size=0;
for ($i=0;$i<count($dir_entries);$i++) { for ($i=0;$i<count($dir_entries);$i++) {
$dir_entries[$i]["src"]=$frame_meta_size; $dir_entries[$i]["src"]=$frame_meta_size;
$frame_meta_size+=$dir_entries[$i]["len"]; $frame_meta_size+=$dir_entries[$i]["len"];
} }
$Exif_str=""; $Exif_str="";
foreach ($dir_entries as $entry) $Exif_str.=pack("V*",$entry["ltag"],$entry["len"],$entry["src"],$entry["dst"]); foreach ($dir_entries as $entry) $Exif_str.=pack("V*",$entry["ltag"],$entry["len"],$entry["src"],$entry["dst"]);
$Exif_meta_file = fopen($ExifDeviceMetadirFilename, 'w'); $Exif_meta_file = fopen($ExifDeviceMetadirFilename, 'w');
fwrite ($Exif_meta_file,$Exif_str); /// will disable and invalidate Exif data fwrite ($Exif_meta_file,$Exif_str); /// will disable and invalidate Exif data
fclose($Exif_meta_file); fclose($Exif_meta_file);
///Rebuild buffer and enable Exif generation/output: ///Rebuild buffer and enable Exif generation/output:
$Exif_file = fopen($ExifDeviceTemplateFilename, 'w'); $Exif_file = fopen($ExifDeviceTemplateFilename, 'w');
fseek ($Exif_file, EXIF_LSEEK_ENABLE, SEEK_END) ; fseek ($Exif_file, EXIF_LSEEK_ENABLE, SEEK_END) ;
fclose($Exif_file); fclose($Exif_file);
if ($_SERVER['REQUEST_METHOD']) { if ($_SERVER['REQUEST_METHOD']) {
echo "</pre>"; echo "</pre>";
} }
if ($_SERVER['REQUEST_METHOD']) { if ($_SERVER['REQUEST_METHOD']) {
echo "<hr/>\n"; echo "<hr/>\n";
test_print_header(); test_print_header();
echo "<hr/>\n"; echo "<hr/>\n";
test_print_directory(); test_print_directory();
} }
} //if ($init) // configure Exif data } //if ($init) // configure Exif data
/// ===== processing optional parameters ======= /// ===== processing optional parameters =======
/// ===== read template ======= /// ===== read template =======
if ($_GET["description"]!==NULL) { if ($_GET["description"]!==NULL) {
/// Read metadir to find the length of the description field /// Read metadir to find the length of the description field
$Exif_file = fopen($ExifDeviceMetadirFilename, 'r'); $Exif_file = fopen($ExifDeviceMetadirFilename, 'r');
fseek ($Exif_file, 0, SEEK_END) ; fseek ($Exif_file, 0, SEEK_END) ;
fseek ($Exif_file, 0, SEEK_SET) ; fseek ($Exif_file, 0, SEEK_SET) ;
$metadir=fread ($Exif_file, 4096); $metadir=fread ($Exif_file, 4096);
fclose($Exif_file); fclose($Exif_file);
$dir_entries=array(); $dir_entries=array();
for ($i=0; $i<strlen($metadir);$i+=16) { for ($i=0; $i<strlen($metadir);$i+=16) {
$dir_entries[]=unpack("V*",substr($metadir,$i,16)); $dir_entries[]=unpack("V*",substr($metadir,$i,16));
} }
foreach ($dir_entries as $entry) foreach ($dir_entries as $entry)
if ($entry[1]==0x010e) { if ($entry[1]==0x010e) {
$descr=$_GET["description"]; $descr=$_GET["description"];
$Exif_file = fopen($ExifDeviceMetaFilename, 'w+'); $Exif_file = fopen($ExifDeviceMetaFilename, 'w+');
fseek ($Exif_file, $entry[3], SEEK_SET) ; fseek ($Exif_file, $entry[3], SEEK_SET) ;
$descr_was=fread ($Exif_file, $entry[2]); $descr_was=fread ($Exif_file, $entry[2]);
$zero=strpos($descr_was,chr(0)); $zero=strpos($descr_was,chr(0));
if ($zero!==false) $descr_was=substr($descr_was,0, $zero); if ($zero!==false) $descr_was=substr($descr_was,0, $zero);
if ($descr) { if ($descr) {
$descr= str_pad($descr, $entry[2], chr(0)); $descr= str_pad($descr, $entry[2], chr(0));
fseek ($Exif_file, $entry[3], SEEK_SET) ; fseek ($Exif_file, $entry[3], SEEK_SET) ;
fwrite($Exif_file, $descr,$entry[2]); fwrite($Exif_file, $descr,$entry[2]);
} }
fclose($Exif_file); fclose($Exif_file);
var_dump($descr_was); echo "<br/>\n"; var_dump($descr_was); echo "<br/>\n";
break; break;
} }
} }
/// ===== read template ======= /// ===== read template =======
if ($_GET["template"]!==NULL) { if ($_GET["template"]!==NULL) {
$Exif_file = fopen($ExifDeviceTemplateFilename, 'r'); $Exif_file = fopen($ExifDeviceTemplateFilename, 'r');
fseek ($Exif_file, 0, SEEK_END) ; fseek ($Exif_file, 0, SEEK_END) ;
echo "<hr/>\n"; echo "<hr/>\n";
echo "ftell()=".ftell($Exif_file).", "; echo "ftell()=".ftell($Exif_file).", ";
fseek ($Exif_file, 0, SEEK_SET) ; fseek ($Exif_file, 0, SEEK_SET) ;
$template=fread ($Exif_file, 4096); $template=fread ($Exif_file, 4096);
fclose($Exif_file); fclose($Exif_file);
echo "read ".strlen($template)." bytes<br/>\n"; echo "read ".strlen($template)." bytes<br/>\n";
hexdump($template); hexdump($template);
} }
/// ===== read meta directory ======= /// ===== read meta directory =======
if ($_GET["metadir"]!==NULL) { if ($_GET["metadir"]!==NULL) {
$Exif_file = fopen($ExifDeviceMetadirFilename, 'r'); $Exif_file = fopen($ExifDeviceMetadirFilename, 'r');
fseek ($Exif_file, 0, SEEK_END) ; fseek ($Exif_file, 0, SEEK_END) ;
echo "<hr/>\n"; echo "<hr/>\n";
echo "ftell()=".ftell($Exif_file).", "; echo "ftell()=".ftell($Exif_file).", ";
fseek ($Exif_file, 0, SEEK_SET) ; fseek ($Exif_file, 0, SEEK_SET) ;
$metadir=fread ($Exif_file, 4096); $metadir=fread ($Exif_file, 4096);
fclose($Exif_file); fclose($Exif_file);
echo "read ".strlen($metadir)." bytes<br/>\n"; echo "read ".strlen($metadir)." bytes<br/>\n";
$dir_entries=array(); $dir_entries=array();
for ($i=0; $i<strlen($metadir);$i+=16) { for ($i=0; $i<strlen($metadir);$i+=16) {
$dir_entries[]=unpack("V*",substr($metadir,$i,16)); $dir_entries[]=unpack("V*",substr($metadir,$i,16));
} }
print_directory($dir_entries); print_directory($dir_entries);
} }
/// ===== read one of the Exif pages (0 - current, 1..512 - buffer) ======= /// ===== read one of the Exif pages (0 - current, 1..512 - buffer) =======
if ($_GET["exif"]!==NULL) { if ($_GET["exif"]!==NULL) {
$frame=$_GET["exif"]+0; $frame=$_GET["exif"]+0;
echo "<hr/>\n"; echo "<hr/>\n";
printf ("Reading frame %d, ",$frame); printf ("Reading frame %d, ",$frame);
$Exif_file = fopen($ExifDeviceExifFilename, 'r'); $Exif_file = fopen($ExifDeviceExifFilename, 'r');
fseek ($Exif_file, 1, SEEK_END) ; fseek ($Exif_file, 1, SEEK_END) ;
$exif_size=ftell($Exif_file); $exif_size=ftell($Exif_file);
if ($frame) fseek ($Exif_file, $frame, SEEK_END) ; if ($frame) fseek ($Exif_file, $frame, SEEK_END) ;
else fseek ($Exif_file, 0, SEEK_SET) ; else fseek ($Exif_file, 0, SEEK_SET) ;
echo "ftell()=".ftell($Exif_file).", "; echo "ftell()=".ftell($Exif_file).", ";
$exif_data=fread ($Exif_file, $exif_size); $exif_data=fread ($Exif_file, $exif_size);
fclose($Exif_file); fclose($Exif_file);
echo "read ".strlen($exif_data)." bytes<br/>\n"; echo "read ".strlen($exif_data)." bytes<br/>\n";
hexdump($exif_data); hexdump($exif_data);
} }
exit(0); exit(0);
/// ======================================= Functions ====================================== /// ======================================= Functions ======================================
function hexdump($data) { function hexdump($data) {
global $exif_head, $exif_data; global $exif_head, $exif_data;
$l=strlen($data); $l=strlen($data);
printf ("<h2>Exif size=%d bytes</h2>\n",$l); printf ("<h2>Exif size=%d bytes</h2>\n",$l);
printf ("<table border=\"0\">\n"); printf ("<table border=\"0\">\n");
for ($i=0; $i<$l;$i=$i+16) { for ($i=0; $i<$l;$i=$i+16) {
printf("<tr><td>%03x</td><td>|</td>\n",$i); printf("<tr><td>%03x</td><td>|</td>\n",$i);
for ($j=$i; $j<$i+16;$j++) { for ($j=$i; $j<$i+16;$j++) {
printf("<td>"); printf("<td>");
if ($j<$l) { if ($j<$l) {
$d=ord($data[$j]); $d=ord($data[$j]);
printf(" %02x",$d); printf(" %02x",$d);
} else printf (" "); } else printf (" ");
printf("</td>"); printf("</td>");
} }
printf("<td>|</td>"); printf("<td>|</td>");
for ($j=$i; $j< ($i+16);$j++) { for ($j=$i; $j< ($i+16);$j++) {
printf("<td>"); printf("<td>");
if ($j<$l) { if ($j<$l) {
$d=ord($data[$j]); $d=ord($data[$j]);
if ($d<32 or $d>126) printf("."); if ($d<32 or $d>126) printf(".");
else printf ("%c",$d); else printf ("%c",$d);
} else printf (" "); } else printf (" ");
printf("</td>"); printf("</td>");
} }
printf("</tr>\n"); printf("</tr>\n");
} }
printf ("</table>"); printf ("</table>");
} }
function print_directory($dir_entries) { function print_directory($dir_entries) {
$meta_size=0; $meta_size=0;
foreach ($dir_entries as $entry) if (($entry[3]+$entry[2])>$meta_size) $meta_size=$entry[3]+$entry[2]; foreach ($dir_entries as $entry) if (($entry[3]+$entry[2])>$meta_size) $meta_size=$entry[3]+$entry[2];
printf ("<h2>Frame meta data size=%d bytes</h2>\n",$meta_size); printf ("<h2>Frame meta data size=%d bytes</h2>\n",$meta_size);
printf ("<table border=\"1\">\n"); printf ("<table border=\"1\">\n");
printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n"); printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n");
foreach ($dir_entries as $entry) { foreach ($dir_entries as $entry) {
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]); 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]);
} }
printf ("</table>"); printf ("</table>");
} }
function test_print_header() { function test_print_header() {
global $exif_head, $exif_data; global $exif_head, $exif_data;
$lh=count($exif_head); $lh=count($exif_head);
$ld=count($exif_data); $ld=count($exif_data);
printf ("<h2>Exif size=%d bytes (head=%d, data=%d)</h2>\n",$lh+$ld,$lh,$ld); printf ("<h2>Exif size=%d bytes (head=%d, data=%d)</h2>\n",$lh+$ld,$lh,$ld);
printf ("<table border=\"0\">\n"); printf ("<table border=\"0\">\n");
for ($i=0; $i<$lh+$ld;$i=$i+16) { for ($i=0; $i<$lh+$ld;$i=$i+16) {
printf("<tr><td>%03x</td><td>|</td>\n",$i); printf("<tr><td>%03x</td><td>|</td>\n",$i);
for ($j=$i; $j<$i+16;$j++) { for ($j=$i; $j<$i+16;$j++) {
printf("<td>"); printf("<td>");
if ($j<($lh+$ld)) { if ($j<($lh+$ld)) {
$d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh]; $d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh];
printf(" %02x",$d); printf(" %02x",$d);
} else printf (" "); } else printf (" ");
printf("</td>"); printf("</td>");
} }
printf("<td>|</td>"); printf("<td>|</td>");
for ($j=$i; $j< ($i+16);$j++) { for ($j=$i; $j< ($i+16);$j++) {
printf("<td>"); printf("<td>");
if ($j<($lh+$ld)) { if ($j<($lh+$ld)) {
$d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh]; $d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh];
if ($d<32 or $d>126) printf("."); if ($d<32 or $d>126) printf(".");
else printf ("%c",$d); else printf ("%c",$d);
} else printf (" "); } else printf (" ");
printf("</td>"); printf("</td>");
} }
printf("</tr>\n"); printf("</tr>\n");
} }
printf ("</table>"); printf ("</table>");
} }
function test_print_directory() { function test_print_directory() {
global $dir_entries,$frame_meta_size; global $dir_entries,$frame_meta_size;
printf ("<h2>Frame meta data size=%d bytes</h2>\n",$frame_meta_size); printf ("<h2>Frame meta data size=%d bytes</h2>\n",$frame_meta_size);
printf ("<table border=\"1\">\n"); printf ("<table border=\"1\">\n");
printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n"); printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n");
foreach ($dir_entries as $entry) foreach ($dir_entries as $entry)
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"]); 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"]);
printf ("</table>"); printf ("</table>");
} }
function start_ifd($count) { function start_ifd($count) {
global $exif_data, $ifd_pointer; global $exif_data, $ifd_pointer;
// printf("start_ifd: ifd_pointer=0x%04x \n", $ifd_pointer); // printf("start_ifd: ifd_pointer=0x%04x \n", $ifd_pointer);
$exif_data[$ifd_pointer++]= ($count >> 8) & 0xff; $exif_data[$ifd_pointer++]= ($count >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $count & 0xff; // may apply & 0xff in the end to all elements $exif_data[$ifd_pointer++]= $count & 0xff; // may apply & 0xff in the end to all elements
} }
function finish_ifd() { // we do not have additional IFDs function finish_ifd() { // we do not have additional IFDs
global $exif_data, $ifd_pointer; global $exif_data, $ifd_pointer;
// printf("finish_ifd: ifd_pointer=0x%04x \n", $ifd_pointer); // printf("finish_ifd: ifd_pointer=0x%04x \n", $ifd_pointer);
$exif_data[$ifd_pointer++]=0; $exif_data[$ifd_pointer++]=0;
$exif_data[$ifd_pointer++]=0; $exif_data[$ifd_pointer++]=0;
$exif_data[$ifd_pointer++]=0; $exif_data[$ifd_pointer++]=0;
$exif_data[$ifd_pointer++]=0; $exif_data[$ifd_pointer++]=0;
} }
//pass2 - building map from frame meta to Exif template //pass2 - building map from frame meta to Exif template
function addDirEntry($ifd_entry) { function addDirEntry($ifd_entry) {
global $dir_sequence,$dir_entries,$exif_head; global $dir_sequence,$dir_entries,$exif_head;
$lh=count($exif_head); $lh=count($exif_head);
$attrs = $ifd_entry->attributes(); $attrs = $ifd_entry->attributes();
// var_dump($attrs); // var_dump($attrs);
// if (array_key_exists ( "seq" , $attrs )) { // if (array_key_exists ( "seq" , $attrs )) {
if ($attrs["seq"]) { if ($attrs["seq"]) {
// echo $attrs["seq"].; // echo $attrs["seq"].;
$dir_sequence[]=((string) $attrs["seq"])+0; $dir_sequence[]=((string) $attrs["seq"])+0;
$len= (integer) $ifd_entry->value_length; $len= (integer) $ifd_entry->value_length;
$offs=$lh+(integer) $ifd_entry->value_offest; $offs=$lh+(integer) $ifd_entry->value_offest;
// if (array_key_exists ( "dlen" , $attrs )) // if (array_key_exists ( "dlen" , $attrs ))
if ($attrs["dlen"]) $len=min($len,((string) $attrs["dlen"])+0); if ($attrs["dlen"]) $len=min($len,((string) $attrs["dlen"])+0);
$dir_entries[]=array("ltag"=>((integer)$ifd_entry->ltag),"dst"=>$offs,"len"=>$len); $dir_entries[]=array("ltag"=>((integer)$ifd_entry->ltag),"dst"=>$offs,"len"=>$len);
} }
} }
function substitute_value($ifd_entry) { function substitute_value($ifd_entry) {
global $SUB_IFD_offset,$GPSInfo_offset; global $SUB_IFD_offset,$GPSInfo_offset;
$attrs = $ifd_entry->attributes(); global $DeviceSNFilename, $DeviceRevisionFilename, $DeviceBrand, $DeviceModel;
$attrs = $ifd_entry->attributes();
switch ($attrs["function"]) {
case "BRAND": switch ($attrs["function"]) {
$ifd_entry->addChild ('value',exec("bootblocktool -x BRAND")); case "BRAND":
break; $ifd_entry->addChild('value', $DeviceBrand);
case "MODEL": break;
if (file_exists ('/var/state/APPLICATION')) { case "MODEL":
$model= file_get_contents('/var/state/APPLICATION'); if (file_exists ('/var/state/APPLICATION')) {
if (file_exists ('/var/state/APPLICATION_MODE')) { $model= file_get_contents('/var/state/APPLICATION');
$model.=' CHN'.file_get_contents('/var/state/APPLICATION_MODE'); if (file_exists ('/var/state/APPLICATION_MODE')) {
} $model.=' CHN'.file_get_contents('/var/state/APPLICATION_MODE');
} else { }
$model= exec("bootblocktool -x MODEL").exec("bootblocktool -x REVISION"); } else {
} $model = $DeviceModel;
/// $ifd_entry->addChild ('value',exec("bootblocktool -x MODEL").exec("bootblocktool -x REVISION")); }
$ifd_entry->addChild ('value',$model); $ifd_entry->addChild ('value',$model);
break;
break; case "SOFTWARE":
case "SOFTWARE": if (file_exists("/usr/html/docs/")) {
$ifd_entry->addChild ('value',exec("ls /usr/html/docs/")); // filter $ifd_entry->addChild ('value',exec("ls /usr/html/docs/")); // filter
break; }
case "SERIAL": break;
$s=exec("bootblocktool -x SERNO"); case "SERIAL":
$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)); $s = "";
break; if (file_exists($DeviceSNFilename)) {
case "EXIFTAG": $s = exec('cat '.$DeviceSNFilename);
$ifd_entry->addChild ('value',$SUB_IFD_offset); }
break; $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));
case "GPSTAG": break;
$ifd_entry->addChild ('value',$GPSInfo_offset); case "EXIFTAG":
break; $ifd_entry->addChild ('value',$SUB_IFD_offset);
} break;
case "GPSTAG":
$ifd_entry->addChild ('value',$GPSInfo_offset);
break;
}
} }
function process_ifd_entry($ifd_entry, $group) { function process_ifd_entry($ifd_entry, $group) {
global $exif_data, $ifd_pointer, $data_pointer,$SUB_IFD_offset,$GPSInfo_offset; global $exif_data, $ifd_pointer, $data_pointer,$SUB_IFD_offset,$GPSInfo_offset;
$attrs = $ifd_entry->attributes(); $attrs = $ifd_entry->attributes();
$ifd_tag= ((string) $attrs["tag"])+0; $ifd_tag= ((string) $attrs["tag"])+0;
$ifd_format=constant("EXIF_".$attrs["format"]); $ifd_format=constant("EXIF_".$attrs["format"]);
$ifd_count= $attrs["count"]; $ifd_count= $attrs["count"];
// echo "\nifd_tag=$ifd_tag, entry=";print_r($ifd_entry); // echo "\nifd_tag=$ifd_tag, entry=";print_r($ifd_entry);
// echo "\nifd_count=$ifd_count"; // echo "\nifd_count=$ifd_count";
// echo "\nifd_bytes:";var_dump($ifd_bytes); // echo "\nifd_bytes:";var_dump($ifd_bytes);
if (!$ifd_count) { if (!$ifd_count) {
if($ifd_format==EXIF_ASCII) $ifd_count=strlen($ifd_entry->value)+1; if($ifd_format==EXIF_ASCII) $ifd_count=strlen($ifd_entry->value)+1;
else $ifd_count=1 ; /// may change? else $ifd_count=1 ; /// may change?
} }
//echo "\nifd_count=$ifd_count"; //echo "\nifd_count=$ifd_count";
$exif_data[$ifd_pointer++]= ($ifd_tag >> 8) & 0xff; $exif_data[$ifd_pointer++]= ($ifd_tag >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $ifd_tag & 0xff; $exif_data[$ifd_pointer++]= $ifd_tag & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_format >> 8 ) & 0xff; $exif_data[$ifd_pointer++]= ($ifd_format >> 8 ) & 0xff;
$exif_data[$ifd_pointer++]= $ifd_format & 0xff; $exif_data[$ifd_pointer++]= $ifd_format & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_count >> 24) & 0xff; $exif_data[$ifd_pointer++]= ($ifd_count >> 24) & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_count >> 16) & 0xff; $exif_data[$ifd_pointer++]= ($ifd_count >> 16) & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_count >> 8) & 0xff; $exif_data[$ifd_pointer++]= ($ifd_count >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $ifd_count & 0xff; $exif_data[$ifd_pointer++]= $ifd_count & 0xff;
$ifd_bytes=0; $ifd_bytes=0;
switch ($ifd_format) { switch ($ifd_format) {
case EXIF_SHORT: case EXIF_SHORT:
case EXIF_SSHORT: $ifd_bytes=2; break; case EXIF_SSHORT: $ifd_bytes=2; break;
case EXIF_LONG: case EXIF_LONG:
case EXIF_SLONG: $ifd_bytes=4; break; case EXIF_SLONG: $ifd_bytes=4; break;
case EXIF_RATIONAL: case EXIF_RATIONAL:
case EXIF_SRATIONAL: $ifd_bytes=8; break; case EXIF_SRATIONAL: $ifd_bytes=8; break;
default: $ifd_bytes=1; //1,2,6,7 default: $ifd_bytes=1; //1,2,6,7
} }
$ifd_bytes=$ifd_bytes*$ifd_count; $ifd_bytes=$ifd_bytes*$ifd_count;
// now prepare ifd_data - array of bytes // now prepare ifd_data - array of bytes
switch ($ifd_format) { switch ($ifd_format) {
case EXIF_BYTE: case EXIF_BYTE:
case EXIF_SBYTE: case EXIF_SBYTE:
$ifd_data= array (); $ifd_data= array ();
foreach ($ifd_entry->value as $a) $ifd_data[]= $a & 0xff; foreach ($ifd_entry->value as $a) $ifd_data[]= $a & 0xff;
break; break;
case EXIF_ASCII: case EXIF_ASCII:
$ifd_data= str_split($ifd_entry->value); $ifd_data= str_split($ifd_entry->value);
foreach($ifd_data as &$d) $d=ord($d); foreach($ifd_data as &$d) $d=ord($d);
break; break;
case EXIF_SHORT: case EXIF_SHORT:
case EXIF_SSHORT: case EXIF_SSHORT:
$ifd_data= array (); $ifd_data= array ();
foreach ($ifd_entry->value as $a) $ifd_data=array_merge($ifd_data,array(($a >> 8) & 0xff, $a & 0xff)); foreach ($ifd_entry->value as $a) $ifd_data=array_merge($ifd_data,array(($a >> 8) & 0xff, $a & 0xff));
break; break;
case EXIF_LONG: case EXIF_LONG:
case EXIF_SLONG: case EXIF_SLONG:
$ifd_data= array (); $ifd_data= array ();
foreach ($ifd_entry->value as $a) $ifd_data=array_merge($ifd_data,array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff)); foreach ($ifd_entry->value as $a) $ifd_data=array_merge($ifd_data,array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff));
break; break;
case EXIF_RATIONAL: case EXIF_RATIONAL:
case EXIF_SRATIONAL: case EXIF_SRATIONAL:
$nom= array (); $nom= array ();
foreach ($ifd_entry->nominator as $a) $nom[]= array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff); foreach ($ifd_entry->nominator as $a) $nom[]= array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff);
$denom= array (); $denom= array ();
foreach ($ifd_entry->denominator as $a) $denom[]=array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff); foreach ($ifd_entry->denominator as $a) $denom[]=array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff);
$ifd_data= array (); $ifd_data= array ();
/* /*
var_dump($nom); var_dump($nom);
echo "\n"; echo "\n";
var_dump($denom); var_dump($denom);
echo "\n"; echo "\n";
//exit(0); //exit(0);
*/ */
for ($i=0;$i<count($nom);$i++) { for ($i=0;$i<count($nom);$i++) {
// echo "i=$i\n"; // echo "i=$i\n";
// echo "\nnom=";var_dump($nom[$i]); // echo "\nnom=";var_dump($nom[$i]);
// echo "\ndenom=";var_dump($denom[$i]); // echo "\ndenom=";var_dump($denom[$i]);
$ifd_data=array_merge($ifd_data,$nom[$i],$denom[$i]); $ifd_data=array_merge($ifd_data,$nom[$i],$denom[$i]);
} }
break; // rational, (un)signed break; // rational, (un)signed
case EXIF_UNDEFINED: // undefined case EXIF_UNDEFINED: // undefined
$ifd_data= array_fill(0,$ifd_bytes,0); // will just fill with "0"-s $ifd_data= array_fill(0,$ifd_bytes,0); // will just fill with "0"-s
break; break;
} }
// echo "\nifd_tag=$ifd_tag, entry=";print_r($i=$ifd_entry->value); // echo "\nifd_tag=$ifd_tag, entry=";print_r($i=$ifd_entry->value);
// echo "\nifd_data:";var_dump($ifd_data); // echo "\nifd_data:";var_dump($ifd_data);
// echo "\nifd_bytes:";var_dump($ifd_bytes); // echo "\nifd_bytes:";var_dump($ifd_bytes);
$ifd_data=array_pad($ifd_data,$ifd_bytes,0); $ifd_data=array_pad($ifd_data,$ifd_bytes,0);
$ifd_entry->addChild ('value_length',count($ifd_data)); $ifd_entry->addChild ('value_length',count($ifd_data));
// if (array_key_exists ( "ltag" , $attrs )) $ltag= ((string) $attrs["ltag"])+0; // if (array_key_exists ( "ltag" , $attrs )) $ltag= ((string) $attrs["ltag"])+0;
if ($attr["ltag"]) $ltag= ((string) $attrs["ltag"])+0; if ($attr["ltag"]) $ltag= ((string) $attrs["ltag"])+0;
else $ltag= $ifd_tag+($group<<16) ; else $ltag= $ifd_tag+($group<<16) ;
$ifd_entry->addChild ("ltag",$ltag ); $ifd_entry->addChild ("ltag",$ltag );
if (count($ifd_data) <=4) { if (count($ifd_data) <=4) {
$ifd_entry->addChild ('value_offest',$ifd_pointer); $ifd_entry->addChild ('value_offest',$ifd_pointer);
$ifd_data= array_pad($ifd_data,-4,0); // add leading zeroes if <4 bytes $ifd_data= array_pad($ifd_data,-4,0); // add leading zeroes if <4 bytes
for ($i=0;$i<4;$i++) $exif_data[$ifd_pointer++]=$ifd_data[$i]; for ($i=0;$i<4;$i++) $exif_data[$ifd_pointer++]=$ifd_data[$i];
} else { //pointer, not data } else { //pointer, not data
$ifd_entry->addChild ('value_offest',$data_pointer); $ifd_entry->addChild ('value_offest',$data_pointer);
$exif_data[$ifd_pointer++]= ($data_pointer >> 24) & 0xff; $exif_data[$ifd_pointer++]= ($data_pointer >> 24) & 0xff;
$exif_data[$ifd_pointer++]= ($data_pointer >> 16) & 0xff; $exif_data[$ifd_pointer++]= ($data_pointer >> 16) & 0xff;
$exif_data[$ifd_pointer++]= ($data_pointer >> 8) & 0xff; $exif_data[$ifd_pointer++]= ($data_pointer >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $data_pointer & 0xff; $exif_data[$ifd_pointer++]= $data_pointer & 0xff;
for ($i=0;$i<count($ifd_data);$i++) { for ($i=0;$i<count($ifd_data);$i++) {
$exif_data[$data_pointer++]=$ifd_data[$i]; $exif_data[$data_pointer++]=$ifd_data[$i];
} }
} }
} }
?> ?>
...@@ -289,7 +289,7 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -289,7 +289,7 @@ int printExifXML(int exif_page, struct file_set *fset)
while (read(fd_exifdir, &dir_table_entry, sizeof(dir_table_entry)) > 0) { while (read(fd_exifdir, &dir_table_entry, sizeof(dir_table_entry)) > 0) {
switch (dir_table_entry.ltag) { switch (dir_table_entry.ltag) {
case Exif_Image_ImageDescription: indx = Exif_Image_ImageDescription_Index; break; case Exif_Image_ImageDescription: indx = Exif_Image_ImageDescription_Index; break;
case Exif_Image_FrameNumber: indx = Exif_Image_FrameNumber_Index; break; case Exif_Image_ImageNumber: indx = Exif_Image_ImageNumber_Index; break;
case Exif_Photo_DateTimeOriginal: indx = Exif_Photo_DateTimeOriginal_Index; break; case Exif_Photo_DateTimeOriginal: indx = Exif_Photo_DateTimeOriginal_Index; break;
case Exif_Photo_SubSecTimeOriginal: indx = Exif_Photo_SubSecTimeOriginal_Index; break; case Exif_Photo_SubSecTimeOriginal: indx = Exif_Photo_SubSecTimeOriginal_Index; break;
case Exif_Photo_ExposureTime: indx = Exif_Photo_ExposureTime_Index; break; case Exif_Photo_ExposureTime: indx = Exif_Photo_ExposureTime_Index; break;
...@@ -349,14 +349,14 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -349,14 +349,14 @@ int printExifXML(int exif_page, struct file_set *fset)
saferead255(fd_exif, val, exif_dir[Exif_Image_ImageDescription_Index].len); saferead255(fd_exif, val, exif_dir[Exif_Image_ImageDescription_Index].len);
printf("<ImageDescription>\"%s\"</ImageDescription>\n", val); printf("<ImageDescription>\"%s\"</ImageDescription>\n", val);
} }
///Exif_Image_FrameNumber_Index 0x13 ///Exif_Image_ImageNumber_Index 0x13
if (exif_dir[Exif_Image_FrameNumber_Index].ltag == Exif_Image_FrameNumber) { // Exif_Image_FrameNumber_Index is present in template if (exif_dir[Exif_Image_ImageNumber_Index].ltag == Exif_Image_ImageNumber) { // Exif_Image_ImageNumber_Index is present in template
lseek(fd_exif, lseek(fd_exif,
exif_page_start + exif_dir[Exif_Image_FrameNumber_Index].dst, exif_page_start + exif_dir[Exif_Image_ImageNumber_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 4); read(fd_exif, rational3, 4);
sprintf(val, "%ld", (long)__cpu_to_be32( rational3[0])); sprintf(val, "%ld", (long)__cpu_to_be32( rational3[0]));
printf("<FrameNumber>\"%s\"</FrameNumber>\n", val); printf("<ImageNumber>\"%s\"</ImageNumber>\n", val);
} }
///Exif_Image_Orientation_Index 0x14 ///Exif_Image_Orientation_Index 0x14
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment