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 @@
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
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>
<Image>
......@@ -22,8 +25,8 @@
<DateTime tag="0x0132" format="ASCII" count="20" seq="1" dlen="20">
<value>2001:06:21 12:00:00</value>
</DateTime>
<HostComputer tag="0x013c" format="ASCII" function="SERIAL"/>
<FrameNumber tag="0x83bb" format="LONG" count="1" seq="25" dlen="4"/>
<CameraSerialNumber tag="0xc62f" format="ASCII" function="SERIAL"/>
<ImageNumber tag="0x9211" format="LONG" count="1" seq="25" dlen="4"/>
<Orientation tag="0x112" format="SHORT" count="1" seq="27" dlen="2"/>
<PageNumber tag="0x129" format="SHORT" count="1" seq="28" dlen="2"/>
<ExifTag tag="0x8769" format="LONG" function="EXIFTAG"/>
......
#!/usr/local/sbin/php -q
#!/usr/bin/env php
<?php
/*!
*! FILE NAME : exif.php
*! 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
*! of Exif headers.
*! 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
*! init - program Exif with default /etc/Exif_template.xml
*! init=path - program Exif with alternative file
*! noGPS - don't include GPS-related fields
*! nocompass - don't include compass-related fields
*! template - print currently loaded template data (hex dump)
*! 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=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
*! -----------------------------------------------------------------------------**
*!
*! 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
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: exif.php,v $
*! 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)
*!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*!
*!
*! Revision 1.2 2008/08/11 19:11:32 elphel
*! comments
*!
*! Revision 1.1 2008/04/07 09:12:14 elphel
*! New Exif template generation
*!
*! $Log: exif.php,v $
*! 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)
*!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*!
*!
*! Revision 1.2 2008/08/11 19:11:32 elphel
*! comments
*!
*! Revision 1.1 2008/04/07 09:12:14 elphel
*! New Exif template generation
*!
*! Revision 1.1.1.1 2007/10/03 19:05:53 elphel
*! This is a fresh tree based on elphel353-2.10
*!
*! Revision 1.6 2007/10/03 19:05:53 elphel
*! cosmetic
*!
*! Revision 1.5 2007/10/03 18:37:53 elphel
*! Made nice html output to see the result data
*!
*! Revision 1.4 2007/10/03 06:33:31 elphel
*! fixed wrong copyright year
*!
*! 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)
*!
*! Revision 1.2 2007/09/25 23:34:02 elphel
*! Fixed time strings to the right length
*!
*! Revision 1.1 2007/09/24 07:27:57 elphel
*! Started php script that prepares Exif header information for serving images by imgsrv
*!
*/
*! FILE NAME : exif.php
*! 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
*! of Exif headers.
*! 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
*! init - program Exif with default /etc/Exif_template.xml
*! init=path - program Exif with alternative file
*! noGPS - don't include GPS-related fields
*! nocompass - don't include compass-related fields
*! template - print currently loaded template data (hex dump)
*! 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=NNN - print one of the Exif pages in the buffer (debug feature, current buffer pointer is not known here)
*!
*! Copyright (C) 2007-2016 Elphel, Inc
*! -----------------------------------------------------------------------------**
*!
*! 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
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: exif.php,v $
*! 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)
*!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*!
*!
*! Revision 1.2 2008/08/11 19:11:32 elphel
*! comments
*!
*! Revision 1.1 2008/04/07 09:12:14 elphel
*! New Exif template generation
*!
*! $Log: exif.php,v $
*! 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)
*!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*!
*!
*! Revision 1.2 2008/08/11 19:11:32 elphel
*! comments
*!
*! Revision 1.1 2008/04/07 09:12:14 elphel
*! New Exif template generation
*!
*! Revision 1.1.1.1 2007/10/03 19:05:53 elphel
*! This is a fresh tree based on elphel353-2.10
*!
*! Revision 1.6 2007/10/03 19:05:53 elphel
*! cosmetic
*!
*! Revision 1.5 2007/10/03 18:37:53 elphel
*! Made nice html output to see the result data
*!
*! Revision 1.4 2007/10/03 06:33:31 elphel
*! fixed wrong copyright year
*!
*! 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)
*!
*! Revision 1.2 2007/09/25 23:34:02 elphel
*! Fixed time strings to the right length
*!
*! Revision 1.1 2007/09/24 07:27:57 elphel
*! 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.
// 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
......@@ -90,6 +90,10 @@ $ExifDeviceMetadirFilename= "/dev/exif_metadir";
$ExifDeviceExifFilename= "/dev/exif_exif";
$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,
//! through CGI - accepts more parameters
......@@ -97,31 +101,31 @@ $ExifDeviceMetaFilename= "/dev/exif_meta";
$ExifXMLName="/etc/Exif_template.xml";
$init=false;
if ($_SERVER['REQUEST_METHOD']=="GET") {
if ($_GET["init"]!==NULL) {
if ($_GET["init"]) $ExifXMLName=$_GET["init"];
$init=true; // in any case - filename specified or not
$noGPS= ($_GET["noGPS"]!==NULL);
$nocompass= ($_GET["nocompass"]!==NULL);
}
if ($_GET["init"]!==NULL) {
if ($_GET["init"]) $ExifXMLName=$_GET["init"];
$init=true; // in any case - filename specified or not
$noGPS= ($_GET["noGPS"]!==NULL);
$nocompass= ($_GET["nocompass"]!==NULL);
}
} else {
foreach ($_SERVER['argv'] as $param) if (substr($param,0,4)=="init") {
$param=substr($param,5);
if (strlen($param)>0) $ExifXMLName=$param;
$init=true; //
break;
}
if ($init) {
$noGPS= in_array ('noGPS' , $_SERVER['argv']);
$nocompass= in_array ('nocompass', $_SERVER['argv']);
} else {
echo <<<USAGE
foreach ($_SERVER['argv'] as $param) if (substr($param,0,4)=="init") {
$param=substr($param,5);
if (strlen($param)>0) $ExifXMLName=$param;
$init=true; //
break;
}
if ($init) {
$noGPS= in_array ('noGPS' , $_SERVER['argv']);
$nocompass= in_array ('nocompass', $_SERVER['argv']);
} else {
echo <<<USAGE
Usage: {$_SERVER['argv'][0]} [init[=filename.xml] [noGPS] [nocompass]]
USAGE;
exit (0);
}
exit (0);
}
}
define("EXIF_BYTE", 1);
......@@ -138,464 +142,468 @@ define("EXIF_SRATIONAL",10);
define("EXIF_LSEEK_ENABLE", 2); // rebuild buffer
/// ===== init/init= CGI parameters or command line mode =======
if ($init) { // configure Exif data
$exif_head= array (
0xff, 0xe1, // APP1 marker
// 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
0x45,0x78,0x69,0x66,0x00,0x00); // Exif header
$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
0x4d,0x4d, // (MM) Big endian, MSB goes first in multi-byte data
0x00,0x2a, // Tag Mark
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);
if ($xml_exif->GPSInfo) {
/// remove all tags named "Compass..."
if ($nocompass) {
$tounset=array();
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});
}
if ($noGPS) {
unset($xml_exif->GPSInfo);
unset($xml_exif->Image->GPSTag);
}
}
$IFD_offset= count($exif_data);
$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;
$data_offset= $GPSInfo_offset+(($xml_exif->GPSInfo)?(12*count($xml_exif->GPSInfo->children())+2+4):0); //$GPSInfo is optional
if ($_SERVER['REQUEST_METHOD']) {
echo "<pre>";
printf ("IFD_offset=0x%x\n",$IFD_offset);
printf ("SUB_IFD_offset=0x%x\n",$SUB_IFD_offset);
printf ("GPSInfo_offset=0x%x\n",$GPSInfo_offset);
printf ("data_offset=0x%x\n",$data_offset);
}
/// Now modify variable fields substituting values
foreach ($xml_exif->Image->children() as $entry) substitute_value($entry);
foreach ($xml_exif->Photo->children() as $entry) substitute_value($entry);
if ($xml_exif->GPSInfo) {
foreach ($xml_exif->GPSInfo->children() as $entry) substitute_value($entry);
}
$ifd_pointer=$IFD_offset;
$data_pointer=$data_offset;
start_ifd(count($xml_exif->Image->children()));
foreach ($xml_exif->Image->children() as $entry) process_ifd_entry($entry,0);
finish_ifd();
$ifd_pointer=$SUB_IFD_offset;
start_ifd(count($xml_exif->Photo->children()));
foreach ($xml_exif->Photo->children() as $entry) process_ifd_entry($entry,1);
finish_ifd();
if ($xml_exif->GPSInfo) {
$ifd_pointer=$GPSInfo_offset;
start_ifd(count($xml_exif->GPSInfo->children()));
foreach ($xml_exif->GPSInfo->children() as $entry) process_ifd_entry($entry,2);
finish_ifd();
}
$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+1]= $exif_len & 0xff;
$Exif_str="";
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]);
$Exif_file = fopen($ExifDeviceTemplateFilename, 'w');
fwrite ($Exif_file,$Exif_str); /// will disable and invalidate Exif data
fclose($Exif_file);
///Exif template is done, now we need a directory to map frame meta data to fields in the template.
$dir_sequence=array();
$dir_entries=array();
foreach ($xml_exif->Image->children() as $entry) addDirEntry($entry);
foreach ($xml_exif->Photo->children() as $entry) addDirEntry($entry);
if ($xml_exif->GPSInfo) {
foreach ($xml_exif->GPSInfo->children() as $entry) addDirEntry($entry);
}
array_multisort($dir_sequence,$dir_entries);
$frame_meta_size=0;
for ($i=0;$i<count($dir_entries);$i++) {
$dir_entries[$i]["src"]=$frame_meta_size;
$frame_meta_size+=$dir_entries[$i]["len"];
}
$Exif_str="";
foreach ($dir_entries as $entry) $Exif_str.=pack("V*",$entry["ltag"],$entry["len"],$entry["src"],$entry["dst"]);
$Exif_meta_file = fopen($ExifDeviceMetadirFilename, 'w');
fwrite ($Exif_meta_file,$Exif_str); /// will disable and invalidate Exif data
fclose($Exif_meta_file);
///Rebuild buffer and enable Exif generation/output:
$Exif_file = fopen($ExifDeviceTemplateFilename, 'w');
fseek ($Exif_file, EXIF_LSEEK_ENABLE, SEEK_END) ;
fclose($Exif_file);
if ($_SERVER['REQUEST_METHOD']) {
echo "</pre>";
}
if ($_SERVER['REQUEST_METHOD']) {
echo "<hr/>\n";
test_print_header();
echo "<hr/>\n";
test_print_directory();
}
} //if ($init) // configure Exif data
if ($init) { // configure Exif data
$exif_head= array (
0xff, 0xe1, // APP1 marker
// 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
0x45,0x78,0x69,0x66,0x00,0x00); // Exif header
$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
0x4d,0x4d, // (MM) Big endian, MSB goes first in multi-byte data
0x00,0x2a, // Tag Mark
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);
if ($xml_exif->GPSInfo) {
/// remove all tags named "Compass..."
if ($nocompass) {
$tounset=array();
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});
}
if ($noGPS) {
unset($xml_exif->GPSInfo);
unset($xml_exif->Image->GPSTag);
}
}
$IFD_offset= count($exif_data);
$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;
$data_offset= $GPSInfo_offset+(($xml_exif->GPSInfo)?(12*count($xml_exif->GPSInfo->children())+2+4):0); //$GPSInfo is optional
if ($_SERVER['REQUEST_METHOD']) {
echo "<pre>";
printf ("IFD_offset=0x%x\n",$IFD_offset);
printf ("SUB_IFD_offset=0x%x\n",$SUB_IFD_offset);
printf ("GPSInfo_offset=0x%x\n",$GPSInfo_offset);
printf ("data_offset=0x%x\n",$data_offset);
}
/// Now modify variable fields substituting values
foreach ($xml_exif->Image->children() as $entry) substitute_value($entry);
foreach ($xml_exif->Photo->children() as $entry) substitute_value($entry);
if ($xml_exif->GPSInfo) {
foreach ($xml_exif->GPSInfo->children() as $entry) substitute_value($entry);
}
$ifd_pointer=$IFD_offset;
$data_pointer=$data_offset;
start_ifd(count($xml_exif->Image->children()));
foreach ($xml_exif->Image->children() as $entry) process_ifd_entry($entry,0);
finish_ifd();
$ifd_pointer=$SUB_IFD_offset;
start_ifd(count($xml_exif->Photo->children()));
foreach ($xml_exif->Photo->children() as $entry) process_ifd_entry($entry,1);
finish_ifd();
if ($xml_exif->GPSInfo) {
$ifd_pointer=$GPSInfo_offset;
start_ifd(count($xml_exif->GPSInfo->children()));
foreach ($xml_exif->GPSInfo->children() as $entry) process_ifd_entry($entry,2);
finish_ifd();
}
$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+1]= $exif_len & 0xff;
$Exif_str="";
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]);
$Exif_file = fopen($ExifDeviceTemplateFilename, 'w');
fwrite ($Exif_file,$Exif_str); /// will disable and invalidate Exif data
fclose($Exif_file);
///Exif template is done, now we need a directory to map frame meta data to fields in the template.
$dir_sequence=array();
$dir_entries=array();
foreach ($xml_exif->Image->children() as $entry) addDirEntry($entry);
foreach ($xml_exif->Photo->children() as $entry) addDirEntry($entry);
if ($xml_exif->GPSInfo) {
foreach ($xml_exif->GPSInfo->children() as $entry) addDirEntry($entry);
}
array_multisort($dir_sequence,$dir_entries);
$frame_meta_size=0;
for ($i=0;$i<count($dir_entries);$i++) {
$dir_entries[$i]["src"]=$frame_meta_size;
$frame_meta_size+=$dir_entries[$i]["len"];
}
$Exif_str="";
foreach ($dir_entries as $entry) $Exif_str.=pack("V*",$entry["ltag"],$entry["len"],$entry["src"],$entry["dst"]);
$Exif_meta_file = fopen($ExifDeviceMetadirFilename, 'w');
fwrite ($Exif_meta_file,$Exif_str); /// will disable and invalidate Exif data
fclose($Exif_meta_file);
///Rebuild buffer and enable Exif generation/output:
$Exif_file = fopen($ExifDeviceTemplateFilename, 'w');
fseek ($Exif_file, EXIF_LSEEK_ENABLE, SEEK_END) ;
fclose($Exif_file);
if ($_SERVER['REQUEST_METHOD']) {
echo "</pre>";
}
if ($_SERVER['REQUEST_METHOD']) {
echo "<hr/>\n";
test_print_header();
echo "<hr/>\n";
test_print_directory();
}
} //if ($init) // configure Exif data
/// ===== processing optional parameters =======
/// ===== read template =======
if ($_GET["description"]!==NULL) {
/// Read metadir to find the length of the description field
$Exif_file = fopen($ExifDeviceMetadirFilename, 'r');
fseek ($Exif_file, 0, SEEK_END) ;
fseek ($Exif_file, 0, SEEK_SET) ;
$metadir=fread ($Exif_file, 4096);
fclose($Exif_file);
$dir_entries=array();
for ($i=0; $i<strlen($metadir);$i+=16) {
$dir_entries[]=unpack("V*",substr($metadir,$i,16));
}
foreach ($dir_entries as $entry)
if ($entry[1]==0x010e) {
$descr=$_GET["description"];
$Exif_file = fopen($ExifDeviceMetaFilename, 'w+');
fseek ($Exif_file, $entry[3], SEEK_SET) ;
$descr_was=fread ($Exif_file, $entry[2]);
$zero=strpos($descr_was,chr(0));
if ($zero!==false) $descr_was=substr($descr_was,0, $zero);
if ($descr) {
$descr= str_pad($descr, $entry[2], chr(0));
fseek ($Exif_file, $entry[3], SEEK_SET) ;
fwrite($Exif_file, $descr,$entry[2]);
}
fclose($Exif_file);
var_dump($descr_was); echo "<br/>\n";
break;
}
}
if ($_GET["description"]!==NULL) {
/// Read metadir to find the length of the description field
$Exif_file = fopen($ExifDeviceMetadirFilename, 'r');
fseek ($Exif_file, 0, SEEK_END) ;
fseek ($Exif_file, 0, SEEK_SET) ;
$metadir=fread ($Exif_file, 4096);
fclose($Exif_file);
$dir_entries=array();
for ($i=0; $i<strlen($metadir);$i+=16) {
$dir_entries[]=unpack("V*",substr($metadir,$i,16));
}
foreach ($dir_entries as $entry)
if ($entry[1]==0x010e) {
$descr=$_GET["description"];
$Exif_file = fopen($ExifDeviceMetaFilename, 'w+');
fseek ($Exif_file, $entry[3], SEEK_SET) ;
$descr_was=fread ($Exif_file, $entry[2]);
$zero=strpos($descr_was,chr(0));
if ($zero!==false) $descr_was=substr($descr_was,0, $zero);
if ($descr) {
$descr= str_pad($descr, $entry[2], chr(0));
fseek ($Exif_file, $entry[3], SEEK_SET) ;
fwrite($Exif_file, $descr,$entry[2]);
}
fclose($Exif_file);
var_dump($descr_was); echo "<br/>\n";
break;
}
}
/// ===== read template =======
if ($_GET["template"]!==NULL) {
$Exif_file = fopen($ExifDeviceTemplateFilename, 'r');
fseek ($Exif_file, 0, SEEK_END) ;
echo "<hr/>\n";
echo "ftell()=".ftell($Exif_file).", ";
fseek ($Exif_file, 0, SEEK_SET) ;
$template=fread ($Exif_file, 4096);
fclose($Exif_file);
echo "read ".strlen($template)." bytes<br/>\n";
hexdump($template);
}
if ($_GET["template"]!==NULL) {
$Exif_file = fopen($ExifDeviceTemplateFilename, 'r');
fseek ($Exif_file, 0, SEEK_END) ;
echo "<hr/>\n";
echo "ftell()=".ftell($Exif_file).", ";
fseek ($Exif_file, 0, SEEK_SET) ;
$template=fread ($Exif_file, 4096);
fclose($Exif_file);
echo "read ".strlen($template)." bytes<br/>\n";
hexdump($template);
}
/// ===== read meta directory =======
if ($_GET["metadir"]!==NULL) {
$Exif_file = fopen($ExifDeviceMetadirFilename, 'r');
fseek ($Exif_file, 0, SEEK_END) ;
echo "<hr/>\n";
echo "ftell()=".ftell($Exif_file).", ";
fseek ($Exif_file, 0, SEEK_SET) ;
$metadir=fread ($Exif_file, 4096);
fclose($Exif_file);
echo "read ".strlen($metadir)." bytes<br/>\n";
$dir_entries=array();
for ($i=0; $i<strlen($metadir);$i+=16) {
$dir_entries[]=unpack("V*",substr($metadir,$i,16));
}
print_directory($dir_entries);
}
if ($_GET["metadir"]!==NULL) {
$Exif_file = fopen($ExifDeviceMetadirFilename, 'r');
fseek ($Exif_file, 0, SEEK_END) ;
echo "<hr/>\n";
echo "ftell()=".ftell($Exif_file).", ";
fseek ($Exif_file, 0, SEEK_SET) ;
$metadir=fread ($Exif_file, 4096);
fclose($Exif_file);
echo "read ".strlen($metadir)." bytes<br/>\n";
$dir_entries=array();
for ($i=0; $i<strlen($metadir);$i+=16) {
$dir_entries[]=unpack("V*",substr($metadir,$i,16));
}
print_directory($dir_entries);
}
/// ===== read one of the Exif pages (0 - current, 1..512 - buffer) =======
if ($_GET["exif"]!==NULL) {
$frame=$_GET["exif"]+0;
echo "<hr/>\n";
printf ("Reading frame %d, ",$frame);
$Exif_file = fopen($ExifDeviceExifFilename, 'r');
fseek ($Exif_file, 1, SEEK_END) ;
$exif_size=ftell($Exif_file);
if ($frame) fseek ($Exif_file, $frame, SEEK_END) ;
else fseek ($Exif_file, 0, SEEK_SET) ;
echo "ftell()=".ftell($Exif_file).", ";
$exif_data=fread ($Exif_file, $exif_size);
fclose($Exif_file);
echo "read ".strlen($exif_data)." bytes<br/>\n";
hexdump($exif_data);
}
exit(0);
if ($_GET["exif"]!==NULL) {
$frame=$_GET["exif"]+0;
echo "<hr/>\n";
printf ("Reading frame %d, ",$frame);
$Exif_file = fopen($ExifDeviceExifFilename, 'r');
fseek ($Exif_file, 1, SEEK_END) ;
$exif_size=ftell($Exif_file);
if ($frame) fseek ($Exif_file, $frame, SEEK_END) ;
else fseek ($Exif_file, 0, SEEK_SET) ;
echo "ftell()=".ftell($Exif_file).", ";
$exif_data=fread ($Exif_file, $exif_size);
fclose($Exif_file);
echo "read ".strlen($exif_data)." bytes<br/>\n";
hexdump($exif_data);
}
exit(0);
/// ======================================= Functions ======================================
function hexdump($data) {
global $exif_head, $exif_data;
$l=strlen($data);
printf ("<h2>Exif size=%d bytes</h2>\n",$l);
printf ("<table border=\"0\">\n");
for ($i=0; $i<$l;$i=$i+16) {
printf("<tr><td>%03x</td><td>|</td>\n",$i);
for ($j=$i; $j<$i+16;$j++) {
printf("<td>");
if ($j<$l) {
$d=ord($data[$j]);
printf(" %02x",$d);
} else printf (" ");
printf("</td>");
}
printf("<td>|</td>");
for ($j=$i; $j< ($i+16);$j++) {
printf("<td>");
if ($j<$l) {
$d=ord($data[$j]);
if ($d<32 or $d>126) printf(".");
else printf ("%c",$d);
} else printf (" ");
printf("</td>");
}
printf("</tr>\n");
}
printf ("</table>");
global $exif_head, $exif_data;
$l=strlen($data);
printf ("<h2>Exif size=%d bytes</h2>\n",$l);
printf ("<table border=\"0\">\n");
for ($i=0; $i<$l;$i=$i+16) {
printf("<tr><td>%03x</td><td>|</td>\n",$i);
for ($j=$i; $j<$i+16;$j++) {
printf("<td>");
if ($j<$l) {
$d=ord($data[$j]);
printf(" %02x",$d);
} else printf (" ");
printf("</td>");
}
printf("<td>|</td>");
for ($j=$i; $j< ($i+16);$j++) {
printf("<td>");
if ($j<$l) {
$d=ord($data[$j]);
if ($d<32 or $d>126) printf(".");
else printf ("%c",$d);
} else printf (" ");
printf("</td>");
}
printf("</tr>\n");
}
printf ("</table>");
}
function print_directory($dir_entries) {
$meta_size=0;
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 ("<table border=\"1\">\n");
printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n");
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 ("</table>");
$meta_size=0;
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 ("<table border=\"1\">\n");
printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n");
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 ("</table>");
}
function test_print_header() {
global $exif_head, $exif_data;
$lh=count($exif_head);
$ld=count($exif_data);
printf ("<h2>Exif size=%d bytes (head=%d, data=%d)</h2>\n",$lh+$ld,$lh,$ld);
printf ("<table border=\"0\">\n");
for ($i=0; $i<$lh+$ld;$i=$i+16) {
printf("<tr><td>%03x</td><td>|</td>\n",$i);
for ($j=$i; $j<$i+16;$j++) {
printf("<td>");
if ($j<($lh+$ld)) {
$d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh];
printf(" %02x",$d);
} else printf (" ");
printf("</td>");
}
printf("<td>|</td>");
for ($j=$i; $j< ($i+16);$j++) {
printf("<td>");
if ($j<($lh+$ld)) {
$d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh];
if ($d<32 or $d>126) printf(".");
else printf ("%c",$d);
} else printf (" ");
printf("</td>");
}
printf("</tr>\n");
}
printf ("</table>");
global $exif_head, $exif_data;
$lh=count($exif_head);
$ld=count($exif_data);
printf ("<h2>Exif size=%d bytes (head=%d, data=%d)</h2>\n",$lh+$ld,$lh,$ld);
printf ("<table border=\"0\">\n");
for ($i=0; $i<$lh+$ld;$i=$i+16) {
printf("<tr><td>%03x</td><td>|</td>\n",$i);
for ($j=$i; $j<$i+16;$j++) {
printf("<td>");
if ($j<($lh+$ld)) {
$d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh];
printf(" %02x",$d);
} else printf (" ");
printf("</td>");
}
printf("<td>|</td>");
for ($j=$i; $j< ($i+16);$j++) {
printf("<td>");
if ($j<($lh+$ld)) {
$d=($j<$lh)?$exif_head[$j]:$exif_data[$j-$lh];
if ($d<32 or $d>126) printf(".");
else printf ("%c",$d);
} else printf (" ");
printf("</td>");
}
printf("</tr>\n");
}
printf ("</table>");
}
function test_print_directory() {
global $dir_entries,$frame_meta_size;
printf ("<h2>Frame meta data size=%d bytes</h2>\n",$frame_meta_size);
printf ("<table border=\"1\">\n");
printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n");
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 ("</table>");
global $dir_entries,$frame_meta_size;
printf ("<h2>Frame meta data size=%d bytes</h2>\n",$frame_meta_size);
printf ("<table border=\"1\">\n");
printf ("<tr><td>ltag</td><td>meta offset</td><td>Exif offset</td><td>length</td></tr>\n");
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 ("</table>");
}
function start_ifd($count) {
global $exif_data, $ifd_pointer;
// printf("start_ifd: ifd_pointer=0x%04x \n", $ifd_pointer);
$exif_data[$ifd_pointer++]= ($count >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $count & 0xff; // may apply & 0xff in the end to all elements
global $exif_data, $ifd_pointer;
// printf("start_ifd: ifd_pointer=0x%04x \n", $ifd_pointer);
$exif_data[$ifd_pointer++]= ($count >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $count & 0xff; // may apply & 0xff in the end to all elements
}
function finish_ifd() { // we do not have additional IFDs
global $exif_data, $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;
global $exif_data, $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;
}
//pass2 - building map from frame meta to Exif template
function addDirEntry($ifd_entry) {
global $dir_sequence,$dir_entries,$exif_head;
$lh=count($exif_head);
$attrs = $ifd_entry->attributes();
// var_dump($attrs);
// if (array_key_exists ( "seq" , $attrs )) {
if ($attrs["seq"]) {
// echo $attrs["seq"].;
$dir_sequence[]=((string) $attrs["seq"])+0;
$len= (integer) $ifd_entry->value_length;
$offs=$lh+(integer) $ifd_entry->value_offest;
// if (array_key_exists ( "dlen" , $attrs ))
if ($attrs["dlen"]) $len=min($len,((string) $attrs["dlen"])+0);
$dir_entries[]=array("ltag"=>((integer)$ifd_entry->ltag),"dst"=>$offs,"len"=>$len);
}
global $dir_sequence,$dir_entries,$exif_head;
$lh=count($exif_head);
$attrs = $ifd_entry->attributes();
// var_dump($attrs);
// if (array_key_exists ( "seq" , $attrs )) {
if ($attrs["seq"]) {
// echo $attrs["seq"].;
$dir_sequence[]=((string) $attrs["seq"])+0;
$len= (integer) $ifd_entry->value_length;
$offs=$lh+(integer) $ifd_entry->value_offest;
// if (array_key_exists ( "dlen" , $attrs ))
if ($attrs["dlen"]) $len=min($len,((string) $attrs["dlen"])+0);
$dir_entries[]=array("ltag"=>((integer)$ifd_entry->ltag),"dst"=>$offs,"len"=>$len);
}
}
function substitute_value($ifd_entry) {
global $SUB_IFD_offset,$GPSInfo_offset;
$attrs = $ifd_entry->attributes();
switch ($attrs["function"]) {
case "BRAND":
$ifd_entry->addChild ('value',exec("bootblocktool -x BRAND"));
break;
case "MODEL":
if (file_exists ('/var/state/APPLICATION')) {
$model= file_get_contents('/var/state/APPLICATION');
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");
}
/// $ifd_entry->addChild ('value',exec("bootblocktool -x MODEL").exec("bootblocktool -x REVISION"));
$ifd_entry->addChild ('value',$model);
break;
case "SOFTWARE":
$ifd_entry->addChild ('value',exec("ls /usr/html/docs/")); // filter
break;
case "SERIAL":
$s=exec("bootblocktool -x SERNO");
$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));
break;
case "EXIFTAG":
$ifd_entry->addChild ('value',$SUB_IFD_offset);
break;
case "GPSTAG":
$ifd_entry->addChild ('value',$GPSInfo_offset);
break;
}
global $SUB_IFD_offset,$GPSInfo_offset;
global $DeviceSNFilename, $DeviceRevisionFilename, $DeviceBrand, $DeviceModel;
$attrs = $ifd_entry->attributes();
switch ($attrs["function"]) {
case "BRAND":
$ifd_entry->addChild('value', $DeviceBrand);
break;
case "MODEL":
if (file_exists ('/var/state/APPLICATION')) {
$model= file_get_contents('/var/state/APPLICATION');
if (file_exists ('/var/state/APPLICATION_MODE')) {
$model.=' CHN'.file_get_contents('/var/state/APPLICATION_MODE');
}
} else {
$model = $DeviceModel;
}
$ifd_entry->addChild ('value',$model);
break;
case "SOFTWARE":
if (file_exists("/usr/html/docs/")) {
$ifd_entry->addChild ('value',exec("ls /usr/html/docs/")); // filter
}
break;
case "SERIAL":
$s = "";
if (file_exists($DeviceSNFilename)) {
$s = exec('cat '.$DeviceSNFilename);
}
$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));
break;
case "EXIFTAG":
$ifd_entry->addChild ('value',$SUB_IFD_offset);
break;
case "GPSTAG":
$ifd_entry->addChild ('value',$GPSInfo_offset);
break;
}
}
function process_ifd_entry($ifd_entry, $group) {
global $exif_data, $ifd_pointer, $data_pointer,$SUB_IFD_offset,$GPSInfo_offset;
$attrs = $ifd_entry->attributes();
$ifd_tag= ((string) $attrs["tag"])+0;
$ifd_format=constant("EXIF_".$attrs["format"]);
$ifd_count= $attrs["count"];
// echo "\nifd_tag=$ifd_tag, entry=";print_r($ifd_entry);
// echo "\nifd_count=$ifd_count";
// echo "\nifd_bytes:";var_dump($ifd_bytes);
if (!$ifd_count) {
if($ifd_format==EXIF_ASCII) $ifd_count=strlen($ifd_entry->value)+1;
else $ifd_count=1 ; /// may change?
}
//echo "\nifd_count=$ifd_count";
$exif_data[$ifd_pointer++]= ($ifd_tag >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $ifd_tag & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_format >> 8 ) & 0xff;
$exif_data[$ifd_pointer++]= $ifd_format & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_count >> 24) & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_count >> 16) & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_count >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $ifd_count & 0xff;
$ifd_bytes=0;
switch ($ifd_format) {
case EXIF_SHORT:
case EXIF_SSHORT: $ifd_bytes=2; break;
case EXIF_LONG:
case EXIF_SLONG: $ifd_bytes=4; break;
case EXIF_RATIONAL:
case EXIF_SRATIONAL: $ifd_bytes=8; break;
default: $ifd_bytes=1; //1,2,6,7
}
$ifd_bytes=$ifd_bytes*$ifd_count;
// now prepare ifd_data - array of bytes
switch ($ifd_format) {
case EXIF_BYTE:
case EXIF_SBYTE:
$ifd_data= array ();
foreach ($ifd_entry->value as $a) $ifd_data[]= $a & 0xff;
break;
case EXIF_ASCII:
$ifd_data= str_split($ifd_entry->value);
foreach($ifd_data as &$d) $d=ord($d);
break;
case EXIF_SHORT:
case EXIF_SSHORT:
$ifd_data= array ();
foreach ($ifd_entry->value as $a) $ifd_data=array_merge($ifd_data,array(($a >> 8) & 0xff, $a & 0xff));
break;
case EXIF_LONG:
case EXIF_SLONG:
$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));
break;
case EXIF_RATIONAL:
case EXIF_SRATIONAL:
$nom= array ();
foreach ($ifd_entry->nominator as $a) $nom[]= array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff);
$denom= array ();
foreach ($ifd_entry->denominator as $a) $denom[]=array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff);
$ifd_data= array ();
global $exif_data, $ifd_pointer, $data_pointer,$SUB_IFD_offset,$GPSInfo_offset;
$attrs = $ifd_entry->attributes();
$ifd_tag= ((string) $attrs["tag"])+0;
$ifd_format=constant("EXIF_".$attrs["format"]);
$ifd_count= $attrs["count"];
// echo "\nifd_tag=$ifd_tag, entry=";print_r($ifd_entry);
// echo "\nifd_count=$ifd_count";
// echo "\nifd_bytes:";var_dump($ifd_bytes);
if (!$ifd_count) {
if($ifd_format==EXIF_ASCII) $ifd_count=strlen($ifd_entry->value)+1;
else $ifd_count=1 ; /// may change?
}
//echo "\nifd_count=$ifd_count";
$exif_data[$ifd_pointer++]= ($ifd_tag >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $ifd_tag & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_format >> 8 ) & 0xff;
$exif_data[$ifd_pointer++]= $ifd_format & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_count >> 24) & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_count >> 16) & 0xff;
$exif_data[$ifd_pointer++]= ($ifd_count >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $ifd_count & 0xff;
$ifd_bytes=0;
switch ($ifd_format) {
case EXIF_SHORT:
case EXIF_SSHORT: $ifd_bytes=2; break;
case EXIF_LONG:
case EXIF_SLONG: $ifd_bytes=4; break;
case EXIF_RATIONAL:
case EXIF_SRATIONAL: $ifd_bytes=8; break;
default: $ifd_bytes=1; //1,2,6,7
}
$ifd_bytes=$ifd_bytes*$ifd_count;
// now prepare ifd_data - array of bytes
switch ($ifd_format) {
case EXIF_BYTE:
case EXIF_SBYTE:
$ifd_data= array ();
foreach ($ifd_entry->value as $a) $ifd_data[]= $a & 0xff;
break;
case EXIF_ASCII:
$ifd_data= str_split($ifd_entry->value);
foreach($ifd_data as &$d) $d=ord($d);
break;
case EXIF_SHORT:
case EXIF_SSHORT:
$ifd_data= array ();
foreach ($ifd_entry->value as $a) $ifd_data=array_merge($ifd_data,array(($a >> 8) & 0xff, $a & 0xff));
break;
case EXIF_LONG:
case EXIF_SLONG:
$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));
break;
case EXIF_RATIONAL:
case EXIF_SRATIONAL:
$nom= array ();
foreach ($ifd_entry->nominator as $a) $nom[]= array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff);
$denom= array ();
foreach ($ifd_entry->denominator as $a) $denom[]=array(($a >> 24) & 0xff,($a >> 16) & 0xff,($a >> 8) & 0xff, $a & 0xff);
$ifd_data= array ();
/*
var_dump($nom);
echo "\n";
var_dump($denom);
echo "\n";
//exit(0);
*/
for ($i=0;$i<count($nom);$i++) {
// echo "i=$i\n";
// echo "\nnom=";var_dump($nom[$i]);
// echo "\ndenom=";var_dump($denom[$i]);
$ifd_data=array_merge($ifd_data,$nom[$i],$denom[$i]);
}
break; // rational, (un)signed
case EXIF_UNDEFINED: // undefined
$ifd_data= array_fill(0,$ifd_bytes,0); // will just fill with "0"-s
break;
}
// echo "\nifd_tag=$ifd_tag, entry=";print_r($i=$ifd_entry->value);
// echo "\nifd_data:";var_dump($ifd_data);
// echo "\nifd_bytes:";var_dump($ifd_bytes);
$ifd_data=array_pad($ifd_data,$ifd_bytes,0);
$ifd_entry->addChild ('value_length',count($ifd_data));
// if (array_key_exists ( "ltag" , $attrs )) $ltag= ((string) $attrs["ltag"])+0;
if ($attr["ltag"]) $ltag= ((string) $attrs["ltag"])+0;
else $ltag= $ifd_tag+($group<<16) ;
$ifd_entry->addChild ("ltag",$ltag );
if (count($ifd_data) <=4) {
$ifd_entry->addChild ('value_offest',$ifd_pointer);
$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];
} else { //pointer, not data
$ifd_entry->addChild ('value_offest',$data_pointer);
$exif_data[$ifd_pointer++]= ($data_pointer >> 24) & 0xff;
$exif_data[$ifd_pointer++]= ($data_pointer >> 16) & 0xff;
$exif_data[$ifd_pointer++]= ($data_pointer >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $data_pointer & 0xff;
for ($i=0;$i<count($ifd_data);$i++) {
$exif_data[$data_pointer++]=$ifd_data[$i];
}
}
*/
for ($i=0;$i<count($nom);$i++) {
// echo "i=$i\n";
// echo "\nnom=";var_dump($nom[$i]);
// echo "\ndenom=";var_dump($denom[$i]);
$ifd_data=array_merge($ifd_data,$nom[$i],$denom[$i]);
}
break; // rational, (un)signed
case EXIF_UNDEFINED: // undefined
$ifd_data= array_fill(0,$ifd_bytes,0); // will just fill with "0"-s
break;
}
// echo "\nifd_tag=$ifd_tag, entry=";print_r($i=$ifd_entry->value);
// echo "\nifd_data:";var_dump($ifd_data);
// echo "\nifd_bytes:";var_dump($ifd_bytes);
$ifd_data=array_pad($ifd_data,$ifd_bytes,0);
$ifd_entry->addChild ('value_length',count($ifd_data));
// if (array_key_exists ( "ltag" , $attrs )) $ltag= ((string) $attrs["ltag"])+0;
if ($attr["ltag"]) $ltag= ((string) $attrs["ltag"])+0;
else $ltag= $ifd_tag+($group<<16) ;
$ifd_entry->addChild ("ltag",$ltag );
if (count($ifd_data) <=4) {
$ifd_entry->addChild ('value_offest',$ifd_pointer);
$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];
} else { //pointer, not data
$ifd_entry->addChild ('value_offest',$data_pointer);
$exif_data[$ifd_pointer++]= ($data_pointer >> 24) & 0xff;
$exif_data[$ifd_pointer++]= ($data_pointer >> 16) & 0xff;
$exif_data[$ifd_pointer++]= ($data_pointer >> 8) & 0xff;
$exif_data[$ifd_pointer++]= $data_pointer & 0xff;
for ($i=0;$i<count($ifd_data);$i++) {
$exif_data[$data_pointer++]=$ifd_data[$i];
}
}
}
?>
......@@ -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) {
switch (dir_table_entry.ltag) {
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_SubSecTimeOriginal: indx = Exif_Photo_SubSecTimeOriginal_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)
saferead255(fd_exif, val, exif_dir[Exif_Image_ImageDescription_Index].len);
printf("<ImageDescription>\"%s\"</ImageDescription>\n", val);
}
///Exif_Image_FrameNumber_Index 0x13
if (exif_dir[Exif_Image_FrameNumber_Index].ltag == Exif_Image_FrameNumber) { // Exif_Image_FrameNumber_Index is present in template
///Exif_Image_ImageNumber_Index 0x13
if (exif_dir[Exif_Image_ImageNumber_Index].ltag == Exif_Image_ImageNumber) { // Exif_Image_ImageNumber_Index is present in template
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);
read(fd_exif, rational3, 4);
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
......
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