mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-05 23:48:31 -04:00
944488afaf
Convert to IActivate, IDeactivate scheme, thanks andrew add support for rfcomm* interfaces on linux fix guage off screen draw mono issue. remove use of BackStageViewContentPanel andrews spacer changes - not using dues to screen space issue change configpanel constructor to load xml directly remove IMavlink Interface fix hsi off screen draw issue on mono modify hud to use sprite fonts, instead of drawing via GDI+ modify progress reporter to use a 10hz timer to update screen, using invoke/begininvoke fails on mono at 50hz (over 100ms per call). fix targetalt and target airspeed jumping issue. lots of cleanup on tab switching, ie stoping timers/other 3dr radio status led update update ardurover car icon speedup georef image screen. tested on over 1000 images.
907 lines
35 KiB
C#
907 lines
35 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections;
|
|
using System.Reflection;
|
|
using System.IO;
|
|
using System.Windows.Forms;
|
|
using com.drew.imaging.jpg;
|
|
using com.drew.metadata;
|
|
using log4net;
|
|
using SharpKml.Base;
|
|
using SharpKml.Dom;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Text;
|
|
|
|
namespace ArdupilotMega
|
|
{
|
|
public class Georefimage : Form
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
|
private OpenFileDialog openFileDialog1;
|
|
private ArdupilotMega.Controls.MyButton BUT_browselog;
|
|
private ArdupilotMega.Controls.MyButton BUT_browsedir;
|
|
private TextBox TXT_logfile;
|
|
private TextBox TXT_jpgdir;
|
|
private TextBox TXT_offsetseconds;
|
|
private ArdupilotMega.Controls.MyButton BUT_doit;
|
|
private FolderBrowserDialog folderBrowserDialog1;
|
|
private Label label1;
|
|
private TextBox TXT_outputlog;
|
|
private ArdupilotMega.Controls.MyButton BUT_estoffset;
|
|
|
|
int latpos = 4, lngpos = 5, altpos = 7, cogpos = 9;
|
|
private NumericUpDown numericUpDown1;
|
|
private NumericUpDown numericUpDown2;
|
|
private NumericUpDown numericUpDown3;
|
|
private NumericUpDown numericUpDown4;
|
|
private Label label2;
|
|
private Label label3;
|
|
private Label label4;
|
|
private Label label5;
|
|
private Label label6;
|
|
private Controls.MyButton BUT_networklinkgeoref;
|
|
private ArdupilotMega.Controls.MyButton BUT_Geotagimages;
|
|
|
|
internal Georefimage() {
|
|
InitializeComponent();
|
|
}
|
|
|
|
Hashtable filedatecache = new Hashtable();
|
|
Hashtable photocoords = new Hashtable();
|
|
|
|
Hashtable timecoordcache = new Hashtable();
|
|
Hashtable imagetotime = new Hashtable();
|
|
|
|
List<string[]> logcache = new List<string[]>();
|
|
|
|
DateTime getPhotoTime(string fn)
|
|
{
|
|
DateTime dtaken = DateTime.MinValue;
|
|
|
|
if (filedatecache.ContainsKey(fn))
|
|
{
|
|
return (DateTime)filedatecache[fn];
|
|
}
|
|
|
|
try
|
|
{
|
|
|
|
Metadata lcMetadata = null;
|
|
try
|
|
{
|
|
FileInfo lcImgFile = new FileInfo(fn);
|
|
// Loading all meta data
|
|
lcMetadata = JpegMetadataReader.ReadMetadata(lcImgFile);
|
|
}
|
|
catch (JpegProcessingException e)
|
|
{
|
|
log.InfoFormat(e.Message);
|
|
return dtaken;
|
|
}
|
|
|
|
foreach (AbstractDirectory lcDirectory in lcMetadata)
|
|
{
|
|
|
|
if (lcDirectory.ContainsTag(0x9003))
|
|
{
|
|
dtaken = lcDirectory.GetDate(0x9003);
|
|
log.InfoFormat("does " + lcDirectory.GetTagName(0x9003) + " " + dtaken);
|
|
|
|
filedatecache[fn] = dtaken;
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////// old method, works, just slow
|
|
/*
|
|
Image myImage = Image.FromFile(fn);
|
|
PropertyItem propItem = myImage.GetPropertyItem(36867); // 36867 // 306
|
|
|
|
//Convert date taken metadata to a DateTime object
|
|
string sdate = Encoding.UTF8.GetString(propItem.Value).Trim();
|
|
string secondhalf = sdate.Substring(sdate.IndexOf(" "), (sdate.Length - sdate.IndexOf(" ")));
|
|
string firsthalf = sdate.Substring(0, 10);
|
|
firsthalf = firsthalf.Replace(":", "-");
|
|
sdate = firsthalf + secondhalf;
|
|
dtaken = DateTime.Parse(sdate);
|
|
|
|
myImage.Dispose();
|
|
*/
|
|
}
|
|
catch { }
|
|
|
|
return dtaken;
|
|
}
|
|
|
|
List<string[]> readLog(string fn)
|
|
{
|
|
if (logcache.Count > 0)
|
|
return logcache;
|
|
|
|
List<string[]> list = new List<string[]>();
|
|
|
|
if (fn.ToLower().EndsWith("tlog"))
|
|
{
|
|
MAVLink mine = new MAVLink();
|
|
mine.logplaybackfile = new BinaryReader(File.Open(fn, FileMode.Open, FileAccess.Read, FileShare.Read));
|
|
mine.logreadmode = true;
|
|
|
|
mine.packets.Initialize(); // clear
|
|
|
|
CurrentState cs = new CurrentState();
|
|
|
|
string[] oldvalues = {""};
|
|
|
|
while (mine.logplaybackfile.BaseStream.Position < mine.logplaybackfile.BaseStream.Length)
|
|
{
|
|
|
|
byte[] packet = mine.readPacket();
|
|
|
|
cs.datetime = mine.lastlogread;
|
|
|
|
cs.UpdateCurrentSettings(null, true, mine);
|
|
|
|
// line "GPS: 82686250, 1, 8, -34.1406480, 118.5441900, 0.0000, 309.1900, 315.9500, 0.0000, 279.1200" string
|
|
|
|
|
|
string[] vals = new string[] { "GPS", (cs.datetime.ToUniversalTime() - new DateTime(cs.datetime.Year,cs.datetime.Month,cs.datetime.Day,0,0,0,DateTimeKind.Utc)).TotalMilliseconds.ToString(), "1",
|
|
cs.satcount.ToString(),cs.lat.ToString(),cs.lng.ToString(),"0.0",cs.alt.ToString(),cs.alt.ToString(),cs.groundspeed.ToString(),cs.yaw.ToString()};
|
|
|
|
if (oldvalues.Length > 2 && oldvalues[latpos] == vals[latpos]
|
|
&& oldvalues[lngpos] == vals[lngpos]
|
|
&& oldvalues[altpos] == vals[altpos])
|
|
continue;
|
|
|
|
oldvalues = vals;
|
|
|
|
list.Add(vals);
|
|
// 4 5 7
|
|
Console.Write((mine.logplaybackfile.BaseStream.Position * 100 / mine.logplaybackfile.BaseStream.Length) + " \r");
|
|
|
|
}
|
|
|
|
mine.logplaybackfile.Close();
|
|
|
|
logcache = list;
|
|
|
|
return list;
|
|
}
|
|
|
|
StreamReader sr = new StreamReader(fn);
|
|
|
|
string lasttime = "0";
|
|
|
|
while (!sr.EndOfStream)
|
|
{
|
|
string line = sr.ReadLine();
|
|
|
|
if (line.ToLower().StartsWith("gps"))
|
|
{
|
|
string[] vals = line.Split(new char[] {',',':'});
|
|
|
|
if (lasttime == vals[1])
|
|
continue;
|
|
|
|
lasttime = vals[1];
|
|
|
|
list.Add(vals);
|
|
}
|
|
}
|
|
|
|
sr.Close();
|
|
sr.Dispose();
|
|
|
|
logcache = list;
|
|
|
|
return list;
|
|
}
|
|
|
|
public void dowork(string logFile, string dirWithImages, float offsetseconds, bool dooffset)
|
|
{
|
|
DateTime localmin = DateTime.MaxValue;
|
|
DateTime localmax = DateTime.MinValue;
|
|
|
|
DateTime startTime = DateTime.MinValue;
|
|
|
|
photocoords = new Hashtable();
|
|
timecoordcache = new Hashtable();
|
|
imagetotime = new Hashtable();
|
|
|
|
//logFile = @"C:\Users\hog\Pictures\farm 1-10-2011\100SSCAM\2011-10-01 11-48 1.log";
|
|
TXT_outputlog.AppendText("Read Log\n");
|
|
|
|
List<string[]> list = readLog(logFile);
|
|
|
|
TXT_outputlog.AppendText("Log Read\n");
|
|
|
|
//dirWithImages = @"C:\Users\hog\Pictures\farm 1-10-2011\100SSCAM";
|
|
|
|
TXT_outputlog.AppendText("Read images\n");
|
|
|
|
string[] files = Directory.GetFiles(dirWithImages);
|
|
|
|
TXT_outputlog.AppendText("images read\n");
|
|
|
|
Document kml = new Document();
|
|
|
|
StreamWriter sw4 = new StreamWriter(dirWithImages + Path.DirectorySeparatorChar + "loglocation.csv");
|
|
|
|
StreamWriter sw3 = new StreamWriter(dirWithImages + Path.DirectorySeparatorChar + "location.kml");
|
|
|
|
StreamWriter sw2 = new StreamWriter(dirWithImages + Path.DirectorySeparatorChar + "location.txt");
|
|
|
|
StreamWriter sw = new StreamWriter(dirWithImages + Path.DirectorySeparatorChar + "location.tel");
|
|
sw.WriteLine("version=1");
|
|
|
|
sw.WriteLine("#seconds offset - " + TXT_offsetseconds.Text);
|
|
sw.WriteLine("#longitude and latitude - in degrees");
|
|
sw.WriteLine("#name utc longitude latitude height");
|
|
|
|
int first = 0;
|
|
int matchs = 0;
|
|
|
|
int lastmatchindex = 0;
|
|
|
|
TXT_outputlog.AppendText("start Processing\n");
|
|
|
|
foreach (string filename in files)
|
|
{
|
|
if (filename.ToLower().EndsWith(".jpg") && !filename.ToLower().Contains("_geotag"))
|
|
{
|
|
DateTime photodt = getPhotoTime(filename);
|
|
|
|
if (startTime == DateTime.MinValue)
|
|
{
|
|
startTime = new DateTime(photodt.Year, photodt.Month, photodt.Day, 0, 0, 0, 0, DateTimeKind.Utc).ToLocalTime();
|
|
|
|
foreach (string[] arr in list)
|
|
{
|
|
DateTime crap = startTime.AddMilliseconds(int.Parse(arr[1])).AddSeconds(offsetseconds);
|
|
|
|
if (localmin > crap)
|
|
localmin = crap;
|
|
if (localmax < crap)
|
|
localmax = crap;
|
|
}
|
|
|
|
log.InfoFormat("min " + localmin + " max " + localmax);
|
|
TXT_outputlog.AppendText("Log min " + localmin + " max " + localmax + "\r\n");
|
|
}
|
|
|
|
TXT_outputlog.AppendText("Photo " + Path.GetFileNameWithoutExtension(filename) + " time " + photodt + "\r\n");
|
|
//Application.DoEvents();
|
|
|
|
int a = 0;
|
|
|
|
foreach (string[] arr in list)
|
|
{
|
|
a++;
|
|
|
|
if (lastmatchindex > (a))
|
|
continue;
|
|
|
|
if (a % 1000 == 0)
|
|
Application.DoEvents();
|
|
|
|
DateTime logdt = startTime.AddMilliseconds(int.Parse(arr[1])).AddSeconds(offsetseconds);
|
|
|
|
if (first == 0)
|
|
{
|
|
TXT_outputlog.AppendText("Photo " + Path.GetFileNameWithoutExtension(filename) + " " + photodt + " vs Log " + logdt + "\r\n");
|
|
|
|
TXT_outputlog.AppendText("offset should be about " + (photodt - logdt).TotalSeconds + "\r\n");
|
|
|
|
if (dooffset)
|
|
return;
|
|
|
|
first++;
|
|
}
|
|
|
|
// time has past, logs are in time order
|
|
if (photodt < logdt.AddSeconds(-1))
|
|
{
|
|
lastmatchindex = a;
|
|
break;
|
|
}
|
|
|
|
//Console.Write("ph " + dt + " log " + crap + " \r");
|
|
|
|
|
|
timecoordcache[(long)(logdt.AddSeconds(-offsetseconds) - DateTime.MinValue).TotalSeconds] = new double[] {
|
|
double.Parse(arr[latpos]), double.Parse(arr[lngpos]), double.Parse(arr[altpos])
|
|
};
|
|
|
|
sw4.WriteLine("ph " + filename + " " + photodt + " log " + logdt);
|
|
|
|
if (photodt.ToString("yyyy-MM-ddTHH:mm:ss") == logdt.ToString("yyyy-MM-ddTHH:mm:ss"))
|
|
{
|
|
lastmatchindex = a;
|
|
|
|
TXT_outputlog.AppendText("MATCH Photo " + Path.GetFileNameWithoutExtension(filename) + " " + photodt + "\r\n");
|
|
|
|
matchs++;
|
|
|
|
|
|
|
|
SharpKml.Dom.Timestamp tstamp = new SharpKml.Dom.Timestamp();
|
|
|
|
tstamp.When = photodt;
|
|
|
|
kml.AddFeature(
|
|
new Placemark()
|
|
{
|
|
Time = tstamp,
|
|
Name = Path.GetFileNameWithoutExtension(filename),
|
|
Geometry = new SharpKml.Dom.Point()
|
|
{
|
|
Coordinate = new Vector(double.Parse(arr[latpos]), double.Parse(arr[lngpos]), double.Parse(arr[altpos]))
|
|
},
|
|
Description = new Description()
|
|
{
|
|
Text = "<table><tr><td><img src=\"" + Path.GetFileName(filename).ToLower() + "\" width=500 /></td></tr></table>"
|
|
},
|
|
StyleSelector = new Style()
|
|
{
|
|
Balloon = new BalloonStyle() { Text = "$[name]<br>$[description]" }
|
|
}
|
|
}
|
|
);
|
|
|
|
photocoords[filename] = new double[] { double.Parse(arr[latpos]), double.Parse(arr[lngpos]), double.Parse(arr[altpos]), double.Parse(arr[cogpos]) };
|
|
|
|
imagetotime[filename] = (long)(logdt.AddSeconds(-offsetseconds) - DateTime.MinValue).TotalSeconds;
|
|
|
|
sw2.WriteLine(Path.GetFileNameWithoutExtension(filename) + " " + arr[lngpos] + " " + arr[latpos] + " " + arr[altpos]);
|
|
sw.WriteLine(Path.GetFileNameWithoutExtension(filename) + "\t" + logdt.ToString("yyyy:MM:dd HH:mm:ss") + "\t" + arr[lngpos] + "\t" + arr[latpos] + "\t" + arr[altpos]);
|
|
sw.Flush();
|
|
sw2.Flush();
|
|
log.InfoFormat(Path.GetFileNameWithoutExtension(filename) + " " + arr[lngpos] + " " + arr[latpos] + " " + arr[altpos] + " ");
|
|
break;
|
|
}
|
|
//Console.WriteLine(crap);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
Serializer serializer = new Serializer();
|
|
serializer.Serialize(kml);
|
|
sw3.Write(serializer.Xml);
|
|
sw3.Close();
|
|
|
|
MainV2.instance.georefkml = serializer.Xml;
|
|
|
|
writeGPX(dirWithImages + Path.DirectorySeparatorChar + "location.gpx");
|
|
|
|
sw4.Close();
|
|
|
|
sw2.Close();
|
|
sw.Close();
|
|
|
|
TXT_outputlog.AppendText("Done " + matchs + " matchs");
|
|
}
|
|
|
|
private void writeGPX(string filename)
|
|
{
|
|
|
|
using (System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(filename) + ".gpx", Encoding.ASCII))
|
|
{
|
|
|
|
xw.WriteStartElement("gpx");
|
|
|
|
xw.WriteStartElement("trk");
|
|
|
|
xw.WriteStartElement("trkseg");
|
|
|
|
List<string> items = new List<string>();
|
|
|
|
foreach (string photo in photocoords.Keys)
|
|
{
|
|
items.Add(photo);
|
|
}
|
|
|
|
items.Sort();
|
|
|
|
foreach (string photo in items)
|
|
{
|
|
|
|
|
|
xw.WriteStartElement("trkpt");
|
|
xw.WriteAttributeString("lat", ((double[])photocoords[photo])[0].ToString(new System.Globalization.CultureInfo("en-US")));
|
|
xw.WriteAttributeString("lon", ((double[])photocoords[photo])[1].ToString(new System.Globalization.CultureInfo("en-US")));
|
|
|
|
// must stay as above
|
|
|
|
xw.WriteElementString("time", ((DateTime)filedatecache[photo]).ToString("yyyy-MM-ddTHH:mm:ssZ"));
|
|
|
|
xw.WriteElementString("ele", ((double[])photocoords[photo])[2].ToString(new System.Globalization.CultureInfo("en-US")));
|
|
xw.WriteElementString("course", ((double[])photocoords[photo])[3].ToString(new System.Globalization.CultureInfo("en-US")));
|
|
|
|
xw.WriteElementString("compass", ((double[])photocoords[photo])[3].ToString(new System.Globalization.CultureInfo("en-US")));
|
|
|
|
xw.WriteEndElement();
|
|
}
|
|
|
|
xw.WriteEndElement();
|
|
xw.WriteEndElement();
|
|
xw.WriteEndElement();
|
|
|
|
xw.Close();
|
|
}
|
|
}
|
|
|
|
private void InitializeComponent()
|
|
{
|
|
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
|
|
this.TXT_logfile = new System.Windows.Forms.TextBox();
|
|
this.TXT_jpgdir = new System.Windows.Forms.TextBox();
|
|
this.TXT_offsetseconds = new System.Windows.Forms.TextBox();
|
|
this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
|
|
this.TXT_outputlog = new System.Windows.Forms.TextBox();
|
|
this.label1 = new System.Windows.Forms.Label();
|
|
this.BUT_Geotagimages = new ArdupilotMega.Controls.MyButton();
|
|
this.BUT_estoffset = new ArdupilotMega.Controls.MyButton();
|
|
this.BUT_doit = new ArdupilotMega.Controls.MyButton();
|
|
this.BUT_browsedir = new ArdupilotMega.Controls.MyButton();
|
|
this.BUT_browselog = new ArdupilotMega.Controls.MyButton();
|
|
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
|
|
this.numericUpDown2 = new System.Windows.Forms.NumericUpDown();
|
|
this.numericUpDown3 = new System.Windows.Forms.NumericUpDown();
|
|
this.numericUpDown4 = new System.Windows.Forms.NumericUpDown();
|
|
this.label2 = new System.Windows.Forms.Label();
|
|
this.label3 = new System.Windows.Forms.Label();
|
|
this.label4 = new System.Windows.Forms.Label();
|
|
this.label5 = new System.Windows.Forms.Label();
|
|
this.label6 = new System.Windows.Forms.Label();
|
|
this.BUT_networklinkgeoref = new ArdupilotMega.Controls.MyButton();
|
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
|
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit();
|
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit();
|
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).BeginInit();
|
|
this.SuspendLayout();
|
|
//
|
|
// openFileDialog1
|
|
//
|
|
this.openFileDialog1.FileName = "openFileDialog1";
|
|
//
|
|
// TXT_logfile
|
|
//
|
|
this.TXT_logfile.Location = new System.Drawing.Point(28, 14);
|
|
this.TXT_logfile.Name = "TXT_logfile";
|
|
this.TXT_logfile.Size = new System.Drawing.Size(317, 20);
|
|
this.TXT_logfile.TabIndex = 2;
|
|
this.TXT_logfile.Text = "C:\\Users\\hog\\Pictures\\farm 1-10-2011\\100SSCAM\\2011-10-01 11-48 1.log";
|
|
this.TXT_logfile.TextChanged += new System.EventHandler(this.TXT_logfile_TextChanged);
|
|
//
|
|
// TXT_jpgdir
|
|
//
|
|
this.TXT_jpgdir.Location = new System.Drawing.Point(28, 43);
|
|
this.TXT_jpgdir.Name = "TXT_jpgdir";
|
|
this.TXT_jpgdir.Size = new System.Drawing.Size(317, 20);
|
|
this.TXT_jpgdir.TabIndex = 3;
|
|
this.TXT_jpgdir.Text = "C:\\Users\\hog\\Pictures\\farm 1-10-2011\\100SSCAM";
|
|
//
|
|
// TXT_offsetseconds
|
|
//
|
|
this.TXT_offsetseconds.Location = new System.Drawing.Point(180, 69);
|
|
this.TXT_offsetseconds.Name = "TXT_offsetseconds";
|
|
this.TXT_offsetseconds.Size = new System.Drawing.Size(100, 20);
|
|
this.TXT_offsetseconds.TabIndex = 4;
|
|
this.TXT_offsetseconds.Text = "-86158";
|
|
//
|
|
// TXT_outputlog
|
|
//
|
|
this.TXT_outputlog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
|
| System.Windows.Forms.AnchorStyles.Left)
|
|
| System.Windows.Forms.AnchorStyles.Right)));
|
|
this.TXT_outputlog.Location = new System.Drawing.Point(28, 190);
|
|
this.TXT_outputlog.Multiline = true;
|
|
this.TXT_outputlog.Name = "TXT_outputlog";
|
|
this.TXT_outputlog.ReadOnly = true;
|
|
this.TXT_outputlog.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
|
this.TXT_outputlog.Size = new System.Drawing.Size(397, 160);
|
|
this.TXT_outputlog.TabIndex = 6;
|
|
//
|
|
// label1
|
|
//
|
|
this.label1.AutoSize = true;
|
|
this.label1.Location = new System.Drawing.Point(94, 75);
|
|
this.label1.Name = "label1";
|
|
this.label1.Size = new System.Drawing.Size(78, 13);
|
|
this.label1.TabIndex = 7;
|
|
this.label1.Text = "Seconds offset";
|
|
//
|
|
// BUT_Geotagimages
|
|
//
|
|
this.BUT_Geotagimages.Enabled = false;
|
|
this.BUT_Geotagimages.Location = new System.Drawing.Point(259, 161);
|
|
this.BUT_Geotagimages.Name = "BUT_Geotagimages";
|
|
this.BUT_Geotagimages.Size = new System.Drawing.Size(75, 23);
|
|
this.BUT_Geotagimages.TabIndex = 9;
|
|
this.BUT_Geotagimages.Text = "GeoTag Images";
|
|
this.BUT_Geotagimages.UseVisualStyleBackColor = true;
|
|
this.BUT_Geotagimages.Click += new System.EventHandler(this.BUT_Geotagimages_Click);
|
|
//
|
|
// BUT_estoffset
|
|
//
|
|
this.BUT_estoffset.Location = new System.Drawing.Point(286, 67);
|
|
this.BUT_estoffset.Name = "BUT_estoffset";
|
|
this.BUT_estoffset.Size = new System.Drawing.Size(75, 23);
|
|
this.BUT_estoffset.TabIndex = 8;
|
|
this.BUT_estoffset.Text = "Estimate Offset";
|
|
this.BUT_estoffset.UseVisualStyleBackColor = true;
|
|
this.BUT_estoffset.Click += new System.EventHandler(this.BUT_estoffset_Click);
|
|
//
|
|
// BUT_doit
|
|
//
|
|
this.BUT_doit.Location = new System.Drawing.Point(97, 161);
|
|
this.BUT_doit.Name = "BUT_doit";
|
|
this.BUT_doit.Size = new System.Drawing.Size(75, 23);
|
|
this.BUT_doit.TabIndex = 5;
|
|
this.BUT_doit.Text = "Do It";
|
|
this.BUT_doit.UseVisualStyleBackColor = true;
|
|
this.BUT_doit.Click += new System.EventHandler(this.BUT_doit_Click);
|
|
//
|
|
// BUT_browsedir
|
|
//
|
|
this.BUT_browsedir.Location = new System.Drawing.Point(351, 41);
|
|
this.BUT_browsedir.Name = "BUT_browsedir";
|
|
this.BUT_browsedir.Size = new System.Drawing.Size(75, 23);
|
|
this.BUT_browsedir.TabIndex = 1;
|
|
this.BUT_browsedir.Text = "Browse Directory";
|
|
this.BUT_browsedir.UseVisualStyleBackColor = true;
|
|
this.BUT_browsedir.Click += new System.EventHandler(this.BUT_browsedir_Click);
|
|
//
|
|
// BUT_browselog
|
|
//
|
|
this.BUT_browselog.Location = new System.Drawing.Point(351, 12);
|
|
this.BUT_browselog.Name = "BUT_browselog";
|
|
this.BUT_browselog.Size = new System.Drawing.Size(75, 23);
|
|
this.BUT_browselog.TabIndex = 0;
|
|
this.BUT_browselog.Text = "Browse Log";
|
|
this.BUT_browselog.UseVisualStyleBackColor = true;
|
|
this.BUT_browselog.Click += new System.EventHandler(this.BUT_browselog_Click);
|
|
//
|
|
// numericUpDown1
|
|
//
|
|
this.numericUpDown1.Location = new System.Drawing.Point(130, 116);
|
|
this.numericUpDown1.Name = "numericUpDown1";
|
|
this.numericUpDown1.Size = new System.Drawing.Size(42, 20);
|
|
this.numericUpDown1.TabIndex = 10;
|
|
this.numericUpDown1.Value = new decimal(new int[] {
|
|
4,
|
|
0,
|
|
0,
|
|
0});
|
|
//
|
|
// numericUpDown2
|
|
//
|
|
this.numericUpDown2.Location = new System.Drawing.Point(178, 116);
|
|
this.numericUpDown2.Name = "numericUpDown2";
|
|
this.numericUpDown2.Size = new System.Drawing.Size(42, 20);
|
|
this.numericUpDown2.TabIndex = 11;
|
|
this.numericUpDown2.Value = new decimal(new int[] {
|
|
5,
|
|
0,
|
|
0,
|
|
0});
|
|
//
|
|
// numericUpDown3
|
|
//
|
|
this.numericUpDown3.Location = new System.Drawing.Point(226, 116);
|
|
this.numericUpDown3.Name = "numericUpDown3";
|
|
this.numericUpDown3.Size = new System.Drawing.Size(42, 20);
|
|
this.numericUpDown3.TabIndex = 12;
|
|
this.numericUpDown3.Value = new decimal(new int[] {
|
|
7,
|
|
0,
|
|
0,
|
|
0});
|
|
//
|
|
// numericUpDown4
|
|
//
|
|
this.numericUpDown4.Location = new System.Drawing.Point(274, 116);
|
|
this.numericUpDown4.Name = "numericUpDown4";
|
|
this.numericUpDown4.Size = new System.Drawing.Size(42, 20);
|
|
this.numericUpDown4.TabIndex = 13;
|
|
this.numericUpDown4.Value = new decimal(new int[] {
|
|
9,
|
|
0,
|
|
0,
|
|
0});
|
|
//
|
|
// label2
|
|
//
|
|
this.label2.AutoSize = true;
|
|
this.label2.Location = new System.Drawing.Point(127, 100);
|
|
this.label2.Name = "label2";
|
|
this.label2.Size = new System.Drawing.Size(22, 13);
|
|
this.label2.TabIndex = 14;
|
|
this.label2.Text = "Lat";
|
|
//
|
|
// label3
|
|
//
|
|
this.label3.AutoSize = true;
|
|
this.label3.Location = new System.Drawing.Point(175, 100);
|
|
this.label3.Name = "label3";
|
|
this.label3.Size = new System.Drawing.Size(25, 13);
|
|
this.label3.TabIndex = 15;
|
|
this.label3.Text = "Lon";
|
|
//
|
|
// label4
|
|
//
|
|
this.label4.AutoSize = true;
|
|
this.label4.Location = new System.Drawing.Point(223, 100);
|
|
this.label4.Name = "label4";
|
|
this.label4.Size = new System.Drawing.Size(19, 13);
|
|
this.label4.TabIndex = 16;
|
|
this.label4.Text = "Alt";
|
|
//
|
|
// label5
|
|
//
|
|
this.label5.AutoSize = true;
|
|
this.label5.Location = new System.Drawing.Point(271, 100);
|
|
this.label5.Name = "label5";
|
|
this.label5.Size = new System.Drawing.Size(47, 13);
|
|
this.label5.TabIndex = 17;
|
|
this.label5.Text = "Heading";
|
|
//
|
|
// label6
|
|
//
|
|
this.label6.AutoSize = true;
|
|
this.label6.Location = new System.Drawing.Point(63, 118);
|
|
this.label6.Name = "label6";
|
|
this.label6.Size = new System.Drawing.Size(61, 13);
|
|
this.label6.TabIndex = 18;
|
|
this.label6.Text = "Log Offsets";
|
|
//
|
|
// BUT_networklinkgeoref
|
|
//
|
|
this.BUT_networklinkgeoref.Location = new System.Drawing.Point(178, 161);
|
|
this.BUT_networklinkgeoref.Name = "BUT_networklinkgeoref";
|
|
this.BUT_networklinkgeoref.Size = new System.Drawing.Size(75, 23);
|
|
this.BUT_networklinkgeoref.TabIndex = 19;
|
|
this.BUT_networklinkgeoref.Text = "Location Kml";
|
|
this.BUT_networklinkgeoref.UseVisualStyleBackColor = true;
|
|
this.BUT_networklinkgeoref.Click += new System.EventHandler(this.BUT_networklinkgeoref_Click);
|
|
//
|
|
// Georefimage
|
|
//
|
|
this.ClientSize = new System.Drawing.Size(452, 362);
|
|
this.Controls.Add(this.BUT_networklinkgeoref);
|
|
this.Controls.Add(this.label6);
|
|
this.Controls.Add(this.label5);
|
|
this.Controls.Add(this.label4);
|
|
this.Controls.Add(this.label3);
|
|
this.Controls.Add(this.label2);
|
|
this.Controls.Add(this.numericUpDown4);
|
|
this.Controls.Add(this.numericUpDown3);
|
|
this.Controls.Add(this.numericUpDown2);
|
|
this.Controls.Add(this.numericUpDown1);
|
|
this.Controls.Add(this.BUT_Geotagimages);
|
|
this.Controls.Add(this.BUT_estoffset);
|
|
this.Controls.Add(this.label1);
|
|
this.Controls.Add(this.TXT_outputlog);
|
|
this.Controls.Add(this.BUT_doit);
|
|
this.Controls.Add(this.TXT_offsetseconds);
|
|
this.Controls.Add(this.TXT_jpgdir);
|
|
this.Controls.Add(this.TXT_logfile);
|
|
this.Controls.Add(this.BUT_browsedir);
|
|
this.Controls.Add(this.BUT_browselog);
|
|
this.Name = "Georefimage";
|
|
this.Text = "Geo Ref Images";
|
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
|
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit();
|
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit();
|
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).EndInit();
|
|
this.ResumeLayout(false);
|
|
this.PerformLayout();
|
|
|
|
}
|
|
|
|
private void BUT_browselog_Click(object sender, EventArgs e)
|
|
{
|
|
logcache.Clear();
|
|
|
|
openFileDialog1.Filter = "Logs|*.log;*.tlog";
|
|
openFileDialog1.ShowDialog();
|
|
|
|
if (File.Exists(openFileDialog1.FileName))
|
|
{
|
|
TXT_logfile.Text = openFileDialog1.FileName;
|
|
}
|
|
}
|
|
|
|
private void BUT_browsedir_Click(object sender, EventArgs e)
|
|
{
|
|
folderBrowserDialog1.ShowDialog();
|
|
|
|
if (folderBrowserDialog1.SelectedPath != "")
|
|
{
|
|
TXT_jpgdir.Text = folderBrowserDialog1.SelectedPath;
|
|
}
|
|
}
|
|
|
|
private void BUT_doit_Click(object sender, EventArgs e)
|
|
{
|
|
if (!File.Exists(TXT_logfile.Text))
|
|
return;
|
|
if (!Directory.Exists(TXT_jpgdir.Text))
|
|
return;
|
|
float seconds;
|
|
if (float.TryParse(TXT_offsetseconds.Text, out seconds) == false)
|
|
return;
|
|
|
|
BUT_doit.Enabled = false;
|
|
try
|
|
{
|
|
dowork(TXT_logfile.Text, TXT_jpgdir.Text, seconds, false);
|
|
}
|
|
catch { }
|
|
BUT_doit.Enabled = true;
|
|
BUT_Geotagimages.Enabled = true;
|
|
}
|
|
|
|
private void BUT_estoffset_Click(object sender, EventArgs e)
|
|
{
|
|
dowork(TXT_logfile.Text, TXT_jpgdir.Text, 0, true);
|
|
}
|
|
|
|
private void BUT_Geotagimages_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
foreach (string file in photocoords.Keys)
|
|
{
|
|
WriteCoordinatesToImage(file, ((double[])photocoords[file])[0], ((double[])photocoords[file])[1], ((double[])photocoords[file])[2]);
|
|
}
|
|
|
|
}
|
|
|
|
byte[] coordtobytearray(double coordin)
|
|
{
|
|
double coord = Math.Abs(coordin);
|
|
|
|
byte[] output = new byte[sizeof(double) * 3];
|
|
|
|
int d = (int)coord;
|
|
int m = (int)((coord - d) * 60);
|
|
double s = ((((coord - d) * 60) - m) * 60);
|
|
/*
|
|
21 00 00 00 01 00 00 00--> 33/1
|
|
18 00 00 00 01 00 00 00--> 24/1
|
|
06 02 00 00 0A 00 00 00--> 518/10
|
|
*/
|
|
|
|
Array.Copy(BitConverter.GetBytes((uint)d), 0, output, 0, sizeof(uint));
|
|
Array.Copy(BitConverter.GetBytes((uint)1), 0, output, 4, sizeof(uint));
|
|
Array.Copy(BitConverter.GetBytes((uint)m), 0, output, 8, sizeof(uint));
|
|
Array.Copy(BitConverter.GetBytes((uint)1), 0, output, 12, sizeof(uint));
|
|
Array.Copy(BitConverter.GetBytes((uint)(s * 10)), 0, output, 16, sizeof(uint));
|
|
Array.Copy(BitConverter.GetBytes((uint)10), 0, output, 20, sizeof(uint));
|
|
|
|
return output;
|
|
}
|
|
|
|
void WriteCoordinatesToImage(string Filename, double dLat, double dLong, double alt)
|
|
{
|
|
using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(Filename)))
|
|
{
|
|
TXT_outputlog.AppendText("GeoTagging "+Filename + "\n");
|
|
Application.DoEvents();
|
|
|
|
using (Image Pic = Image.FromStream(ms))
|
|
{
|
|
PropertyItem[] pi = Pic.PropertyItems;
|
|
|
|
pi[0].Id = 0x0004;
|
|
pi[0].Type = 5;
|
|
pi[0].Len = sizeof(ulong) * 3;
|
|
pi[0].Value = coordtobytearray(dLong);
|
|
Pic.SetPropertyItem(pi[0]);
|
|
|
|
pi[0].Id = 0x0002;
|
|
pi[0].Type = 5;
|
|
pi[0].Len = sizeof(ulong) * 3;
|
|
pi[0].Value = coordtobytearray(dLat);
|
|
Pic.SetPropertyItem(pi[0]);
|
|
|
|
pi[0].Id = 0x0006;
|
|
pi[0].Type = 5;
|
|
pi[0].Len = 8;
|
|
pi[0].Value = new Rational(alt).GetBytes();
|
|
Pic.SetPropertyItem(pi[0]);
|
|
|
|
pi[0].Id = 1;
|
|
pi[0].Len = 2;
|
|
pi[0].Type = 2;
|
|
if (dLat < 0)
|
|
{
|
|
pi[0].Value = new byte[] { (byte)'S', 0 };
|
|
}
|
|
else
|
|
{
|
|
pi[0].Value = new byte[] { (byte)'N', 0 };
|
|
}
|
|
Pic.SetPropertyItem(pi[0]);
|
|
|
|
pi[0].Id = 3;
|
|
pi[0].Len = 2;
|
|
pi[0].Type = 2;
|
|
if (dLong < 0)
|
|
{
|
|
pi[0].Value = new byte[] { (byte)'W', 0 };
|
|
}
|
|
else
|
|
{
|
|
pi[0].Value = new byte[] { (byte)'E', 0 };
|
|
}
|
|
Pic.SetPropertyItem(pi[0]);
|
|
|
|
|
|
|
|
string outputfilename = Path.GetDirectoryName(Filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(Filename) + "_geotag" + Path.GetExtension(Filename);
|
|
|
|
File.Delete(outputfilename);
|
|
|
|
Pic.Save(outputfilename);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void BUT_networklinkgeoref_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + "m3u" + Path.DirectorySeparatorChar + "GeoRefnetworklink.kml");
|
|
}
|
|
|
|
private void TXT_logfile_TextChanged(object sender, EventArgs e)
|
|
{
|
|
logcache.Clear();
|
|
}
|
|
}
|
|
|
|
public class Rational
|
|
{
|
|
uint dem = 0;
|
|
uint num = 0;
|
|
|
|
public Rational(double input)
|
|
{
|
|
Value = input;
|
|
}
|
|
|
|
public byte[] GetBytes()
|
|
{
|
|
byte[] answer = new byte[8];
|
|
|
|
Array.Copy(BitConverter.GetBytes((uint)num), 0, answer, 0, sizeof(uint));
|
|
Array.Copy(BitConverter.GetBytes((uint)dem), 0, answer, 4, sizeof(uint));
|
|
|
|
return answer;
|
|
}
|
|
|
|
public double Value {
|
|
get {
|
|
return num / dem;
|
|
}
|
|
set {
|
|
if ((value % 1.0) != 0)
|
|
{
|
|
dem = 100; num = (uint)(value * dem);
|
|
}
|
|
else
|
|
{
|
|
dem = 1; num = (uint)(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|