OJW's image locator script - source code

From OpenStreetMap Wiki
Jump to navigation Jump to search

Source code to OJW's image locator script

This program is public domain

 use strict;
 my $Tracklog = shift();
 my $Directory = shift();
 my $GpsTime = shift() or 0;
 my $CameraTime = shift() or 0;
 
 my $Offset = TimeToSeconds($CameraTime) - TimeToSeconds($GpsTime);
 printf STDERR "Using an offset of %+d seconds\n", $Offset;
 
 my($Lat,$Long);
 my %Points;
 
 ReadTracklog($Tracklog);
 print HtmlHeader();
 ProcessImageDir($Directory);
 print HtmlFooter();
 
 sub ProcessImageDir(){
   my $Dir = shift();
   print STDERR "$Dir:";
   opendir(DIR, $Dir) || return;
   while(my $File = readdir(DIR))
   {
     if($File =~ /\.jpg$/i && (substr($File,0,1) ne "_"))
     {
       my $FullFile = "$Dir/$File";
       my $Thumbnail = "$Dir/_thumb_$File";
       my ($ImageDate,$ImageTime) = GetImageDate($FullFile);
       my $CorrectedTime = PrintTime(TimeToSeconds($ImageTime) - $Offset);
       my ($Valid, $Lat,$Long,$Quality) = LookupTime($ImageDate, $CorrectedTime);
 
       print HtmlSummary(
         $File,
         $FullFile,
         $Thumbnail,
         $ImageDate, 
         $ImageTime, 
         $CorrectedTime,
         $Valid,
         $Lat,
         $Long,
         $Quality);
       print STDERR $Valid ? ($Quality > 20 ? "~" : ".") : "X";
     }
   }
   print STDERR "\n";
 }
 sub HtmlHeader(){
   my $Style = ".good{background-color:#CFC}.ok{background-color:#FFC}.bad{background-color:#FCC}";
   return("<html><head><title>Photo correlation</title><style>$Style</style></head><body>");
 }
 sub HtmlFooter(){
   return("</body></html>");
 }
 sub HtmlSummary()
 {
   my ($Title, $Filename, $Thumbnail, $Date, $Time, $CorrectedTime, $Valid, $Lat, $Long, $Quality) = @_;
 
   my $Html = sprintf("<p class=\"%s\">", 
     ((!$Valid) || $Quality > 60) ? "bad" : ($Quality < 10 ? "good" : "ok"));
   my $Image = "<img src=\"file://$Thumbnail\" width=\"200\" alt=\"$Title\">";
   $Html .= "<a href=\"file://$Filename\">$Image</a><br>";
   $Html .= "<table>".
     HtmlTableRow("Filename", $Title).
     HtmlTableRow("Date", $Date). 
     HtmlTableRow("Image timestamp", $Time).
     HtmlTableRow("Corrected timestamp", $CorrectedTime).
     HtmlTableRow("Quality", !$Valid ? "No GPS found" : "GPS was $Quality seconds from photo").
     HtmlTableRow("Latitude", $Lat).
     HtmlTableRow("Longitude", $Long).
     "</table>\n";
   $Html .= "</p>\n<hr>\n";
   return($Html);
 }
 
 sub HtmlTableRow(){
   return(sprintf("<tr><th>%s</th><td>%s</td></tr>\n",shift(), shift()));
 }
 
 sub ReadTracklog(){
   my $Filename = shift();
   print STDERR "Reading tracklog...";
   open(TRACKS, "<", $Filename) || return;
   foreach my $Line(<TRACKS>){
     if($Line =~ /<trkpt lat=\"(.*)\" lon=\"(.*)\">/){
      ($Lat,$Long) = ($1,$2);
     }
     if($Line =~ /<time>(.*)<\/time>/){
       my ($Date, $Time) = GpxTime($1);
       $Points{$Date}{$Time}{LAT} = $Lat;
       $Points{$Date}{$Time}{LONG} = $Long;
       $Points{$Date}{$Time}{VALID} = 1;
       #printf "%s %s = %f,%f\n", $Date, PrintTime($Time), $Lat, $Long;
     }
   }
   close TRACKS;
   print STDERR "done\n";
 }
 
 sub GetImageDate(){
   my $Filename = shift();
   open(IN, $Filename) || return((0,0));
   binmode(IN);
   read(IN, my $Data, 3000);
   close IN;
 
   if($Data =~ /(\d{4}:\d{2}:\d{2}) (\d{2}:\d{2}:\d{2})/){
     my ($Date, $Time) = ($1,$2);
     $Date =~ tr/:/-/;
     return($Date,$Time);
   }
   return(0,0);
 }
 
 sub LookupTime(){
   my $LookupDate = shift();
   my $LookupTime = TimeToSeconds(shift()); 
 
   for(my $Offset = 0; $Offset < 6000; $Offset++){
     if($Points{$LookupDate}{$LookupTime - $Offset}{VALID} == 1){
       return(
         1,
         $Points{$LookupDate}{$LookupTime - $Offset}{LAT},
         $Points{$LookupDate}{$LookupTime - $Offset}{LONG},
         $Offset);
     }
   }
   return(0,0,0,0);
 }
 
 sub GpxTime(){
   my $Time = shift();
   if($Time =~ /(.*)T(\d+)\:(\d+)\:(\d+)Z/){
     return($1, $4 + ($3 + ($2 * 60)) * 60);
   }
   return(-1,-1);
 } 
 
 sub TimeToSeconds(){
   my @Parts = split(/:/, shift());
   return(
     $Parts[0] * 3600 + 
     $Parts[1] * 60 + 
     $Parts[2]);
 }
 
 sub PrintTime($Seconds){
   my $Time = shift();
   return(sprintf("%02d:%02d:%02d", 
     ($Time % 86400) / 3600,
     ($Time % 3600) / 60,
     ($Time % 60)));
    
 }