public bool GetBorderingData(DateTime time, out ImageData before, out ImageData after)
        {
            before = GetClosestDataBefore(time);
            after = GetClosestDataAfter(time);

            if (before != null && after != null)
                return true;

            return false;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlConnection"></param>
        public ImageData GetImageDataFromDatabase(SqlCommand command)
        {
            SqlDataReader reader = null;
            try
            {
                //Console.WriteLine("Attempting to get image data.");
                reader = command.ExecuteReader();
                ImageData Row = new ImageData();

                if(!reader.HasRows)
                {
                    reader.Close();
                    return null;
                }

                if (reader.Read())
                {
                    //ID, TimeStamp, Latitude, Longitude, Altitude, Azimuth, Pitch, Roll, PhotoCounter, IsPhoto

                    int rowId = reader.GetInt32(0);
                    DateTime timestamp = reader.GetDateTime(1);
                    Row.DateTimeCreated = timestamp;
                    Row.GPSHours = timestamp.Hour;
                    Row.GPSMinutes = timestamp.Minute;
                    Row.GPSSeconds = timestamp.Second; // TODO: figure out if this is how the DT should be stored
                    Row.GPSLatitudeDegrees = reader.GetDouble(2);
                    Row.GPSLongitudeDegrees = reader.GetDouble(3);
                    Row.GPSAltitude = (float) reader.GetDouble(4);
                    Row.Yaw = (float) reader.GetDouble(5);
                    Row.Pitch = (float) reader.GetDouble(6);
                    Row.Roll = (float) reader.GetDouble(7);
                    int photocount = reader.GetInt32(8);
                }

                reader.Close();

                return Row;
            }
            catch (Exception e)
            {
                //TODO better error handling
                //Console.WriteLine("Failed to get image data, closing and re-opening database connection.");
                //DatabaseConnection.Close();
               // DatabaseConnection = null;
                //SetupDatabaseConnection();
               // return GetImageDataFromDatabase(command);
                Console.WriteLine("Error reading from database: " + e + " " + e.Message);
                if(reader != null)
                    reader.Close();
                return null;
            }
        }
        /// <summary>
        /// Reads the embedded image data from an image already in memory.
        /// </summary>
        /// <param name="image">Image in memory in which to read the embedded data</param>
        /// <returns>ImageData class with the embedded data.</returns>
        /// <exception cref="System.Exception">
        /// Image loaded does not have all embedded data expected
        /// </exception>
        public static ImageData ReadImage(Image image)
        {
            float num = 0;
            float den = 0;
            int degrees;
            int minutes;
            double seconds;
            String str;
            int height = image.Height;
            int width = image.Width;

            ImageData retData = new ImageData();
            lock (image)
            {
                PropertyItem[] propItems = image.PropertyItems;
                PropertyItem gpsTime = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.gpsTime);
                PropertyItem gpsLat = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.gpsLat);
                PropertyItem gpsLong = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.gpsLong);
                PropertyItem gpsAlt = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.gpsAlt);
                PropertyItem yaw = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.yaw);
                PropertyItem gpsLatRef = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.gpsLatRef);
                PropertyItem gpsLongRef = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.gpsLongRef);
                PropertyItem dateTimeTaken = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.dateTimeTaken);
                PropertyItem cameraModel = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.cameraModel);
                PropertyItem focalLength = propItems.FirstOrDefault(p => p.Id == (int)ProportyItemId.focalLength);

                if (cameraModel != null)
                {
                    str = asciiEncoder.GetString(cameraModel.Value);
                    retData.CameraModel = str;
                }

                if(height > 0)
                {
                    retData.Height = height;
                }

                if (width > 0)
                {
                    retData.Width = width;
                }

                if (dateTimeTaken != null)
                {
                    str = asciiEncoder.GetString(dateTimeTaken.Value);
                    str = str.Trim();
                    str = str.Substring(0, str.Length - 1);
                    StringBuilder s = new StringBuilder(str);
                    s[4] = '/';
                    s[7] = '/';
                    retData.DateTimeCreated = DateTime.Parse(s.ToString());
                }

                if (gpsLatRef != null)
                {
                    retData.GPSLatitudeRef = asciiEncoder.GetString(gpsLatRef.Value, 0, 1);
                }

                if (gpsLongRef != null)
                {
                    retData.GPSLongitudeRef = asciiEncoder.GetString(gpsLongRef.Value, 0, 1);
                }

                if (gpsTime != null)
                {
                    retData.GPSHours = BitConverter.ToInt32(gpsTime.Value, 0);
                    retData.GPSMinutes = BitConverter.ToInt32(gpsTime.Value, 8);
                    num = (float)BitConverter.ToInt32(gpsTime.Value, 16);
                    den = (float)BitConverter.ToInt32(gpsTime.Value, 20);
                    retData.GPSSeconds = num / den;
                }

                if (gpsAlt != null)
                {
                    num = (float)BitConverter.ToInt32(gpsAlt.Value, 0);
                    den = (float)BitConverter.ToInt32(gpsAlt.Value, 4);
                    retData.GPSAltitude = num / den;
                }

                // Latitude
                if (gpsLat != null)
                {
                    degrees = BitConverter.ToInt32(gpsLat.Value, 0);
                    minutes = BitConverter.ToInt32(gpsLat.Value, 8);
                    seconds = (double)BitConverter.ToInt32(gpsLat.Value, 16) / (double)BitConverter.ToInt32(gpsLat.Value, 20);
                    retData.GPSLatitudeDegrees = (double)(degrees * 3600 + minutes * 60 + seconds) / 3600d;
                }

                // Longitude
                if (gpsLong != null)
                {
                    degrees = BitConverter.ToInt32(gpsLong.Value, 0);
                    minutes = BitConverter.ToInt32(gpsLong.Value, 8);
                    seconds = (double)BitConverter.ToInt32(gpsLong.Value, 16) / (double)BitConverter.ToInt32(gpsLong.Value, 20);
                    retData.GPSLongitudeDegrees = (double)(degrees * 3600 + minutes * 60 + seconds) / 3600d;
                }

                if (yaw != null)
                {
                    num = (float)BitConverter.ToInt32(yaw.Value, 0);
                    den = (float)BitConverter.ToInt32(yaw.Value, 4);
                    retData.Yaw = num / den;
                }

                if (focalLength != null)
                {
                    retData.FocalLength = BitConverter.ToInt32(focalLength.Value, 0);
                }
            }

            return retData;
        }
        private static bool PackageAndShipImage(PendingFile image, ImageData data)
        {
            //embed
            if (data != null)
            {
                Console.WriteLine("Embedding data for: " + image.file.Name);
                try
                {
                    data.SaveToImage(image.file.FullName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Failed to embed: " + image.file.Name + ": " + e + ", " + e.Message);
                    return false;
                }
            }
            else
            {
                Console.WriteLine("No data for image: " + image.file.Name + " (is database empty or failing to connect?). Moving to destination with no data.");
            }

            //move
            string destinationFile = DESTINATION_IMAGE_FOLDER + image.file.Name.Split('_')[0];
            if (image.file.Name.ToLower().Contains("thermal"))
                destinationFile += "_" + image.file.Name.Split('_')[1];
            destinationFile += image.file.Extension;

            Console.WriteLine("Moving " + image.file.Name + " to " + destinationFile);
            try
            {
                if (!System.IO.File.Exists(destinationFile))
                    System.IO.File.Move(image.file.FullName, destinationFile);

                if (!System.IO.File.Exists(DESTINATION_IMAGE_FOLDER_BACKUP + image.file.Name))
                System.IO.File.Copy(destinationFile, DESTINATION_IMAGE_FOLDER_BACKUP + image.file.Name);
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to move " + image.file.Name + " to " + destinationFile + ":" + e + ", " + e.Message);
                return false;
            }

            return true;
        }
        public static ImageData interpolate(DateTime imageTime, ImageData earlierData, ImageData laterData)
        {
            float totalTimeSpan = (laterData.DateTimeCreated.Ticks - earlierData.DateTimeCreated.Ticks);
            if (totalTimeSpan == 0)
                return earlierData;

            float scaling = (imageTime.Ticks - earlierData.DateTimeCreated.Ticks) / totalTimeSpan;
            ImageData result = new ImageData();
            result.DateTimeCreated = new DateTime((long)((laterData.DateTimeCreated.Ticks + earlierData.DateTimeCreated.Ticks) * scaling));
            result.GPSHours = earlierData.GPSHours + (int)((-earlierData.GPSHours + laterData.GPSHours) * scaling);
            result.GPSMinutes = earlierData.GPSMinutes + (int)((-earlierData.GPSMinutes + laterData.GPSMinutes) * scaling);
            result.GPSSeconds = earlierData.GPSSeconds + (-earlierData.GPSSeconds + laterData.GPSSeconds) * scaling;
            result.GPSLatitudeDegrees = earlierData.GPSLatitudeDegrees + (-earlierData.GPSLatitudeDegrees + laterData.GPSLatitudeDegrees) * scaling;
            result.GPSLongitudeDegrees = earlierData.GPSLongitudeDegrees + (-earlierData.GPSLongitudeDegrees + laterData.GPSLongitudeDegrees) * scaling;
            result.GPSAltitude = earlierData.GPSAltitude + (-earlierData.GPSAltitude + laterData.GPSAltitude) * scaling;
            result.Yaw = earlierData.Yaw + (-earlierData.Yaw + laterData.Yaw) * scaling;
            result.Pitch = earlierData.Pitch + (-earlierData.Pitch + laterData.Pitch) * scaling;
            result.Roll = earlierData.Roll + (-earlierData.Roll + laterData.Roll) * scaling;

            return result;

            /*
            float scaling;

            if (laterData.DateTimeCreated.Ticks - earlierData.DateTimeCreated.Ticks == 0)
                scaling = 0;
            else
                scaling = (laterData.DateTimeCreated.Ticks - imageTime.Ticks) / (laterData.DateTimeCreated.Ticks - earlierData.DateTimeCreated.Ticks);

            ImageData result = new ImageData();
            result.DateTimeCreated =        new DateTime((long) ((laterData.DateTimeCreated.Ticks + earlierData.DateTimeCreated.Ticks) * scaling));
            result.GPSHours =              (int) (( earlierData.GPSHours +                laterData.GPSHours                ) * scaling);
            result.GPSMinutes =            (int) (( earlierData.GPSMinutes +              laterData.GPSMinutes              ) * scaling);
            result.GPSSeconds =            ( earlierData.GPSSeconds +              laterData.GPSSeconds              ) * scaling;
            result.GPSLatitudeDegrees =    ( earlierData.GPSLatitudeDegrees +      laterData.GPSLatitudeDegrees      ) * scaling;
            result.GPSLongitudeDegrees =   ( earlierData.GPSLongitudeDegrees +     laterData.GPSLongitudeDegrees     ) * scaling;
            result.GPSAltitude =           ( earlierData.GPSAltitude +             laterData.GPSAltitude             ) * scaling;
            result.Yaw =                   ( earlierData.Yaw +                     laterData.Yaw                     ) * scaling;
            result.Pitch =                 ( earlierData.Pitch +                   laterData.Pitch                   ) * scaling;
            result.Roll =                  ( earlierData.Roll +                    laterData.Roll                    ) * scaling;

            return result;
             * */
        }