public static SharpMapillaryInfo LoadGPX(this String GPXFile, Int32? TimeOffset = null, Func<String, DateTime, Double, Double, Double, DateTime> OnDupliateTimestamp = null, Action<DateTime, DateTime, DateTimeKind> OnResult = null) { var Mapillary = new SharpMapillaryInfo(GPXFile.Substring(0, GPXFile.LastIndexOf(Path.DirectorySeparatorChar))); return LoadGPX(GPXFile, ref Mapillary, TimeOffset, OnDupliateTimestamp, OnResult); }
public static SharpMapillaryInfo LoadJPEG(this String JPEGFile, DateTimeKind DateTimeType = DateTimeKind.Utc, Int32? TimeOffset = null, Func<String, DateTime, DateTime> OnDupliateTimestamp = null) { var Mapillary = new SharpMapillaryInfo(JPEGFile.Substring(0, JPEGFile.LastIndexOf(Path.DirectorySeparatorChar))); return LoadJPEG(JPEGFile, ref Mapillary, DateTimeType, TimeOffset, OnDupliateTimestamp); }
public static SharpMapillaryInfo LoadJPEG(String JPEGFile, ref SharpMapillaryInfo MapillaryInfo, DateTimeKind DateTimeType = DateTimeKind.Utc, Int32? TimeOffset = null, Func<String, DateTime, DateTime> OnDupliateTimestamp = null) { #region Initial checks... if (JPEGFile == null) throw new ArgumentNullException("Illegal path!"); if (MapillaryInfo == null) lock (SharpMapillaryLock) { MapillaryInfo = new SharpMapillaryInfo(JPEGFile.Substring(0, JPEGFile.LastIndexOf(Path.DirectorySeparatorChar))); } #endregion #region Init... ImageFile EXIFFile = null; ImageEXIFInfo MapillaryImage = null; var Timestamp = DateTime.MinValue; var Latitude = 0.0; var Longitude = 0.0; var Altitude = 0.0; var Direction = 0.0; MathEx.UFraction32[] EXIF_Latitude; MathEx.UFraction32[] EXIF_Longitude; DMSLatitudeType EXIF_LatitudeO; DMSLongitudeType EXIF_LongitudeO; #endregion DateTimeType = DateTimeKind.Local; try { EXIFFile = ImageFile.FromFile(JPEGFile); if (EXIFFile.Properties.ContainsKey(ExifTag.DateTime)) { Timestamp = DateTime.SpecifyKind((DateTime) EXIFFile.Properties[ExifTag.DateTime].Value, DateTimeType).ToUniversalTime(); if (TimeOffset.HasValue) { if (TimeOffset.Value > 0) Timestamp += TimeSpan.FromSeconds(TimeOffset.Value); else Timestamp -= TimeSpan.FromSeconds(-TimeOffset.Value); } } //if (EXIFFile.Properties.ContainsKey(ExifTag.GPSLatitude)) //{ // EXIF_Latitude = (MathEx.UFraction32[]) EXIFFile.Properties[ExifTag.GPSLatitude]. Value; // EXIF_LatitudeO = (DMSLatitudeType) EXIFFile.Properties[ExifTag.GPSLatitudeRef].Value; //ToDo: Wrong cast! // Latitude = SharpMapillary.ToLatitude(EXIF_Latitude[0].Numerator / (Double) EXIF_Latitude[0].Denominator, // EXIF_Latitude[1].Numerator / (Double) EXIF_Latitude[1].Denominator, // EXIF_Latitude[2].Numerator / (Double) EXIF_Latitude[2].Denominator, // EXIF_LatitudeO); //} //if (EXIFFile.Properties.ContainsKey(ExifTag.GPSLongitude)) //{ // EXIF_Longitude = (MathEx.UFraction32[]) EXIFFile.Properties[ExifTag.GPSLongitude].Value; // EXIF_LongitudeO = (DMSLongitudeType) EXIFFile.Properties[ExifTag.GPSLongitudeRef].Value; //ToDo: Wrong cast! // Longitude = SharpMapillary.ToLongitude(EXIF_Longitude[0].Numerator / (Double) EXIF_Longitude[0].Denominator, // EXIF_Longitude[1].Numerator / (Double) EXIF_Longitude[1].Denominator, // EXIF_Longitude[2].Numerator / (Double) EXIF_Longitude[2].Denominator, // EXIF_LongitudeO); //} //if (EXIFFile.Properties.ContainsKey(ExifTag.GPSAltitude)) // Altitude = (Double) EXIFFile.Properties[ExifTag.GPSAltitude].Value; //if (EXIFFile.Properties.ContainsKey(ExifTag.GPSImgDirection)) // Direction = (Double) EXIFFile.Properties[ExifTag.GPSImgDirection].Value; lock (SharpMapillaryLock) { MapillaryInfo.NumberOfImages++; if (!MapillaryInfo.Images.TryGetValue(Timestamp, out MapillaryImage)) MapillaryInfo.Images.Add(Timestamp, new ImageEXIFInfo(JPEGFile, Timestamp, Latitude, Longitude, Altitude, Direction)); else { if (!MapillaryImage.Timestamp.HasValue) { MapillaryImage.FileName = JPEGFile; MapillaryImage.Timestamp = Timestamp; MapillaryImage.Latitude = Latitude; MapillaryImage.Longitude = Longitude; MapillaryImage.Altitude = Altitude; } else { MapillaryInfo.NumberOfDuplicateEXIFTimestamps++; if (OnDupliateTimestamp != null) { var FixedTimestamp = OnDupliateTimestamp(JPEGFile, Timestamp); MapillaryInfo.Images.Add(FixedTimestamp, new ImageEXIFInfo(JPEGFile, FixedTimestamp, Latitude, Longitude, Altitude, Direction)); } } } } } catch (Exception e) { Console.WriteLine("There is something wrong in file: " + JPEGFile + Environment.NewLine + e.Message); Console.WriteLine("Moving it to the 'errors'-directory!"); Directory.CreateDirectory(MapillaryInfo.FilePath + Path.DirectorySeparatorChar + "errors"); File.Move(JPEGFile, MapillaryInfo.FilePath + Path.DirectorySeparatorChar + "errors" + Path.DirectorySeparatorChar + JPEGFile.Remove(0, JPEGFile.LastIndexOf(Path.DirectorySeparatorChar) + 1)); } return MapillaryInfo; }
public static SharpMapillaryInfo LoadJPEGs(String Path, SearchOption SearchOption = SearchOption.TopDirectoryOnly, SharpMapillaryInfo MapillaryInfo = null, DateTimeKind DateTimeType = DateTimeKind.Utc, Int32? TimeOffset = null, Action<UInt32, UInt32, Double> OnProcessed = null, Func<String, DateTime, DateTime> OnDupliateTimestamp = null, ParallelOptions ParallelOptions = null, Action<DateTime, DateTime, DateTimeKind> OnResult = null, Boolean ParallelProcessing = false) { #region Initial checks... if (Path == null) throw new ArgumentNullException("Illegal path!"); #endregion #region Init... var AllJPegs = Directory.EnumerateFiles(Path, "*.JPG", SearchOption).OrderBy(a => a).ToArray(); var NumberOfJPEGsFound = (UInt32) AllJPegs.Length; var NumberOfJPEGsProcessed = 0; var OnProcessedLocal = OnProcessed; var MinDateTime = DateTime.MaxValue; var MaxDateTime = DateTime.MinValue; #endregion if (ParallelProcessing) { Parallel.ForEach(AllJPegs, ParallelOptions != null ? ParallelOptions : new ParallelOptions() { MaxDegreeOfParallelism = 1 }, JPegFile => { LoadJPEG(JPegFile, ref MapillaryInfo, DateTimeType, TimeOffset, OnDupliateTimestamp); Interlocked.Increment(ref NumberOfJPEGsProcessed); OnProcessedLocal = OnProcessed; if (OnProcessedLocal != null) OnProcessedLocal(NumberOfJPEGsFound, (UInt32) NumberOfJPEGsProcessed, (Double) NumberOfJPEGsProcessed / (Double) NumberOfJPEGsFound * 100); }); } else { foreach (var JPegFile in AllJPegs) { LoadJPEG(JPegFile, ref MapillaryInfo, DateTimeType, TimeOffset, OnDupliateTimestamp); Interlocked.Increment(ref NumberOfJPEGsProcessed); OnProcessedLocal = OnProcessed; if (OnProcessedLocal != null) OnProcessedLocal(NumberOfJPEGsFound, (UInt32) NumberOfJPEGsProcessed, (Double) NumberOfJPEGsProcessed / (Double) NumberOfJPEGsFound * 100); } } #region Process OnResult-delegate... if (OnResult != null) { foreach (var ImageInfo in MapillaryInfo.Images.Values) { if (ImageInfo.Timestamp.Value < MinDateTime) MinDateTime = ImageInfo.Timestamp.Value; if (ImageInfo.Timestamp.Value > MaxDateTime) MaxDateTime = ImageInfo.Timestamp.Value; } OnResult(MinDateTime, MaxDateTime, MinDateTime.Kind); } #endregion return MapillaryInfo; }
public static SharpMapillaryInfo SyncGPS(ref SharpMapillaryInfo MapillaryInfo, GPSInterpolation GPSInterpolation = GPSInterpolation.LinearInterpolation, Double DirectionOffset = 0.0) { #region Data //var Ratio = Math.Round((Double) GPXLookup.Data.Count() / (Double) NumberOfImages, 2); GPSInfo GPSEarly; GPSInfo GPSLate; GPSInfo NextGPSTrackpoint; var GPSEarlyTimestamp = DateTime.MinValue; var GPSLateTimestamp = DateTime.MinValue; var EarlyDiff = 0.0; var LateDiff = 0.0; var GPSTimeRange = 0.0; var GPSEarly2Image_TimeOffset = 0.0; var dx = 0.0; var dy = 0.0; //var GPXArray = GPXLookup.Keys.ToArray(); //var GPXList = GPXLookup.Keys.ToList(); #endregion foreach (var ImageInfo in MapillaryInfo.Images.Values) { // == is an image! if (ImageInfo.FileName != null && ImageInfo.Timestamp.HasValue) { // ToDo: Currently a bit inefficient! GPSEarly = MapillaryInfo.GPSData.Values.Where(v => ImageInfo.Timestamp >= v.Timestamp).LastOrDefault(); GPSLate = MapillaryInfo.GPSData.Values.Where(v => ImageInfo.Timestamp <= v.Timestamp).FirstOrDefault(); //var GPXIndex = GPXList.BinarySearch(timestamp); //LateTimestamp = (GPXIndex >= 0) ? GPXArray[GPXIndex] : GPXArray[-GPXIndex - 1]; // Returns the next timestamp if no exact match was found! if (GPSEarly == null) { Console.WriteLine("Could not find a GPSEarly timestamp!"); Environment.Exit(1); } if (GPSLate == null) { Console.WriteLine("Could not find a GPSLate timestamp!"); Environment.Exit(1); } // Ignore GPS-less images without GPS coordinates // before and after the image was taken! if (GPSEarly != null && GPSLate != null) { GPSEarlyTimestamp = GPSEarly != null ? GPSEarly.Timestamp.Value : DateTime.MinValue; GPSLateTimestamp = GPSLate != null ? GPSLate. Timestamp.Value : DateTime.MaxValue; EarlyDiff = (ImageInfo.Timestamp.Value - GPSEarlyTimestamp) .TotalSeconds; LateDiff = (GPSLateTimestamp - ImageInfo.Timestamp.Value).TotalSeconds; ImageInfo.Image2GPS_TimeDifference = (EarlyDiff < LateDiff) ? -EarlyDiff : LateDiff; #region Update DiffHistogram if (!MapillaryInfo.DiffHistogram.ContainsKey(ImageInfo.Image2GPS_TimeDifference)) MapillaryInfo.DiffHistogram.Add(ImageInfo.Image2GPS_TimeDifference, 1); else MapillaryInfo.DiffHistogram[ImageInfo.Image2GPS_TimeDifference]++; #endregion #region A image sharing its timestamp with a GPS coordinate! if (ImageInfo.Image2GPS_TimeDifference == 0) { #region Set Lat/Lng/Alt ImageInfo.Latitude = GPSEarly.Latitude; ImageInfo.Longitude = GPSEarly.Longitude; ImageInfo.Altitude = GPSEarly.Altitude; #endregion #region Calculate image direction // ToDo: Currently a bit inefficient! NextGPSTrackpoint = MapillaryInfo.GPSData.Values.Where(v => ImageInfo.Timestamp < v.Timestamp).FirstOrDefault(); if (NextGPSTrackpoint != null) { dy = GPSEarly.Latitude - NextGPSTrackpoint.Latitude; dx = Math.Cos(Math.PI / 180 * NextGPSTrackpoint.Latitude) * (NextGPSTrackpoint.Longitude - GPSEarly.Longitude); } #endregion } #endregion else { #region GPSInterpolation switch (GPSInterpolation) { case GPSInterpolation.NearestMatch: ImageInfo.Latitude = (EarlyDiff < LateDiff) ? GPSEarly.Latitude : GPSLate.Latitude; ImageInfo.Longitude = (EarlyDiff < LateDiff) ? GPSEarly.Longitude : GPSLate.Longitude; ImageInfo.Altitude = (EarlyDiff < LateDiff) ? GPSEarly.Altitude : GPSLate.Altitude; break; case GPSInterpolation.LinearInterpolation: GPSTimeRange = (GPSLateTimestamp - GPSEarlyTimestamp).TotalSeconds; GPSEarly2Image_TimeOffset = (ImageInfo.Timestamp.Value - GPSEarlyTimestamp).TotalSeconds; ImageInfo.Latitude = GPSEarly.Latitude - (GPSEarly.Latitude - GPSLate.Latitude) / GPSTimeRange * GPSEarly2Image_TimeOffset; ImageInfo.Longitude = GPSEarly.Longitude - (GPSEarly.Longitude - GPSLate.Longitude) / GPSTimeRange * GPSEarly2Image_TimeOffset; ImageInfo.Altitude = GPSEarly.Altitude - (GPSEarly.Altitude - GPSLate.Altitude) / GPSTimeRange * GPSEarly2Image_TimeOffset; break; } #endregion #region Calculate image direction dy = GPSEarly.Latitude - GPSLate.Latitude; dx = Math.Cos(Math.PI / 180 * GPSLate.Latitude) * (GPSLate.Longitude - GPSEarly.Longitude); #endregion } #region Calculate image direction ImageInfo.ViewingDirection = (90 + Math.Atan2(dy, dx) * 180 / Math.PI + DirectionOffset) % 360; if (ImageInfo.ViewingDirection < 0) ImageInfo.ViewingDirection += 360; #endregion ImageInfo.NoValidGPSFound = false; } else { ImageInfo.NoValidGPSFound = true; MapillaryInfo.NumberOfImagesWithoutGPS++; } } } #region Store DiffHistogram using (var DiffHistogramFile = new StreamWriter(MapillaryInfo.FilePath + Path.DirectorySeparatorChar + @"DiffHistogram.txt")) { foreach (var KVPair in MapillaryInfo.DiffHistogram) DiffHistogramFile.WriteLine(String.Concat(KVPair.Key, ";", KVPair.Value)); } #endregion return MapillaryInfo; }
public static SharpMapillaryInfo LoadGPX(String GPXFile, ref SharpMapillaryInfo MapillaryInfo, Int32? TimeOffset = null, Func<String, DateTime, Double, Double, Double, DateTime> OnDupliateTimestamp = null, Action<DateTime, DateTime, DateTimeKind> OnResult = null) { #region GPX XML docu... // <?xml version="1.0" encoding="UTF-8"?> // <gpx version="1.1" // creator="RunKeeper - http://www.runkeeper.com" // xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" // xmlns="http://www.topografix.com/GPX/1/1" // xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" // xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"> // <trk> // <name><![CDATA[Cycling 7/22/14 1:29 pm]]></name> // <time>2014-07-22T13:29:07Z</time> // <trkseg> // <trkpt lat="50.927267000" lon="11.612756000"><ele>236.0</ele><time>2014-07-22T13:29:07Z</time></trkpt> // <trkpt lat="50.927267000" lon="11.612754000"><ele>236.0</ele><time>2014-07-22T13:29:09Z</time></trkpt> // <trkpt lat="50.927367000" lon="11.612731000"><ele>236.0</ele><time>2014-07-22T13:29:33Z</time></trkpt> // <trkpt lat="50.927454000" lon="11.612754000"><ele>235.0</ele><time>2014-07-22T13:29:35Z</time></trkpt> // <trkpt lat="50.927563000" lon="11.612748000"><ele>234.2</ele><time>2014-07-22T13:29:37Z</time></trkpt> // </trkseg> // </trk> // </gpx> #endregion #region Initial checks... if (GPXFile == null) throw new ArgumentNullException("Illegal path!"); if (MapillaryInfo == null) MapillaryInfo = new SharpMapillaryInfo(GPXFile.Substring(0, GPXFile.LastIndexOf(Path.DirectorySeparatorChar))); #endregion #region Init... XNamespace NS = "http://www.topografix.com/GPX/1/1"; GPSInfo GPSInfoElement = null; DateTime Timestamp; Double Latitude; Double Longitude; Double Altitude; var MinDateTime = DateTime.MaxValue; var MaxDateTime = DateTime.MinValue; #endregion try { foreach (var GPSTrackPoint in XDocument.Load(GPXFile). Root. Elements(NS + "trk"). Elements(NS + "trkseg"). Elements(NS + "trkpt")) { Timestamp = DateTime.Parse(GPSTrackPoint.Element(NS + "time").Value).ToUniversalTime(); if (TimeOffset.HasValue) { if (TimeOffset.Value > 0) Timestamp += TimeSpan.FromSeconds(TimeOffset.Value); else Timestamp -= TimeSpan.FromSeconds(-TimeOffset.Value); } if (Timestamp < MinDateTime) MinDateTime = Timestamp; if (Timestamp > MaxDateTime) MaxDateTime = Timestamp; Latitude = Double. Parse(GPSTrackPoint.Attribute("lat").Value, CultureInfo.InvariantCulture); Longitude = Double. Parse(GPSTrackPoint.Attribute("lon").Value, CultureInfo.InvariantCulture); Altitude = Double. Parse(GPSTrackPoint.Element(NS + "ele").Value, CultureInfo.InvariantCulture); MapillaryInfo.NumberOfGPSPoints++; if (!MapillaryInfo.GPSData.TryGetValue(Timestamp, out GPSInfoElement)) MapillaryInfo.GPSData.Add(Timestamp, new GPSInfo(Timestamp, Latitude, Longitude, Altitude)); else { MapillaryInfo.NumberOfDuplicateGPSTimestamps++; if (OnDupliateTimestamp != null) { var FixedTimestamp = OnDupliateTimestamp(GPXFile, Timestamp, Latitude, Longitude, Altitude); MapillaryInfo.GPSData.Add(FixedTimestamp, new GPSInfo(FixedTimestamp, Latitude, Longitude, Altitude)); } } } } catch (Exception e) { Console.WriteLine("There is something wrong in file: " + GPXFile + Environment.NewLine + e.Message); } if (OnResult != null) OnResult(MinDateTime, MaxDateTime, MinDateTime.Kind); return MapillaryInfo; }
public static SharpMapillaryInfo LoadGPXs(String Path, SharpMapillaryInfo MapillaryInfo = null, Int32? TimeOffset = null, Func<String, DateTime, Double, Double, Double, DateTime> OnDupliateTimestamp = null, Action<DateTime, DateTime, DateTimeKind> OnResult = null) { #region Initial checks... if (Path == null) throw new ArgumentNullException("Illegal path!"); #endregion foreach (var GPXFile in Directory.EnumerateFiles(Path, "*.gpx")) LoadGPX(GPXFile, ref MapillaryInfo, TimeOffset, OnDupliateTimestamp, OnResult); return MapillaryInfo; }
/// <summary> /// Store the given SharpMapillaryInfo within the given subdirectory. /// </summary> /// <param name="MapillaryInfo">A SharpMapillaryInfo data structure.</param> /// <param name="SubDirectory">A subdirectory for storing the processed Mapillary images.</param> /// <param name="SubDirectoryNoGPS">A subdirectory for storing Mapillary images without valid GPS data.</param> </param> /// <param name="OnProcessed">An optional delegate to be invoked for every processed SharpMapillaryInfo.</param> /// <param name="ParallelOptions">Optional for controlling the multi-threading behaviour.</param> public static SharpMapillaryInfo Store(ref SharpMapillaryInfo MapillaryInfo, String SubDirectory = "fixed", String SubDirectoryNoGPS = "noGPS", Action<UInt32, UInt32, Double> OnProcessed = null, ParallelOptions ParallelOptions = null) { #region Data if (MapillaryInfo == null) throw new ArgumentNullException("MapillaryInfo", "The given parameter must not be null!"); // ref/out parameters are not allowed inside Parallel.ForEach! var _MapillaryInfo = MapillaryInfo; var EXIFFile = new ThreadLocal<ImageFile>(); var LatitudeDMS = new ThreadLocal<DMS>(); var LongitudeDMS = new ThreadLocal<DMS>(); var newImage = new ThreadLocal<Bitmap>(); var oldImage = new ThreadLocal<Bitmap>(); var g = new ThreadLocal<Graphics>(); var NewFilePath = new ThreadLocal<String>(); var NumberOfJPEGs = (UInt32) MapillaryInfo.Images.Count; var NumberOfJPEGsProcessed = 0; var NumberOfImagesWithoutGPS = 0; var OnProcessedLocal = OnProcessed; #endregion Directory.CreateDirectory(MapillaryInfo.FilePath + Path.DirectorySeparatorChar + SubDirectory); Parallel.ForEach(MapillaryInfo.Images.Values, ParallelOptions != null ? ParallelOptions : new ParallelOptions() { MaxDegreeOfParallelism = 8 }, ImageInfo => { // == is an image! if (ImageInfo.FileName != null && ImageInfo.Timestamp.HasValue) { #region Valid GPS data... if (ImageInfo.NoValidGPSFound.HasValue && ImageInfo.NoValidGPSFound.Value == false && ImageInfo.Latitude. HasValue && ImageInfo.Longitude.HasValue && ImageInfo.Altitude. HasValue) { #region Load image and update EXIF metadata... var MS = new MemoryStream(); try { EXIFFile.Value = ImageFile.FromFile(ImageInfo.FileName); #region Set/update EXIF data... LatitudeDMS. Value = ImageInfo.Latitude. Value.ToDMSLat(); LongitudeDMS.Value = ImageInfo.Longitude.Value.ToDMSLng(); //if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.GPSLatitude)) EXIFFile.Value.Properties.Set(ExifTag.GPSLatitude, LatitudeDMS.Value.Degree, LatitudeDMS.Value.Minute, LatitudeDMS.Value.Second); if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.GPSLatitudeRef)) EXIFFile.Value.Properties.Set(ExifTag.GPSLatitudeRef, ImageInfo.Latitude > 0 ? GPSLatitudeRef.North : GPSLatitudeRef.South); //if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.GPSLongitude)) EXIFFile.Value.Properties.Set(ExifTag.GPSLongitude, LongitudeDMS.Value.Degree, LongitudeDMS.Value.Minute, LongitudeDMS.Value.Second); if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.GPSLongitudeRef)) EXIFFile.Value.Properties.Set(ExifTag.GPSLongitudeRef, ImageInfo.Longitude > 0 ? GPSLongitudeRef.East : GPSLongitudeRef.West); //if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.GPSAltitude)) EXIFFile.Value.Properties.Set(ExifTag.GPSAltitude, ImageInfo.Altitude.Value); if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.GPSAltitudeRef)) EXIFFile.Value.Properties.Set(ExifTag.GPSAltitudeRef, GPSAltitudeRef.AboveSeaLevel); //if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.GPSImgDirection)) EXIFFile.Value.Properties.Add(new ExifURational(ExifTag.GPSImgDirection, new MathEx.UFraction32(ImageInfo.ViewingDirection))); if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.Artist)) EXIFFile.Value.Properties.Set(ExifTag.Artist, "Achim 'ahzf' Friedland <*****@*****.**>"); //// Used by GoPro //if (!EXIFFile.Properties.ContainsKey(ExifTag.ImageDescription)) // EXIFFile.Properties.Set(ExifTag.ImageDescription, "ImageDescription"); //// Used by GoPro //if (!EXIFFile.Properties.ContainsKey(ExifTag.Software)) // EXIFFile.Properties.Set(ExifTag.Software, "Software"); if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.UserComment)) EXIFFile.Value.Properties.Set(ExifTag.UserComment, "Mapillary"); if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.WindowsAuthor)) EXIFFile.Value.Properties.Set(ExifTag.WindowsAuthor, "Achim 'ahzf' Friedland <*****@*****.**>"); //if (!EXIFFile.Properties.ContainsKey(ExifTag.WindowsComment)) // EXIFFile.Properties.Set(ExifTag.WindowsComment, "WindowsComment"); if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.WindowsKeywords)) EXIFFile.Value.Properties.Set(ExifTag.WindowsKeywords, "Mapillary; Deutschland; Thüringen; Jena; GPSLinearInterpolation"); if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.WindowsSubject)) EXIFFile.Value.Properties.Set(ExifTag.WindowsSubject, "Mapillary"); //if (!EXIFFile.Properties.ContainsKey(ExifTag.WindowsTitle)) // EXIFFile.Properties.Set(ExifTag.WindowsTitle, "WindowsTitle"); if (!EXIFFile.Value.Properties.ContainsKey(ExifTag.Copyright)) EXIFFile.Value.Properties.Set(ExifTag.Copyright, "Creative Commons Attribution-NonCommercial 4.0 International License (CC BY-NC)"); //if (!EXIFFile.Properties.ContainsKey(ExifTag.ImageUniqueID)) // EXIFFile.Properties.Set(ExifTag.ImageUniqueID, "4711"); #endregion EXIFFile.Value.Save(MS); } catch (Exception e) { Console.WriteLine("Exception during 'Load image and update EXIF metadata': " + e.Message); } #endregion #region Resize and store the image... try { #region Load Image from memory stream and resize it... oldImage.Value = new Bitmap(MS); newImage.Value = new Bitmap((Int32)_MapillaryInfo.FinalImageWidth, (Int32)_MapillaryInfo.FinalImageHeight); g.Value = Graphics.FromImage((Image)newImage.Value); g.Value.InterpolationMode = InterpolationMode.HighQualityBicubic; g.Value.CompositingQuality = CompositingQuality.HighQuality; g.Value.CompositingMode = CompositingMode.SourceCopy; g.Value.DrawImage(oldImage.Value, 0, 0, (Int32)_MapillaryInfo.FinalImageWidth, (Int32)_MapillaryInfo.FinalImageHeight); g.Value.Dispose(); #endregion #region Copy EXIF metadata // Copy all metadata... foreach (var PropertyItem in oldImage.Value.PropertyItems) newImage.Value.SetPropertyItem(PropertyItem); //// Get an ImageCodecInfo object that represents the JPEG codec. //var imageCodecInfo = GetEncoderInfo(ImageFormat.Jpeg); //// Create an Encoder object for the Quality parameter. //var encoder = Encoder.Quality; //// Create an EncoderParameters object. //EncoderParameters encoderParameters = new EncoderParameters(1); //// Save the image as a JPEG file with quality level. //EncoderParameter encoderParameter = new EncoderParameter(encoder, quality); //encoderParameters.Param[0] = encoderParameter; //newImage.Save(filePath, imageCodecInfo, encoderParameters); #endregion #region Store resized image on disc... // Generate new file name including a possible subdirectory... NewFilePath.Value = String.Concat(_MapillaryInfo.FilePath, Path.DirectorySeparatorChar, SubDirectory, ImageInfo.FileName.Replace(_MapillaryInfo.FilePath, "")); // Check if the possible subdirectory already exists... or create it! Directory.CreateDirectory(NewFilePath.Value.Substring(0, NewFilePath.Value.LastIndexOf(Path.DirectorySeparatorChar))); newImage.Value.Save(NewFilePath.Value, ImageFormat.Jpeg); newImage.Value.Dispose(); MS.Dispose(); #endregion } catch (Exception e) { Console.WriteLine("Exception during 'Resize and store the image': " + e.Message); } #endregion Interlocked.Increment(ref NumberOfJPEGsProcessed); OnProcessedLocal = OnProcessed; if (OnProcessedLocal != null) OnProcessedLocal(NumberOfJPEGs, (UInt32) NumberOfJPEGsProcessed, (Double) NumberOfJPEGsProcessed / (Double) NumberOfJPEGs * 100); } #endregion #region ...no valid GPS data! else { if (ImageInfo.FileName != null) { Directory.CreateDirectory(_MapillaryInfo.FilePath + Path.DirectorySeparatorChar + SubDirectoryNoGPS); File.Copy(ImageInfo.FileName, _MapillaryInfo.FilePath + Path.DirectorySeparatorChar + SubDirectoryNoGPS + Path.DirectorySeparatorChar + ImageInfo.FileName.Remove(0, ImageInfo.FileName.LastIndexOf(Path.DirectorySeparatorChar) + 1)); Interlocked.Increment(ref NumberOfImagesWithoutGPS); } } #endregion } }); _MapillaryInfo.NumberOfImagesWithoutGPS = (UInt32) NumberOfImagesWithoutGPS; return _MapillaryInfo; }