Commit 2433f6a3 authored by Andrey Filippov's avatar Andrey Filippov

project setup, exif

parent 7320ec95
...@@ -16,36 +16,37 @@ ...@@ -16,36 +16,37 @@
</extensions> </extensions>
</storageModule> </storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> <storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="0.253868715" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg"> <configuration artifactName="${ProjName}" buildProperties="" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="0.253868715" name="Default" optionalBuildProperties="" parent="org.eclipse.cdt.build.core.prefbase.cfg">
<folderInfo id="0.253868715." name="/" resourcePath=""> <folderInfo id="0.253868715." name="/" resourcePath="">
<toolChain errorParsers="" id="org.eclipse.cdt.build.core.prefbase.toolchain.1179427350" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain"> <toolChain errorParsers="" id="org.eclipse.cdt.build.core.prefbase.toolchain.1179427350" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
<targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="org.eclipse.cdt.build.core.prefbase.toolchain.1179427350.1398057461" name=""/> <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="org.eclipse.cdt.build.core.prefbase.toolchain.1179427350.1398057461" name=""/>
<builder arguments="apps-imgsrv" command="${workspace_loc:/elphel-apps-imgsrv/scripts/run_bitbake.sh}" enableCleanBuild="false" errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator" id="org.eclipse.cdt.build.core.settings.default.builder.580164057" incrementalBuildTarget="-c compile -f" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/> <builder arguments="apps-imgsrv" command="${workspace_loc:/elphel-apps-imgsrv/scripts/run_bitbake.sh}" enableCleanBuild="false" errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator" id="org.eclipse.cdt.build.core.settings.default.builder.580164057" incrementalBuildTarget="-c compile -f" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<tool errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="org.eclipse.cdt.build.core.settings.holder.libs.2129855326" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/> <tool errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="org.eclipse.cdt.build.core.settings.holder.libs.2129855326" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
<tool errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="org.eclipse.cdt.build.core.settings.holder.745731625" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder"> <tool errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="org.eclipse.cdt.build.core.settings.holder.745731625" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.1859993711" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths"/> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.build.core.settings.holder.incpaths.1859993711" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
<option id="org.eclipse.cdt.build.core.settings.holder.symbols.798371956" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols"> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/elphel-apps-imgsrv/sysroots/usr/include-uapi}&quot;"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.build.core.settings.holder.symbols.798371956" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__arm__=1"/> <listOptionValue builtIn="false" value="__arm__=1"/>
<listOptionValue builtIn="true" value="__arm__=1"/> <listOptionValue builtIn="true" value="__arm__=1"/>
</option> </option>
<option id="org.eclipse.cdt.build.core.settings.holder.undef.symbols.1804718883" superClass="org.eclipse.cdt.build.core.settings.holder.undef.symbols" valueType="undefDefinedSymbols"/> <option id="org.eclipse.cdt.build.core.settings.holder.undef.symbols.1804718883" name="Undefined Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.undef.symbols"/>
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.58661368" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/> <inputType id="org.eclipse.cdt.build.core.settings.holder.inType.58661368" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool> </tool>
<tool errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="org.eclipse.cdt.build.core.settings.holder.1227611439" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder"> <tool errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="org.eclipse.cdt.build.core.settings.holder.1227611439" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.40980442" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.build.core.settings.holder.incpaths.40980442" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/linux-elphel/linux/source/include/uapi/elphel}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/elphel-apps-imgsrv/sysroots/usr/include-uapi}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/elphel-apps-imgsrv/sysroots/elphel393/usr/include-uapi}&quot;"/>
</option> </option>
<option id="org.eclipse.cdt.build.core.settings.holder.symbols.10916844" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.build.core.settings.holder.symbols.10916844" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__arm__=1"/> <listOptionValue builtIn="false" value="__arm__=1"/>
</option> </option>
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1739426241" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/> <inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1739426241" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool> </tool>
<tool errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="org.eclipse.cdt.build.core.settings.holder.176385540" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder"> <tool errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="org.eclipse.cdt.build.core.settings.holder.176385540" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.1931881995" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.build.core.settings.holder.incpaths.1931881995" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/elphel-apps-imgsrv/sysroots/elphel393/usr/include-uapi}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/elphel-apps-imgsrv/sysroots/usr/include-uapi}&quot;"/>
</option> </option>
<option id="org.eclipse.cdt.build.core.settings.holder.symbols.226200006" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.build.core.settings.holder.symbols.226200006" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__arm__=1"/> <listOptionValue builtIn="false" value="__arm__=1"/>
</option> </option>
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1408747788" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/> <inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1408747788" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
......
...@@ -26,8 +26,13 @@ ...@@ -26,8 +26,13 @@
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand> <buildCommand>
<name>org.python.pydev.PyDevBuilder</name> <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments> <arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.python.pydev.PyDevBuilder.launch</value>
</dictionary>
</arguments> </arguments>
</buildCommand> </buildCommand>
</buildSpec> </buildSpec>
......
...@@ -2,13 +2,15 @@ ...@@ -2,13 +2,15 @@
<!-- <!--
attributes: attributes:
tag - Exif tag (full tag in the camera will combine tag and group<<16 tag - Exif tag (full tag in the camera will combine tag and group<<16
format: format (BYTE/ASCII/SHORT/LONG/RATIONAL/UNDEFINED?SLONG?SRATIONAL format: format (BYTE/ASCII/SHORT/LONG/RATIONAL/UNDEFINED?SLONG?SRATIONAL
count: number of values (characters in ASCII) count: number of values (characters in ASCII)
seq: sequence number of the variable data field (stored in a frame buffer) seq: sequence number of the variable data field (stored in a frame buffer)
If not specified - static data If not specified - static data. Values are used only for ordering.
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 (not used)
SubSecTimeOriginal should go immediately after DateTimeOriginal (in the sequence numbers, not in the Exif templete) function: use exif.php to provide value/size
mode: E(Exif only), T(Tiff only), B(Both). If not specified - both
SubSecTimeOriginal should go immediately after DateTimeOriginal (in the sequence numbers, not in the Exif template)
Update, June 2016: PageNumber field is used as sensor port number, HostComputer field is replaced with CameraSerialNumber and 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. FrameNumber field (which actually was IPTCNAA field) is replaced with standart ImageNumber field.
...@@ -31,6 +33,23 @@ ...@@ -31,6 +33,23 @@
<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"/>
<GPSTag tag="0x08825" format="LONG" function="GPSTAG"/> <GPSTag tag="0x08825" format="LONG" function="GPSTAG"/>
<!-- Tiff only -->
<NewSubfileType tag="0x00fe" format="LONG" count="1" dlen="4" mode="T">
<value> 0 </value><!-- (not reduced, not multipage, not mask) -->
</NewSubfileType>
<ImageWidth tag="0x0100" format="LONG" count="1" seq="30" dlen="4" mode="T"/>
<ImageLength tag="0x0101" format="LONG" count="1" seq="31" dlen="4" mode="T"/>
<BitsPerSample tag="0x0102" format="SHORT" count="1" seq="32" dlen="2" mode="T"/>
<PhotometricInterpretation tag="0x0106" format="SHORT" count="1" dlen="2" mode="T">
<value> 1 </value><!-- black is zero -->
</PhotometricInterpretation>
<!-- <StripOffsets tag="0x0111" format="LONG" function="STRIPOFFSETS" mode="T"/>--> <!-- offset to actual image -->
<StripOffsets tag="0x0111" format="LONG" count="1" dlen="4" mode="T"/> <!-- offset to actual image -->
<SamplesPerPixel tag="0x0115" format="SHORT" count="1" seq="33" dlen="2" mode="T">
<value> 1 </value><!-- One color per pixel, will be overwritten by driver -->
</SamplesPerPixel>
<RowsPerStrip tag="0x0116" format="SHORT" count="1" seq="34" dlen="2" mode="T"/>
<StripByteCounts tag="0x0117" format="LONG" count="1" seq="35" dlen="4" mode="T"/>
</Image> </Image>
<Photo> <Photo>
<ExposureTime tag="0x829a" format="RATIONAL" seq="3" dlen="4"> <ExposureTime tag="0x829a" format="RATIONAL" seq="3" dlen="4">
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*! 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)
*! chn=0..3 - sensor channel
*! *!
*! Copyright (C) 2007-2016 Elphel, Inc *! Copyright (C) 2007-2016 Elphel, Inc
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
...@@ -89,9 +90,20 @@ $chn = 0; ...@@ -89,9 +90,20 @@ $chn = 0;
$ExifDeviceTemplateFilename="/dev/exif_template"; $ExifDeviceTemplateFilename="/dev/exif_template";
$ExifDeviceMetadirFilename= "/dev/exif_metadir"; $ExifDeviceMetadirFilename= "/dev/exif_metadir";
$TiffDeviceTemplateFilename="/dev/tiff_template";
$ExifDeviceExifFilename= "/dev/exif_exif"; $ExifDeviceExifFilename= "/dev/exif_exif";
$TiffDeviceTiffFilename= "/dev/tiff_tiff";
$ExifDeviceMetaFilename= "/dev/exif_meta"; $ExifDeviceMetaFilename= "/dev/exif_meta";
///$ExifDeviceTemplateFilename="/dev/null";
///$ExifDeviceMetadirFilename= "/dev/null";
///$TiffDeviceTemplateFilename="/dev/null";
///$ExifDeviceExifFilename= "/dev/null";
///$ExifDeviceMetaFilename= "/dev/null";
$DeviceSNFilename = "/sys/devices/soc0/elphel393-init/serial"; $DeviceSNFilename = "/sys/devices/soc0/elphel393-init/serial";
$DeviceRevisionFilename = "/sys/devices/soc0/elphel393-init/revision"; $DeviceRevisionFilename = "/sys/devices/soc0/elphel393-init/revision";
$DeviceBrand = "Elphel"; $DeviceBrand = "Elphel";
...@@ -100,7 +112,9 @@ $DeviceModel = "Elphel393"; ...@@ -100,7 +112,9 @@ $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
$ExifXMLName="/etc/Exif_template.xml"; /// $ExifXMLName="/etc/Exif_template.xml";
$ExifXMLName="./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) {
...@@ -111,7 +125,8 @@ if ($_SERVER['REQUEST_METHOD']=="GET") { ...@@ -111,7 +125,8 @@ if ($_SERVER['REQUEST_METHOD']=="GET") {
} }
if (isset($_GET['chn'])) $chn = $_GET['chn']; if (isset($_GET['chn'])) $chn = $_GET['chn'];
$ExifDeviceExifFilename .= $chn; $ExifDeviceExifFilename .= $chn;
$ExifDeviceMetaFilename .= $chn; $ExifDeviceMetaFilename .= $chn;
$TiffDeviceTiffFilename .= $chn;
} 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);
...@@ -149,7 +164,7 @@ define("EXIF_LSEEK_ENABLE", 2); // rebuild buffer ...@@ -149,7 +164,7 @@ 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 at byte 2 of the file
// 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
...@@ -159,90 +174,232 @@ if ($init) { // configure Exif data ...@@ -159,90 +174,232 @@ if ($init) { // configure Exif data
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); $tiff_data= array (// start of TIFF Header, data offsets will match indexes in this array
if ($xml_exif->GPSInfo) { 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_both = simplexml_load_file($ExifXMLName); // include tags for either Exif or Tiff
if ($xml_both->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_both->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_both->GPSInfo->{$entry});
} }
if ($noGPS) { if ($noGPS) {
unset($xml_exif->GPSInfo); unset($xml_both->GPSInfo);
unset($xml_exif->Image->GPSTag); unset($xml_both->Image->GPSTag);
} }
} }
// now copy filtered $xml_both to $xml_exif and $xml_tiff to filter them separately
$IFD_offset= count($exif_data); $xml_exif = simplexml_load_string ( $xml_both->asXML());
$SUB_IFD_offset= 12*count($xml_exif->Image->children())+2+4+$IFD_offset; foreach ($xml_exif->children() as $group){
$GPSInfo_offset= 12*count($xml_exif->Photo->children())+2+4+$SUB_IFD_offset; $tounset=array();
$data_offset= $GPSInfo_offset+(($xml_exif->GPSInfo)?(12*count($xml_exif->GPSInfo->children())+2+4):0); //$GPSInfo is optional foreach ($group->children() as $entry) if ($entry->attributes()['mode'] == 'T') $tounset[]=$entry->getName(); // keep if no mode, mode =='E' or mode == 'B'
foreach ($tounset as $entry) unset ($group->{$entry});
}
$xml_tiff = simplexml_load_string ( $xml_both->asXML());
foreach ($xml_tiff->children() as $group){
$tounset=array();
foreach ($group->children() as $entry) if ($entry->attributes()['mode'] == 'E') $tounset[]=$entry->getName(); // keep if no mode, mode =='E' or mode == 'B'
foreach ($tounset as $entry) unset ($group->{$entry});
}
$IFD_offset_exif= count($exif_data); // 8
$SUB_IFD_offset_exif= 12*count($xml_exif->Image->children())+2+4+$IFD_offset_exif; // length of Image (main) IFD including length and offset to next
$GPSInfo_offset_exif= 12*count($xml_exif->Photo->children())+2+4+$SUB_IFD_offset_exif;// length of Photo IFD including length and offset to next
// Include or skip GPS IFD
$data_offset_exif= $GPSInfo_offset_exif+(($xml_exif->GPSInfo)?(12*count($xml_exif->GPSInfo->children())+2+4):0); //$GPSInfo is optional
$IFD_offset_tiff= count($tiff_data); // 8
$SUB_IFD_offset_tiff= 12*count($xml_tiff->Image->children())+2+4+$IFD_offset_tiff; // length of Image (main) IFD including length and offset to next
$GPSInfo_offset_tiff= 12*count($xml_tiff->Photo->children())+2+4+$SUB_IFD_offset_tiff;// length of Photo IFD including length and offset to next
// Include or skip GPS IFD
$data_offset_tiff= $GPSInfo_offset_tiff+(($xml_tiff->GPSInfo)?(12*count($xml_tiff->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_exif=0x%x\n",$IFD_offset_exif);
printf ("SUB_IFD_offset=0x%x\n",$SUB_IFD_offset); printf ("SUB_IFD_offset_exif=0x%x\n",$SUB_IFD_offset_exif);
printf ("GPSInfo_offset=0x%x\n",$GPSInfo_offset); printf ("GPSInfo_offset_exif=0x%x\n",$GPSInfo_offset_exif);
printf ("data_offset=0x%x\n",$data_offset); printf ("data_offset_exif=0x%x\n",$data_offset_exif);
printf ("IFD_offset_tiff=0x%x\n",$IFD_offset_tiff);
printf ("SUB_IFD_offset_tiff=0x%x\n",$SUB_IFD_offset_tiff);
printf ("GPSInfo_offset_tiff=0x%x\n",$GPSInfo_offset_tiff);
printf ("data_offset_tiff=0x%x\n",$data_offset_tiff);
} }
/*
/// Now modify variable fields substituting values IFD_offset=0x8
foreach ($xml_exif->Image->children() as $entry) substitute_value($entry); SUB_IFD_offset=0x86
foreach ($xml_exif->Photo->children() as $entry) substitute_value($entry); GPSInfo_offset=0xbc
data_offset=0xbc
*/
// printf("\n\n1 - exif_head:\n"); print_r($exif_head);
// printf("\n\n1 - exif_data\n"); print_r($exif_data);
// printf("\n\n1 - tiff_data\n"); print_r($tiff_data);
/// Now modify variable fields substituting values. Has to be separate, as it uses addresses calculated from remaining tags ($SUB_IFD_offset_*,$GPSInfo_offset_*
// for ---- Exif ----
foreach ($xml_exif->Image->children() as $entry) substitute_value($entry, $SUB_IFD_offset_exif, $GPSInfo_offset_exif);
foreach ($xml_exif->Photo->children() as $entry) substitute_value($entry, $SUB_IFD_offset_exif, $GPSInfo_offset_exif);
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, $SUB_IFD_offset_exif, $GPSInfo_offset_exif);
} }
$ifd_pointer=$IFD_offset; $ifd_pointer_exif=$IFD_offset_exif;
$data_pointer=$data_offset; $data_pointer_exif=$data_offset_exif;
start_ifd(count($xml_exif->Image->children())); // printf("ifd_pointer_exif= % d, data_pointer_exif = %d, count(xml_exif->Image->children())=%d\n",$ifd_pointer_exif, $data_pointer_exif, count($xml_exif->Image->children()));
foreach ($xml_exif->Image->children() as $entry) process_ifd_entry($entry,0);
finish_ifd(); start_ifd(count($xml_exif->Image->children()), $exif_data, $ifd_pointer_exif);
$ifd_pointer=$SUB_IFD_offset; // printf("ifd_pointer_exif= % d, data_pointer_exif = %d\n",$ifd_pointer_exif, $data_pointer_exif);
start_ifd(count($xml_exif->Photo->children())); // printf("\n\n0 - exif_data\n"); print_r($exif_data);
foreach ($xml_exif->Photo->children() as $entry) process_ifd_entry($entry,1);
finish_ifd(); foreach ($xml_exif->Image->children() as $entry) process_ifd_entry($entry, 0, $exif_data, $ifd_pointer_exif, $data_pointer_exif, $SUB_IFD_offset_exif, $GPSInfo_offset_exif);
finish_ifd($exif_data, $ifd_pointer_exif);
$ifd_pointer_exif=$SUB_IFD_offset_exif;
start_ifd(count($xml_exif->Photo->children()), $exif_data, $ifd_pointer_exif);
foreach ($xml_exif->Photo->children() as $entry) process_ifd_entry($entry, 1, $exif_data, $ifd_pointer_exif, $data_pointer_exif, $SUB_IFD_offset_exif, $GPSInfo_offset_exif);
finish_ifd($exif_data, $ifd_pointer_exif);
if ($xml_exif->GPSInfo) { if ($xml_exif->GPSInfo) {
$ifd_pointer=$GPSInfo_offset; $ifd_pointer_exif=$GPSInfo_offset_exif;
start_ifd(count($xml_exif->GPSInfo->children())); start_ifd(count($xml_exif->GPSInfo->children()), $exif_data, $ifd_pointer_exif);
foreach ($xml_exif->GPSInfo->children() as $entry) process_ifd_entry($entry,2); foreach ($xml_exif->GPSInfo->children() as $entry) process_ifd_entry($entry, 2, $exif_data, $ifd_pointer_exif, $data_pointer_exif, $SUB_IFD_offset_exif, $GPSInfo_offset_exif);
finish_ifd(); finish_ifd($exif_data, $ifd_pointer_exif);
} }
$exif_len=count($exif_head)+count($exif_data)-$Exif_length_offset; $exif_len=count($exif_head)+count($exif_data)-$Exif_length_offset;
// printf("\nexif_len = %d, Exif_length_offset = %d\n",$exif_len, $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;
// printf("\n\n2 - exif_head:\n"); print_r($exif_head);
// printf("\n\n2 - exif_data\n"); print_r($exif_data);
// ---- for Tiff ---- Need to catch $STRIPOFFSETS
foreach ($xml_tiff->Image->children() as $entry) substitute_value($entry, $SUB_IFD_offset_tiff, $GPSInfo_offset_tiff);
foreach ($xml_tiff->Photo->children() as $entry) substitute_value($entry, $SUB_IFD_offset_tiff, $GPSInfo_offset_tiff);
if ($xml_tiff->GPSInfo) {
foreach ($xml_tiff->GPSInfo->children() as $entry) substitute_value($entry, $SUB_IFD_offset_tiff, $GPSInfo_offset_tiff);
}
$ifd_pointer_tiff=$IFD_offset_tiff;
$data_pointer_tiff=$data_offset_tiff;
start_ifd(count($xml_tiff->Image->children()), $tiff_data, $ifd_pointer_tiff);
foreach ($xml_tiff->Image->children() as $entry) {
if ($entry->getName() == "StripOffsets") {
$StripOffsets_ifd_pointer = $ifd_pointer_tiff; // put STRIPOFFSET long here when known
$StripOffsets_data_pointer = $data_pointer_tiff; // put STRIPOFFSET long here when known
$StripOffsets_entry = $entry;
}
process_ifd_entry($entry, 0, $tiff_data, $ifd_pointer_tiff, $data_pointer_tiff, $SUB_IFD_offset_tiff, $GPSInfo_offset_tiff);
}
finish_ifd($tiff_data, $ifd_pointer_tiff);
$ifd_pointer_tiff=$SUB_IFD_offset_tiff;
start_ifd(count($xml_tiff->Photo->children()), $tiff_data, $ifd_pointer_tiff);
foreach ($xml_tiff->Photo->children() as $entry) process_ifd_entry($entry, 1, $tiff_data, $ifd_pointer_tiff, $data_pointer_tiff, $SUB_IFD_offset_tiff, $GPSInfo_offset_tiff);
finish_ifd($tiff_data, $ifd_pointer_tiff);
if ($xml_tiff->GPSInfo) {
$ifd_pointer_tiff=$GPSInfo_offset_tiff;
start_ifd(count($xml_tiff->GPSInfo->children()), $tiff_data, $ifd_pointer_tiff);
foreach ($xml_tiff->GPSInfo->children() as $entry) process_ifd_entry($entry, 2, $tiff_data, $ifd_pointer_tiff, $data_pointer_tiff, $SUB_IFD_offset_tiff, $GPSInfo_offset_tiff);
finish_ifd($tiff_data, $ifd_pointer_tiff);
}
// printf("\n\nbefore STRIPOFFSETS - tiff_data\n"); print_r($tiff_data);
// printf("StripOffsets_ifd_pointer= 0x%x (%d)\n", $StripOffsets_ifd_pointer, $StripOffsets_ifd_pointer);
// printf("StripOffsets_data_pointer=0x%x (%d)\n", $StripOffsets_data_pointer, $StripOffsets_data_pointer);
// printf("count(tiff_data)=0x%x (%d)\n", count($tiff_data), count($tiff_data));
if ($StripOffsets_ifd_pointer) {
// echo "StripOffsets_entry:";
// echo $StripOffsets_entry->getName();
$StripOffsets_entry->addChild('value', count($tiff_data));
// re-process
// process_ifd_entry($StripOffsets_entry, 0, $tiff_data, $StripOffsets_ifd_pointer, $StripOffsets_data_pointer, $SUB_IFD_offset_tiff, $GPSInfo_offset_tiff, 1);
process_ifd_entry($StripOffsets_entry, 0, $tiff_data, $StripOffsets_ifd_pointer, $StripOffsets_data_pointer, $SUB_IFD_offset_tiff, $GPSInfo_offset_tiff);
}
$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]);
// printf("\ - Exif_str\n"); hexdump($Exif_str);
$Tiff_str="";
for ($i=0; $i<count($tiff_data);$i++) $Tiff_str.= chr ($tiff_data[$i]);
// printf("\ - Tiff_str\n"); hexdump($Tiff_str);
$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. $Tiff_file = fopen($TiffDeviceTemplateFilename, 'w');
$dir_sequence=array(); fwrite ($Tiff_file,$Tiff_str); /// will disable and invalidate Exif data
$dir_entries=array(); fclose($Tiff_file);
foreach ($xml_exif->Image->children() as $entry) addDirEntry($entry); $dir_entries_exif=array();
foreach ($xml_exif->Photo->children() as $entry) addDirEntry($entry); $exif_head_length = count($exif_head);
foreach ($xml_exif->Image->children() as $entry) addDirEntry($entry, $dir_entries_exif, $exif_head_length);
foreach ($xml_exif->Photo->children() as $entry) addDirEntry($entry, $dir_entries_exif, $exif_head_length);
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, $dir_entries_exif, $exif_head_length);
}
// printf("\ndir_entries_exif:\n"); print_r($dir_entries_exif);
ksort ($dir_entries_exif);
// printf("\ndir_entries_exif sorted:\n"); print_r($dir_entries_exif);
$dir_entries_tiff=array();
foreach ($xml_tiff->Image->children() as $entry) addDirEntry($entry, $dir_entries_tiff, 0);
foreach ($xml_tiff->Photo->children() as $entry) addDirEntry($entry, $dir_entries_tiff, 0);
if ($xml_tiff->GPSInfo) {
foreach ($xml_tiff->GPSInfo->children() as $entry) addDirEntry($entry, $dir_entries_tiff, 0);
}
// printf("\ndir_entries_tiff:\n"); print_r($dir_entries_tiff);
ksort ($dir_entries_tiff);
// printf("\ndir_entries_tiff sorted:\n"); print_r($dir_entries_tiff);
// combine directories
$dir_entries=array();
foreach ($dir_entries_exif as $key => $value){
$dir_entries[$key] = array("ltag"=>$value['ltag'],"dst_exif"=>$value['dst'],"dst_tiff"=>0,"len"=>$value['len']);
}
foreach ($dir_entries_tiff as $key => $value){
if (array_key_exists($key, $dir_entries)){
$dir_entries[$key]["dst_tiff"] = $value['dst'];
} else {
$dir_entries[$key] = array("ltag"=>$value['ltag'],"dst_exif"=>0,"dst_tiff"=>$value['dst'],"len"=>$value['len']);
}
} }
array_multisort($dir_sequence,$dir_entries); ksort ($dir_entries);
// get rid of keys:
$dir_entries_val=array();
foreach ($dir_entries as $value)$dir_entries_val[] = $value;
$dir_entries = $dir_entries_val;
$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"];
} }
// printf("\ndir_entries sorted:\n"); print_r($dir_entries);
$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"] +($entry["dst_tiff"] << 16)));
// printf("\ - Exif_str (directory)\n"); hexdump($Exif_str);
$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');
...@@ -254,10 +411,14 @@ if ($init) { // configure Exif data ...@@ -254,10 +411,14 @@ if ($init) { // configure Exif data
} }
if ($_SERVER['REQUEST_METHOD']) { if ($_SERVER['REQUEST_METHOD']) {
echo "<hr/>\n"; echo "<hr/>\n";
test_print_header(); test_print_header($exif_head, $exif_data);
echo "<hr/>\n";
$tiff_head=array(); // empty
test_print_header($tiff_head, $tiff_data);
echo "<hr/>\n"; echo "<hr/>\n";
test_print_directory(); test_print_directory($dir_entries,$frame_meta_size);
} }
} //if ($init) // configure Exif data } //if ($init) // configure Exif data
/// ===== processing optional parameters ======= /// ===== processing optional parameters =======
/// ===== read template ======= /// ===== read template =======
...@@ -304,6 +465,19 @@ if ($_GET["template"]!==NULL) { ...@@ -304,6 +465,19 @@ if ($_GET["template"]!==NULL) {
echo "read ".strlen($template)." bytes<br/>\n"; echo "read ".strlen($template)." bytes<br/>\n";
hexdump($template); hexdump($template);
} }
if ($_GET["template_tiff"]!==NULL) {
$Exif_file = fopen($TiffDeviceTemplateFilename, '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 ======= /// ===== read meta directory =======
if ($_GET["metadir"]!==NULL) { if ($_GET["metadir"]!==NULL) {
$Exif_file = fopen($ExifDeviceMetadirFilename, 'r'); $Exif_file = fopen($ExifDeviceMetadirFilename, 'r');
...@@ -336,12 +510,27 @@ if ($_GET["exif"]!==NULL) { ...@@ -336,12 +510,27 @@ if ($_GET["exif"]!==NULL) {
echo "read ".strlen($exif_data)." bytes<br/>\n"; echo "read ".strlen($exif_data)." bytes<br/>\n";
hexdump($exif_data); hexdump($exif_data);
} }
if ($_GET["tiff"]!==NULL) {
$frame=$_GET["tiff"]+0;
echo "<hr/>\n";
printf ("Reading frame %d from %s, ",$frame,$ExifDeviceTiffFilename);
$Tiff_file = fopen($TiffDeviceTiffFilename, 'r');
fseek ($Tiff_file, 1, SEEK_END) ;
$tiff_size=ftell($Tiff_file);
if ($frame) fseek ($Tiff_file, $frame, SEEK_END) ;
else fseek ($Tiff_file, 0, SEEK_SET) ;
echo "ftell()=".ftell($Tiff_file).", ";
$tiff_data=fread ($Tiff_file, $tiff_size);
fclose($Tiff_file);
echo "read ".strlen($tiff_data)." bytes<br/>\n";
hexdump($tiff_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>Data 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);
...@@ -374,18 +563,21 @@ function print_directory($dir_entries) { ...@@ -374,18 +563,21 @@ function print_directory($dir_entries) {
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><th>ltag</th><th>meta offset</th><th>Exif offset</th><th>Tiff offset</th><th>length</th></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]); $exif_offset = $entry[4] & 0xfff;
$tiff_offset = $entry[4] >> 16;
printf ("<tr><td>0x%x</td><td>0x%x</td><td>0x%x</td><td>0x%x</td><td>0x%x</td></tr>\n",$entry[1],$entry[3],$exif_offset,$tiff_offset,$entry[2]);
} }
printf ("</table>"); printf ("</table>");
} }
function test_print_header() { function test_print_header(&$exif_head, &$exif_data) {
global $exif_head, $exif_data; // global $exif_head, $exif_data;
$lh=count($exif_head); $lh = 0;
if ($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/Tiff 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);
...@@ -413,27 +605,30 @@ function test_print_header() { ...@@ -413,27 +605,30 @@ function test_print_header() {
printf ("</table>"); printf ("</table>");
} }
function test_print_directory() { function test_print_directory(&$dir_entries, &$frame_meta_size) {
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><th>ltag</th><th>meta offset</th><th>Exif offset</th><th>Tiff offset</th><th>length</th></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><td>0x%x</td></tr>\n",$entry["ltag"],$entry["src"],$entry["dst_exif"],$entry["dst_tiff"],$entry["len"]);
printf ("</table>"); printf ("</table>");
} }
function start_ifd($count) { function start_ifd($count, &$exif_data, &$ifd_pointer) {
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
// printf("++++start_ifd(): ifd_pointer= %d, exif_data=\n",$ifd_pointer); print_r($exif_data);
} }
function finish_ifd() { // we do not have additional IFDs function finish_ifd(&$exif_data, &$ifd_pointer) { // 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;
...@@ -443,9 +638,9 @@ function finish_ifd() { // we do not have additional IFDs ...@@ -443,9 +638,9 @@ function finish_ifd() { // we do not have additional IFDs
//pass2 - building map from frame meta to Exif template //pass2 - building map from frame meta to Exif template
function addDirEntry($ifd_entry) { function addDirEntry0($ifd_entry, &$dir_sequence, &$dir_entries, $lh) {
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);
...@@ -461,9 +656,30 @@ function addDirEntry($ifd_entry) { ...@@ -461,9 +656,30 @@ function addDirEntry($ifd_entry) {
} }
} }
function substitute_value($ifd_entry) { function addDirEntry($ifd_entry, &$dir_entries, $lh) {
global $SUB_IFD_offset,$GPSInfo_offset; // global $dir_sequence,$dir_entries,$exif_head;
global $DeviceSNFilename, $DeviceRevisionFilename, $DeviceBrand, $DeviceModel; // $lh=count($exif_head);
$attrs = $ifd_entry->attributes();
// var_dump($attrs);
// if (array_key_exists ( "seq" , $attrs )) {
if ($attrs["seq"]) {
// echo $attrs["seq"].;
$key=((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[$key]=array("ltag"=>((integer)$ifd_entry->ltag),"dst"=>$offs,"len"=>$len);
}
}
function substitute_value($ifd_entry, $SUB_IFD_offset, $GPSInfo_offset) {
// global $SUB_IFD_offset,$GPSInfo_offset;
global $DeviceSNFilename, $DeviceRevisionFilename, $DeviceBrand, $DeviceModel; // keep these globals
$attrs = $ifd_entry->attributes(); $attrs = $ifd_entry->attributes();
switch ($attrs["function"]) { switch ($attrs["function"]) {
...@@ -486,7 +702,7 @@ function substitute_value($ifd_entry) { ...@@ -486,7 +702,7 @@ function substitute_value($ifd_entry) {
$ifd_entry->addChild ('value',exec("ls /usr/html/docs/")); // filter $ifd_entry->addChild ('value',exec("ls /usr/html/docs/")); // filter
} }
*/ */
$ifd_entry->addChild ('value',"https://github.com/Elphel/elphel393"); $ifd_entry->addChild ('value',"https://git.elphel.com/Elphel/elphel393");
break; break;
case "SERIAL": case "SERIAL":
$s = ""; $s = "";
...@@ -501,19 +717,30 @@ function substitute_value($ifd_entry) { ...@@ -501,19 +717,30 @@ function substitute_value($ifd_entry) {
case "GPSTAG": case "GPSTAG":
$ifd_entry->addChild ('value',$GPSInfo_offset); $ifd_entry->addChild ('value',$GPSInfo_offset);
break; break;
// case "STRIPOFFSETS": // temporary - maybe remove this function
// $ifd_entry->addChild ('value',$GPSInfo_offset);
// break;
//STRIPOFFSETS
} }
} }
function process_ifd_entry($ifd_entry, $group) { function process_ifd_entry($ifd_entry, $group, &$exif_data, &$ifd_pointer, &$data_pointer, $SUB_IFD_offset, $GPSInfo_offset, $debug=0) {
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); if ($debug){
// echo "\nifd_count=$ifd_count"; echo "\nifd_tag "; echo $ifd_tag; echo "\n";
// echo "\nifd_bytes:";var_dump($ifd_bytes); echo "ifd_format "; echo $ifd_format; echo "\n";
echo "ifd_count "; echo $ifd_count; echo "\n";
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_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?
......
...@@ -308,10 +308,13 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -308,10 +308,13 @@ int printExifXML(int exif_page, struct file_set *fset)
&CameraSerialNumber[8], &CameraSerialNumber[8],
&CameraSerialNumber[10]); &CameraSerialNumber[10]);
//TODO: Check .dst_exif > 0, maybe add same for Tiff fields
// Image Description // Image Description
if (exif_dir[Exif_Image_ImageDescription_Index].ltag == Exif_Image_ImageDescription) { // Exif_Image_ImageDescription is present in template if (exif_dir[Exif_Image_ImageDescription_Index].ltag == Exif_Image_ImageDescription) { // Exif_Image_ImageDescription is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_Image_ImageDescription_Index].dst, exif_page_start + exif_dir[Exif_Image_ImageDescription_Index].dst_exif,
SEEK_SET); SEEK_SET);
saferead255(fset->exif_dev_fd, val, exif_dir[Exif_Image_ImageDescription_Index].len); saferead255(fset->exif_dev_fd, val, exif_dir[Exif_Image_ImageDescription_Index].len);
printf("<ImageDescription>\"%s\"</ImageDescription>\n", val); printf("<ImageDescription>\"%s\"</ImageDescription>\n", val);
...@@ -319,7 +322,7 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -319,7 +322,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Exif_Image_ImageNumber_Index 0x13 // Exif_Image_ImageNumber_Index 0x13
if (exif_dir[Exif_Image_ImageNumber_Index].ltag == Exif_Image_ImageNumber) { // Exif_Image_ImageNumber_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(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_Image_ImageNumber_Index].dst, exif_page_start + exif_dir[Exif_Image_ImageNumber_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, rational3, 4); read(fset->exif_dev_fd, rational3, 4);
sprintf(val, "%ld", (long)__cpu_to_be32( rational3[0])); sprintf(val, "%ld", (long)__cpu_to_be32( rational3[0]));
...@@ -329,7 +332,7 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -329,7 +332,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Exif_Image_Orientation_Index 0x14 // Exif_Image_Orientation_Index 0x14
if (exif_dir[Exif_Image_Orientation_Index].ltag == Exif_Image_Orientation) { // Exif_Image_Orientation_Index is present in template if (exif_dir[Exif_Image_Orientation_Index].ltag == Exif_Image_Orientation) { // Exif_Image_Orientation_Index is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_Image_Orientation_Index].dst, exif_page_start + exif_dir[Exif_Image_Orientation_Index].dst_exif,
SEEK_SET); SEEK_SET);
rational3[0] = 0; rational3[0] = 0;
read(fset->exif_dev_fd, rational3, 2); read(fset->exif_dev_fd, rational3, 2);
...@@ -340,7 +343,7 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -340,7 +343,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Exif_Image_PageNumber // Exif_Image_PageNumber
if (exif_dir[Exif_Image_PageNumber_Index].ltag == Exif_Image_PageNumber) { // Exif_Image_Orientation_Index is present in template if (exif_dir[Exif_Image_PageNumber_Index].ltag == Exif_Image_PageNumber) { // Exif_Image_Orientation_Index is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_Image_PageNumber_Index].dst, exif_page_start + exif_dir[Exif_Image_PageNumber_Index].dst_exif,
SEEK_SET); SEEK_SET);
rational3[0] = 0; rational3[0] = 0;
read(fset->exif_dev_fd, rational3, 2); read(fset->exif_dev_fd, rational3, 2);
...@@ -351,14 +354,14 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -351,14 +354,14 @@ int printExifXML(int exif_page, struct file_set *fset)
// DateTimeOriginal (with subseconds) // DateTimeOriginal (with subseconds)
if (exif_dir[Exif_Photo_DateTimeOriginal_Index].ltag == Exif_Photo_DateTimeOriginal) { if (exif_dir[Exif_Photo_DateTimeOriginal_Index].ltag == Exif_Photo_DateTimeOriginal) {
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_Photo_DateTimeOriginal_Index].dst, exif_page_start + exif_dir[Exif_Photo_DateTimeOriginal_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, val, 19); read(fset->exif_dev_fd, val, 19);
val[19] = '\0'; val[19] = '\0';
if (exif_dir[Exif_Photo_SubSecTimeOriginal_Index].ltag == Exif_Photo_SubSecTimeOriginal) { if (exif_dir[Exif_Photo_SubSecTimeOriginal_Index].ltag == Exif_Photo_SubSecTimeOriginal) {
val[19] = '.'; val[19] = '.';
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_Photo_SubSecTimeOriginal_Index].dst, exif_page_start + exif_dir[Exif_Photo_SubSecTimeOriginal_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, &val[20], 7); read(fset->exif_dev_fd, &val[20], 7);
val[27] = '\0'; val[27] = '\0';
...@@ -368,7 +371,7 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -368,7 +371,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Exif_Photo_ExposureTime // Exif_Photo_ExposureTime
if (exif_dir[Exif_Photo_ExposureTime_Index].ltag == Exif_Photo_ExposureTime) { // Exif_Photo_ExposureTime is present in template if (exif_dir[Exif_Photo_ExposureTime_Index].ltag == Exif_Photo_ExposureTime) { // Exif_Photo_ExposureTime is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_Photo_ExposureTime_Index].dst, exif_page_start + exif_dir[Exif_Photo_ExposureTime_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, rational3, 8); read(fset->exif_dev_fd, rational3, 8);
exposure = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]); exposure = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
...@@ -379,7 +382,7 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -379,7 +382,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Exif_Photo_MakerNote // Exif_Photo_MakerNote
if (exif_dir[Exif_Photo_MakerNote_Index].ltag == Exif_Photo_MakerNote) { // Exif_Photo_MakerNote is present in template if (exif_dir[Exif_Photo_MakerNote_Index].ltag == Exif_Photo_MakerNote) { // Exif_Photo_MakerNote is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_Photo_MakerNote_Index].dst, exif_page_start + exif_dir[Exif_Photo_MakerNote_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, makerNote, 64); read(fset->exif_dev_fd, makerNote, 64);
sprintf(val, sprintf(val,
...@@ -406,7 +409,7 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -406,7 +409,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS measure mode // GPS measure mode
if (exif_dir[Exif_GPSInfo_GPSMeasureMode_Index].ltag == Exif_GPSInfo_GPSMeasureMode) { if (exif_dir[Exif_GPSInfo_GPSMeasureMode_Index].ltag == Exif_GPSInfo_GPSMeasureMode) {
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_GPSMeasureMode_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSMeasureMode_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, val, 1); read(fset->exif_dev_fd, val, 1);
val[1] = '\0'; val[1] = '\0';
...@@ -416,13 +419,13 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -416,13 +419,13 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS date/time // GPS date/time
if (exif_dir[Exif_GPSInfo_GPSDateStamp_Index].ltag == Exif_GPSInfo_GPSDateStamp) { if (exif_dir[Exif_GPSInfo_GPSDateStamp_Index].ltag == Exif_GPSInfo_GPSDateStamp) {
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_GPSDateStamp_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSDateStamp_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, val, 10); read(fset->exif_dev_fd, val, 10);
val[10] = '\0'; val[10] = '\0';
if (exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].ltag == Exif_GPSInfo_GPSTimeStamp) { if (exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].ltag == Exif_GPSInfo_GPSTimeStamp) {
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, rational3, 24); read(fset->exif_dev_fd, rational3, 24);
hours = __cpu_to_be32( rational3[0]); hours = __cpu_to_be32( rational3[0]);
...@@ -433,7 +436,7 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -433,7 +436,7 @@ int printExifXML(int exif_page, struct file_set *fset)
printf("<GPSDateTime>\"%s\"</GPSDateTime>\n", val); printf("<GPSDateTime>\"%s\"</GPSDateTime>\n", val);
/* /*
printf("<DBGGPSDateTime>\"0x%x 0x%x 0x%x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\"</DBGGPSDateTime>\n", printf("<DBGGPSDateTime>\"0x%x 0x%x 0x%x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\"</DBGGPSDateTime>\n",
Exif_GPSInfo_GPSDateStamp, Exif_GPSInfo_GPSDateStamp_Index, exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].dst, Exif_GPSInfo_GPSDateStamp, Exif_GPSInfo_GPSDateStamp_Index, exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].dst_exif,
val[0],val[1],val[2],val[3],val[4],val[5],val[6],val[7],val[8],val[9],val[10],val[11],val[12]); val[0],val[1],val[2],val[3],val[4],val[5],val[6],val[7],val[8],val[9],val[10],val[11],val[12]);
*/ */
} }
...@@ -442,13 +445,13 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -442,13 +445,13 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS Longitude // GPS Longitude
if (exif_dir[Exif_GPSInfo_GPSLongitude_Index].ltag == Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template if (exif_dir[Exif_GPSInfo_GPSLongitude_Index].ltag == Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_GPSLongitude_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSLongitude_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, rational3, 24); read(fset->exif_dev_fd, rational3, 24);
longitude = __cpu_to_be32( rational3[0]) / (1.0 * __cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2]) / (60.0 * __cpu_to_be32( rational3[3])); longitude = __cpu_to_be32( rational3[0]) / (1.0 * __cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2]) / (60.0 * __cpu_to_be32( rational3[3]));
if (exif_dir[Exif_GPSInfo_GPSLongitudeRef_Index].ltag == Exif_GPSInfo_GPSLongitudeRef) { if (exif_dir[Exif_GPSInfo_GPSLongitudeRef_Index].ltag == Exif_GPSInfo_GPSLongitudeRef) {
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_GPSLongitudeRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSLongitudeRef_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, val, 1); read(fset->exif_dev_fd, val, 1);
if (val[0] != 'E') longitude = -longitude; if (val[0] != 'E') longitude = -longitude;
...@@ -459,13 +462,13 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -459,13 +462,13 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS Latitude // GPS Latitude
if (exif_dir[Exif_GPSInfo_GPSLatitude_Index].ltag == Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template if (exif_dir[Exif_GPSInfo_GPSLatitude_Index].ltag == Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_GPSLatitude_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSLatitude_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, rational3, 24); read(fset->exif_dev_fd, rational3, 24);
latitude = __cpu_to_be32( rational3[0]) / (1.0 * __cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2]) / (60.0 * __cpu_to_be32( rational3[3])); latitude = __cpu_to_be32( rational3[0]) / (1.0 * __cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2]) / (60.0 * __cpu_to_be32( rational3[3]));
if (exif_dir[Exif_GPSInfo_GPSLatitudeRef_Index].ltag == Exif_GPSInfo_GPSLatitudeRef) { if (exif_dir[Exif_GPSInfo_GPSLatitudeRef_Index].ltag == Exif_GPSInfo_GPSLatitudeRef) {
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_GPSLatitudeRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSLatitudeRef_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, val, 1); read(fset->exif_dev_fd, val, 1);
if (val[0] != 'N') latitude = -latitude; if (val[0] != 'N') latitude = -latitude;
...@@ -476,14 +479,14 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -476,14 +479,14 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS Altitude // GPS Altitude
if (exif_dir[Exif_GPSInfo_GPSAltitude_Index].ltag == Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template if (exif_dir[Exif_GPSInfo_GPSAltitude_Index].ltag == Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_GPSAltitude_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSAltitude_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, rational3, 8); read(fset->exif_dev_fd, rational3, 8);
altitude = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]); altitude = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
if (exif_dir[Exif_GPSInfo_GPSAltitudeRef_Index].ltag == Exif_GPSInfo_GPSAltitudeRef) { if (exif_dir[Exif_GPSInfo_GPSAltitudeRef_Index].ltag == Exif_GPSInfo_GPSAltitudeRef) {
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_GPSAltitudeRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSAltitudeRef_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, val, 1); read(fset->exif_dev_fd, val, 1);
if (val[0] != '\0') altitude = -altitude; if (val[0] != '\0') altitude = -altitude;
...@@ -494,7 +497,7 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -494,7 +497,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Compass Direction (magnetic) // Compass Direction (magnetic)
if (exif_dir[Exif_GPSInfo_CompassDirection_Index].ltag == Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template if (exif_dir[Exif_GPSInfo_CompassDirection_Index].ltag == Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_CompassDirection_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassDirection_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, rational3, 8); read(fset->exif_dev_fd, rational3, 8);
heading = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]); heading = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
...@@ -505,14 +508,14 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -505,14 +508,14 @@ int printExifXML(int exif_page, struct file_set *fset)
// Compass Roll // Compass Roll
if (exif_dir[Exif_GPSInfo_CompassRoll_Index].ltag == Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template if (exif_dir[Exif_GPSInfo_CompassRoll_Index].ltag == Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_CompassRoll_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassRoll_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, rational3, 8); read(fset->exif_dev_fd, rational3, 8);
roll = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]); roll = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
if (exif_dir[Exif_GPSInfo_CompassRollRef_Index].ltag == Exif_GPSInfo_CompassRollRef) { if (exif_dir[Exif_GPSInfo_CompassRollRef_Index].ltag == Exif_GPSInfo_CompassRollRef) {
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_CompassRollRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassRollRef_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, val, 1); read(fset->exif_dev_fd, val, 1);
if (val[0] != EXIF_COMPASS_ROLL_ASCII[0]) roll = -roll; if (val[0] != EXIF_COMPASS_ROLL_ASCII[0]) roll = -roll;
...@@ -524,14 +527,14 @@ int printExifXML(int exif_page, struct file_set *fset) ...@@ -524,14 +527,14 @@ int printExifXML(int exif_page, struct file_set *fset)
// Compass Pitch // Compass Pitch
if (exif_dir[Exif_GPSInfo_CompassPitch_Index].ltag == Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template if (exif_dir[Exif_GPSInfo_CompassPitch_Index].ltag == Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_CompassPitch_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassPitch_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, rational3, 8); read(fset->exif_dev_fd, rational3, 8);
pitch = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]); pitch = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
if (exif_dir[Exif_GPSInfo_CompassPitchRef_Index].ltag == Exif_GPSInfo_CompassPitchRef) { if (exif_dir[Exif_GPSInfo_CompassPitchRef_Index].ltag == Exif_GPSInfo_CompassPitchRef) {
lseek(fset->exif_dev_fd, lseek(fset->exif_dev_fd,
exif_page_start + exif_dir[Exif_GPSInfo_CompassPitchRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassPitchRef_Index].dst_exif,
SEEK_SET); SEEK_SET);
read(fset->exif_dev_fd, val, 1); read(fset->exif_dev_fd, val, 1);
if (val[0] != EXIF_COMPASS_PITCH_ASCII[0]) pitch = -pitch; if (val[0] != EXIF_COMPASS_PITCH_ASCII[0]) pitch = -pitch;
......
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