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

project setup, exif

parent 7320ec95
......@@ -16,36 +16,37 @@
</extensions>
</storageModule>
<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="">
<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=""/>
<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.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 id="org.eclipse.cdt.build.core.settings.holder.symbols.798371956" name="Symbols" 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.incpaths.1859993711" 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/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="true" value="__arm__=1"/>
</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"/>
</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">
<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">
<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/elphel393/usr/include-uapi}&quot;"/>
<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:/elphel-apps-imgsrv/sysroots/usr/include-uapi}&quot;"/>
</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"/>
</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"/>
</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">
<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">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/elphel-apps-imgsrv/sysroots/elphel393/usr/include-uapi}&quot;"/>
<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/usr/include-uapi}&quot;"/>
</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"/>
</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"/>
......
......@@ -26,8 +26,13 @@
</arguments>
</buildCommand>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.python.pydev.PyDevBuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
......
......@@ -5,10 +5,12 @@
format: format (BYTE/ASCII/SHORT/LONG/RATIONAL/UNDEFINED?SLONG?SRATIONAL
count: number of values (characters in ASCII)
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
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)
ltag: Exif_tag+(group<<16). If specified, is used by the software, while the Exif output will still have tag (not used)
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
FrameNumber field (which actually was IPTCNAA field) is replaced with standart ImageNumber field.
......@@ -31,6 +33,23 @@
<PageNumber tag="0x129" format="SHORT" count="1" seq="28" dlen="2"/>
<ExifTag tag="0x8769" format="LONG" function="EXIFTAG"/>
<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>
<Photo>
<ExposureTime tag="0x829a" format="RATIONAL" seq="3" dlen="4">
......
......@@ -15,6 +15,7 @@
*! 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)
*! chn=0..3 - sensor channel
*!
*! Copyright (C) 2007-2016 Elphel, Inc
*! -----------------------------------------------------------------------------**
......@@ -89,9 +90,20 @@ $chn = 0;
$ExifDeviceTemplateFilename="/dev/exif_template";
$ExifDeviceMetadirFilename= "/dev/exif_metadir";
$TiffDeviceTemplateFilename="/dev/tiff_template";
$ExifDeviceExifFilename= "/dev/exif_exif";
$TiffDeviceTiffFilename= "/dev/tiff_tiff";
$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";
$DeviceRevisionFilename = "/sys/devices/soc0/elphel393-init/revision";
$DeviceBrand = "Elphel";
......@@ -100,7 +112,9 @@ $DeviceModel = "Elphel393";
//! if called from the command line - accepts just one parameter - configuration file,
//! through CGI - accepts more parameters
$ExifXMLName="/etc/Exif_template.xml";
/// $ExifXMLName="/etc/Exif_template.xml";
$ExifXMLName="./Exif_template.xml";
$init=false;
if ($_SERVER['REQUEST_METHOD']=="GET") {
if ($_GET["init"]!==NULL) {
......@@ -112,6 +126,7 @@ if ($_SERVER['REQUEST_METHOD']=="GET") {
if (isset($_GET['chn'])) $chn = $_GET['chn'];
$ExifDeviceExifFilename .= $chn;
$ExifDeviceMetaFilename .= $chn;
$TiffDeviceTiffFilename .= $chn;
} else {
foreach ($_SERVER['argv'] as $param) if (substr($param,0,4)=="init") {
$param=substr($param,5);
......@@ -149,7 +164,7 @@ 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
0xff, 0xe1, // APP1 marker at byte 2 of the file
// 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
......@@ -159,86 +174,228 @@ if ($init) { // configure Exif data
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) {
$tiff_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_both = simplexml_load_file($ExifXMLName); // include tags for either Exif or Tiff
if ($xml_both->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});
foreach ($xml_both->GPSInfo->children() as $entry) if (strpos ($entry->getName() , "Compass" )!==false) $tounset[]=$entry->getName();
foreach ($tounset as $entry) unset ($xml_both->GPSInfo->{$entry});
}
if ($noGPS) {
unset($xml_exif->GPSInfo);
unset($xml_exif->Image->GPSTag);
unset($xml_both->GPSInfo);
unset($xml_both->Image->GPSTag);
}
}
// now copy filtered $xml_both to $xml_exif and $xml_tiff to filter them separately
$xml_exif = simplexml_load_string ( $xml_both->asXML());
foreach ($xml_exif->children() as $group){
$tounset=array();
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= 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
$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']) {
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);
printf ("IFD_offset_exif=0x%x\n",$IFD_offset_exif);
printf ("SUB_IFD_offset_exif=0x%x\n",$SUB_IFD_offset_exif);
printf ("GPSInfo_offset_exif=0x%x\n",$GPSInfo_offset_exif);
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);
}
/*
IFD_offset=0x8
SUB_IFD_offset=0x86
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
foreach ($xml_exif->Image->children() as $entry) substitute_value($entry);
foreach ($xml_exif->Photo->children() as $entry) substitute_value($entry);
/// 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) {
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;
$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_exif=$IFD_offset_exif;
$data_pointer_exif=$data_offset_exif;
// 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()));
start_ifd(count($xml_exif->Image->children()), $exif_data, $ifd_pointer_exif);
// printf("ifd_pointer_exif= % d, data_pointer_exif = %d\n",$ifd_pointer_exif, $data_pointer_exif);
// printf("\n\n0 - exif_data\n"); print_r($exif_data);
$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();
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) {
$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();
$ifd_pointer_exif=$GPSInfo_offset_exif;
start_ifd(count($xml_exif->GPSInfo->children()), $exif_data, $ifd_pointer_exif);
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($exif_data, $ifd_pointer_exif);
}
$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+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="";
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]);
// 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');
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();
$Tiff_file = fopen($TiffDeviceTemplateFilename, 'w');
fwrite ($Tiff_file,$Tiff_str); /// will disable and invalidate Exif data
fclose($Tiff_file);
foreach ($xml_exif->Image->children() as $entry) addDirEntry($entry);
foreach ($xml_exif->Photo->children() as $entry) addDirEntry($entry);
$dir_entries_exif=array();
$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) {
foreach ($xml_exif->GPSInfo->children() as $entry) addDirEntry($entry);
foreach ($xml_exif->GPSInfo->children() as $entry) addDirEntry($entry, $dir_entries_exif, $exif_head_length);
}
array_multisort($dir_sequence,$dir_entries);
// 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']);
}
}
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;
for ($i=0;$i<count($dir_entries);$i++) {
$dir_entries[$i]["src"]=$frame_meta_size;
$frame_meta_size+=$dir_entries[$i]["len"];
}
// printf("\ndir_entries sorted:\n"); print_r($dir_entries);
$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');
fwrite ($Exif_meta_file,$Exif_str); /// will disable and invalidate Exif data
fclose($Exif_meta_file);
......@@ -254,10 +411,14 @@ if ($init) { // configure Exif data
}
if ($_SERVER['REQUEST_METHOD']) {
echo "<hr/>\n";
test_print_header();
test_print_header($exif_head, $exif_data);
echo "<hr/>\n";
test_print_directory();
$tiff_head=array(); // empty
test_print_header($tiff_head, $tiff_data);
echo "<hr/>\n";
test_print_directory($dir_entries,$frame_meta_size);
}
} //if ($init) // configure Exif data
/// ===== processing optional parameters =======
/// ===== read template =======
......@@ -304,6 +465,19 @@ if ($_GET["template"]!==NULL) {
echo "read ".strlen($template)." bytes<br/>\n";
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 =======
if ($_GET["metadir"]!==NULL) {
$Exif_file = fopen($ExifDeviceMetadirFilename, 'r');
......@@ -336,12 +510,27 @@ if ($_GET["exif"]!==NULL) {
echo "read ".strlen($exif_data)." bytes<br/>\n";
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);
/// ======================================= Functions ======================================
function hexdump($data) {
global $exif_head, $exif_data;
function hexdump(&$data) {
// global $exif_head, $exif_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");
for ($i=0; $i<$l;$i=$i+16) {
printf("<tr><td>%03x</td><td>|</td>\n",$i);
......@@ -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];
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");
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) {
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>");
}
function test_print_header() {
global $exif_head, $exif_data;
$lh=count($exif_head);
function test_print_header(&$exif_head, &$exif_data) {
// global $exif_head, $exif_data;
$lh = 0;
if ($exif_head) $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 ("<h2>Exif/Tiff 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);
......@@ -413,27 +605,30 @@ function test_print_header() {
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);
function test_print_directory(&$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 ("<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)
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>");
}
function start_ifd($count) {
global $exif_data, $ifd_pointer;
function start_ifd($count, &$exif_data, &$ifd_pointer) {
// 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
// printf("++++start_ifd(): ifd_pointer= %d, exif_data=\n",$ifd_pointer); print_r($exif_data);
}
function finish_ifd() { // we do not have additional IFDs
global $exif_data, $ifd_pointer;
function finish_ifd(&$exif_data, &$ifd_pointer) { // 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;
......@@ -443,9 +638,9 @@ function finish_ifd() { // we do not have additional IFDs
//pass2 - building map from frame meta to Exif template
function addDirEntry($ifd_entry) {
global $dir_sequence,$dir_entries,$exif_head;
$lh=count($exif_head);
function addDirEntry0($ifd_entry, &$dir_sequence, &$dir_entries, $lh) {
// global $dir_sequence,$dir_entries,$exif_head;
// $lh=count($exif_head);
$attrs = $ifd_entry->attributes();
// var_dump($attrs);
......@@ -461,9 +656,30 @@ function addDirEntry($ifd_entry) {
}
}
function substitute_value($ifd_entry) {
global $SUB_IFD_offset,$GPSInfo_offset;
global $DeviceSNFilename, $DeviceRevisionFilename, $DeviceBrand, $DeviceModel;
function addDirEntry($ifd_entry, &$dir_entries, $lh) {
// 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"].;
$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();
switch ($attrs["function"]) {
......@@ -486,7 +702,7 @@ function substitute_value($ifd_entry) {
$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;
case "SERIAL":
$s = "";
......@@ -501,19 +717,30 @@ function substitute_value($ifd_entry) {
case "GPSTAG":
$ifd_entry->addChild ('value',$GPSInfo_offset);
break;
// case "STRIPOFFSETS": // temporary - maybe remove this function
// $ifd_entry->addChild ('value',$GPSInfo_offset);
// break;
//STRIPOFFSETS
}
}
function process_ifd_entry($ifd_entry, $group) {
global $exif_data, $ifd_pointer, $data_pointer,$SUB_IFD_offset,$GPSInfo_offset;
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;
$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 ($debug){
echo "\nifd_tag "; echo $ifd_tag; echo "\n";
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_format==EXIF_ASCII) $ifd_count=strlen($ifd_entry->value)+1;
else $ifd_count=1 ; /// may change?
......
......@@ -308,10 +308,13 @@ int printExifXML(int exif_page, struct file_set *fset)
&CameraSerialNumber[8],
&CameraSerialNumber[10]);
//TODO: Check .dst_exif > 0, maybe add same for Tiff fields
// Image Description
if (exif_dir[Exif_Image_ImageDescription_Index].ltag == Exif_Image_ImageDescription) { // Exif_Image_ImageDescription is present in template
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);
saferead255(fset->exif_dev_fd, val, exif_dir[Exif_Image_ImageDescription_Index].len);
printf("<ImageDescription>\"%s\"</ImageDescription>\n", val);
......@@ -319,7 +322,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// 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(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);
read(fset->exif_dev_fd, rational3, 4);
sprintf(val, "%ld", (long)__cpu_to_be32( rational3[0]));
......@@ -329,7 +332,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Exif_Image_Orientation_Index 0x14
if (exif_dir[Exif_Image_Orientation_Index].ltag == Exif_Image_Orientation) { // Exif_Image_Orientation_Index is present in template
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);
rational3[0] = 0;
read(fset->exif_dev_fd, rational3, 2);
......@@ -340,7 +343,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Exif_Image_PageNumber
if (exif_dir[Exif_Image_PageNumber_Index].ltag == Exif_Image_PageNumber) { // Exif_Image_Orientation_Index is present in template
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);
rational3[0] = 0;
read(fset->exif_dev_fd, rational3, 2);
......@@ -351,14 +354,14 @@ int printExifXML(int exif_page, struct file_set *fset)
// DateTimeOriginal (with subseconds)
if (exif_dir[Exif_Photo_DateTimeOriginal_Index].ltag == Exif_Photo_DateTimeOriginal) {
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);
read(fset->exif_dev_fd, val, 19);
val[19] = '\0';
if (exif_dir[Exif_Photo_SubSecTimeOriginal_Index].ltag == Exif_Photo_SubSecTimeOriginal) {
val[19] = '.';
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);
read(fset->exif_dev_fd, &val[20], 7);
val[27] = '\0';
......@@ -368,7 +371,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Exif_Photo_ExposureTime
if (exif_dir[Exif_Photo_ExposureTime_Index].ltag == Exif_Photo_ExposureTime) { // Exif_Photo_ExposureTime is present in template
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);
read(fset->exif_dev_fd, rational3, 8);
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)
// Exif_Photo_MakerNote
if (exif_dir[Exif_Photo_MakerNote_Index].ltag == Exif_Photo_MakerNote) { // Exif_Photo_MakerNote is present in template
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);
read(fset->exif_dev_fd, makerNote, 64);
sprintf(val,
......@@ -406,7 +409,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS measure mode
if (exif_dir[Exif_GPSInfo_GPSMeasureMode_Index].ltag == Exif_GPSInfo_GPSMeasureMode) {
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);
read(fset->exif_dev_fd, val, 1);
val[1] = '\0';
......@@ -416,13 +419,13 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS date/time
if (exif_dir[Exif_GPSInfo_GPSDateStamp_Index].ltag == Exif_GPSInfo_GPSDateStamp) {
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);
read(fset->exif_dev_fd, val, 10);
val[10] = '\0';
if (exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].ltag == Exif_GPSInfo_GPSTimeStamp) {
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);
read(fset->exif_dev_fd, rational3, 24);
hours = __cpu_to_be32( rational3[0]);
......@@ -433,7 +436,7 @@ int printExifXML(int exif_page, struct file_set *fset)
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",
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]);
*/
}
......@@ -442,13 +445,13 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS Longitude
if (exif_dir[Exif_GPSInfo_GPSLongitude_Index].ltag == Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template
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);
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]));
if (exif_dir[Exif_GPSInfo_GPSLongitudeRef_Index].ltag == Exif_GPSInfo_GPSLongitudeRef) {
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);
read(fset->exif_dev_fd, val, 1);
if (val[0] != 'E') longitude = -longitude;
......@@ -459,13 +462,13 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS Latitude
if (exif_dir[Exif_GPSInfo_GPSLatitude_Index].ltag == Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template
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);
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]));
if (exif_dir[Exif_GPSInfo_GPSLatitudeRef_Index].ltag == Exif_GPSInfo_GPSLatitudeRef) {
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);
read(fset->exif_dev_fd, val, 1);
if (val[0] != 'N') latitude = -latitude;
......@@ -476,14 +479,14 @@ int printExifXML(int exif_page, struct file_set *fset)
// GPS Altitude
if (exif_dir[Exif_GPSInfo_GPSAltitude_Index].ltag == Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template
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);
read(fset->exif_dev_fd, rational3, 8);
altitude = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
if (exif_dir[Exif_GPSInfo_GPSAltitudeRef_Index].ltag == Exif_GPSInfo_GPSAltitudeRef) {
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);
read(fset->exif_dev_fd, val, 1);
if (val[0] != '\0') altitude = -altitude;
......@@ -494,7 +497,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// Compass Direction (magnetic)
if (exif_dir[Exif_GPSInfo_CompassDirection_Index].ltag == Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template
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);
read(fset->exif_dev_fd, rational3, 8);
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)
// Compass Roll
if (exif_dir[Exif_GPSInfo_CompassRoll_Index].ltag == Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template
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);
read(fset->exif_dev_fd, rational3, 8);
roll = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
if (exif_dir[Exif_GPSInfo_CompassRollRef_Index].ltag == Exif_GPSInfo_CompassRollRef) {
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);
read(fset->exif_dev_fd, val, 1);
if (val[0] != EXIF_COMPASS_ROLL_ASCII[0]) roll = -roll;
......@@ -524,14 +527,14 @@ int printExifXML(int exif_page, struct file_set *fset)
// Compass Pitch
if (exif_dir[Exif_GPSInfo_CompassPitch_Index].ltag == Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template
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);
read(fset->exif_dev_fd, rational3, 8);
pitch = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
if (exif_dir[Exif_GPSInfo_CompassPitchRef_Index].ltag == Exif_GPSInfo_CompassPitchRef) {
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);
read(fset->exif_dev_fd, val, 1);
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