public static GpsHelper FromDouble(double angleInDegrees)
        {
            //ensure the value will fall within the primary range [-180.0..+180.0]
            while (angleInDegrees < -180.0)
            {
                angleInDegrees += 360.0;
            }

            while (angleInDegrees > 180.0)
            {
                angleInDegrees -= 360.0;
            }

            var result = new GpsHelper {
                IsNegative = angleInDegrees < 0
            };

            //switch the value to positive
            angleInDegrees = Math.Abs(angleInDegrees);

            //gets the degree
            result.Degrees = (int)Math.Floor(angleInDegrees);
            var delta = angleInDegrees - result.Degrees;

            //gets minutes and seconds
            var seconds = (int)Math.Floor(3600.0 * delta);

            result.Seconds = seconds % 60;
            result.Minutes = (int)Math.Floor(seconds / 60.0);
            delta          = delta * 3600.0 - seconds;

            //gets fractions
            result.Milliseconds = (int)(1000.0 * delta);

            return(result);
        }
Exemplo n.º 2
0
        public static void SetMetadata(string imgSourcePath, string metadata, bool fixImageOrientation = true)
        {
            var saveimage = false;

            try
            {
                ImageFile fileInfo;

                try
                {
                    //Retrieve current known metadata for the image
                    fileInfo = ImageFile.FromFile(imgSourcePath);
                }
                catch //Most likely this type of image is either not supported by the Exif library or does not have any Exif information
                {
                    return;
                }

                if (!string.IsNullOrWhiteSpace(metadata))
                {
                    var defaultProperties = fileInfo.Properties.Count;

                    //Iterate through all properties to be set on the image
                    foreach (var geoElement in JObject.Parse(metadata))
                    {
                        //Current new property has a valid value?
                        if (!string.IsNullOrEmpty(geoElement.Value.Value <string>()))
                        {
                            //Is the current geolocation element supported?
                            if (Geoloc2ExifPropertyMapper.ContainsKey(geoElement.Key))
                            {
                                //Get current EXIF tag for the current geolocation property
                                var currentExifTag = (ExifTag)Geoloc2ExifPropertyMapper[geoElement.Key];
                                var exifProperty   =
                                    fileInfo.Properties.FirstOrDefault(p =>
                                                                       p.IFD == IFD.GPS && p.Tag == currentExifTag);

                                //Image does not contain this property in the metadata
                                if (exifProperty == null)
                                {
                                    switch (currentExifTag)
                                    {
                                    case ExifTag.GPSLatitude:
                                        var lat            = GpsHelper.FromDouble(geoElement.Value.Value <double>());
                                        var newLatProperty = new GPSLatitudeLongitude(ExifTag.GPSLatitude,
                                                                                      lat.Degrees, lat.Minutes, lat.Seconds);
                                        fileInfo.Properties.Add(newLatProperty);
                                        var newLatRefProperty = new ExifAscii(ExifTag.GPSLatitudeRef,
                                                                              geoElement.Value.Value <double>() > 0 ? "N" : "S", Encoding.ASCII);
                                        fileInfo.Properties.Add(newLatRefProperty);
                                        break;

                                    case ExifTag.GPSLongitude:
                                        var lng             = GpsHelper.FromDouble(geoElement.Value.Value <double>());
                                        var newLongProperty = new GPSLatitudeLongitude(ExifTag.GPSLongitude,
                                                                                       lng.Degrees, lng.Minutes, lng.Seconds);
                                        fileInfo.Properties.Add(newLongProperty);
                                        var newLongRefProperty = new ExifAscii(ExifTag.GPSLongitudeRef,
                                                                               geoElement.Value.Value <double>() > 0 ? "E" : "W", Encoding.ASCII);
                                        fileInfo.Properties.Add(newLongRefProperty);
                                        break;

                                    case ExifTag.GPSDOP:
                                        var newDopProperty = new ExifSRational(ExifTag.GPSDOP,
                                                                               new MathEx.Fraction32(geoElement.Value.Value <double>()));
                                        fileInfo.Properties.Add(newDopProperty);
                                        break;

                                    case ExifTag.GPSAltitude:
                                        var newAltitudeProperty = new ExifSRational(ExifTag.GPSAltitude,
                                                                                    new MathEx.Fraction32(geoElement.Value.Value <double>()));
                                        fileInfo.Properties.Add(newAltitudeProperty);
                                        var newAltitudeRefProperty = new ExifByte(ExifTag.GPSAltitudeRef, 0);
                                        fileInfo.Properties.Add(newAltitudeRefProperty);
                                        break;

                                    case ExifTag.GPSSpeed:
                                        var newSpeedProperty = new ExifSRational(ExifTag.GPSSpeed,
                                                                                 new MathEx.Fraction32(
                                                                                     geoElement.Value.Value <double>() * 3.6)); //Convert to Km/h
                                        fileInfo.Properties.Add(newSpeedProperty);

                                        if (fileInfo.Properties.All(p => p.Name != ExifTag.GPSSpeedRef.ToString()))
                                        {
                                            var newSpeedRefProperty = new ExifAscii(ExifTag.GPSSpeedRef, "K",
                                                                                    Encoding.ASCII); //Km/h
                                            fileInfo.Properties.Add(newSpeedRefProperty);
                                        }

                                        break;

                                    case ExifTag.GPSImgDirection:
                                        var newDirectionProperty = new ExifSRational(ExifTag.GPSImgDirection,
                                                                                     new MathEx.Fraction32(geoElement.Value.Value <double>()));
                                        fileInfo.Properties.Add(newDirectionProperty);

                                        if (fileInfo.Properties.All(p =>
                                                                    p.Name != ExifTag.GPSImgDirectionRef.ToString()))
                                        {
                                            var newDirectionRefProperty = new ExifAscii(ExifTag.GPSImgDirectionRef,
                                                                                        "T", Encoding.ASCII); //True North
                                            fileInfo.Properties.Add(newDirectionRefProperty);
                                        }

                                        break;
                                    }
                                }
                            }
                        }
                    }

                    //Set additional information in EXIF header
                    if (defaultProperties < fileInfo.Properties.Count)
                    {
                        saveimage = true;

                        if (fileInfo.Properties.FirstOrDefault(p => p.Name == ExifTag.Software.ToString()) == null)
                        {
                            var newSoftwaredProperty = new ExifAscii(ExifTag.Software, ExifDefaultSoftware, Encoding.ASCII);
                            fileInfo.Properties.Add(newSoftwaredProperty);
                        }

                        if (fileInfo.Properties.FirstOrDefault(p => p.Name == ExifTag.GPSDateStamp.ToString()) == null)
                        {
                            var newDateStampProperty = new ExifAscii(ExifTag.GPSDateStamp, DateTime.Now.Date.ToString("yyyy:MM:dd"), Encoding.ASCII);
                            fileInfo.Properties.Add(newDateStampProperty);
                        }

                        if (fileInfo.Properties.FirstOrDefault(p => p.Name == ExifTag.GPSTimeStamp.ToString()) == null)
                        {
                            var newTimeStampProperty = new GPSLatitudeLongitude(ExifTag.GPSTimeStamp, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);
                            fileInfo.Properties.Add(newTimeStampProperty);
                        }
                    }
                }

                //Image orientation needs correction?
                if (fixImageOrientation)
                {
                    var imgOrientation = fileInfo.Properties.FirstOrDefault(i => i.Name == ExifTag.Orientation.ToString());

                    if (imgOrientation != null)
                    {
                        var orientationValue = BitConverter.ToUInt16(imgOrientation.Interoperability.Data, 0);

                        if (orientationValue != (int)RotateFlipType.RotateNoneFlipNone)
                        {
                            var rotateFlipType = GetRotateFlipTypeByExifOrientationData(orientationValue);

                            if (rotateFlipType != RotateFlipType.RotateNoneFlipNone)
                            {
                                //Get copy of current exif data from original image
                                var exifData = fileInfo.Properties.ToArray();

                                //Remove thumbnail related data from original image
                                foreach (var thumbData in exifData.Where(p => p.IFD == IFD.First || p.IFD == IFD.JFIF).ToArray())
                                {
                                    fileInfo.Properties.Remove(thumbData);
                                }

                                SaveImageFileWithRetry(fileInfo, imgSourcePath);

                                //Flip image
                                using (var img = Image.FromFile(imgSourcePath))
                                {
                                    var encoderParams = new EncoderParameters
                                    {
                                        Param = { [0] = new EncoderParameter(Encoder.Quality, 90L) }
                                    };

                                    img.RotateFlip(rotateFlipType);
                                    img.RemovePropertyItem((int)ExifTag.Orientation - (int)IFD.Zeroth);
                                    img.Save(imgSourcePath, GetEncoder(ImageFormat.Jpeg), encoderParams);

                                    saveimage = false;
                                }
                            }
                        }
                    }
                }

                //Save changes in EXIF header
                if (saveimage)
                {
                    SaveImageFileWithRetry(fileInfo, imgSourcePath);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error in ACTransit.Framework.Imaging.SetMetadata", ex);
            }
        }