EXIF PropertyTagGpsLatitude 格式
EXIF PropertyTagGpsLatitude Format
我正在以编程方式更新一堆扫描的 jpg 图像的 exif 数据
我更新大多数 exif 数据没有太大问题,但我很难设置 gps 坐标
例如我正在尝试按如下方式保存纬度坐标
PropertyItem PropertyTagGpsLatitude = srcImg.GetPropertyItem(2);
PropertyTagGpsLatitude.Value = System.Text.ASCIIEncoding.ASCII.GetBytes("42/1,5/1,33/1");
srcImg.SetPropertyItem(PropertyTagGpsLatitude);
根据其说明的文档
Latitude is expressed as three rational values giving the degrees,
minutes, and seconds respectively. When degrees, minutes, and seconds
are expressed, the format is dd/1, mm/1, ss/1. When degrees and
minutes are used and, for example, fractions of minutes are given up
to two decimal places, the format is dd/1, mmmm/100, 0/1.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
我可以设置其他 gps 相关数据,例如这个转换正确
PropertyItem PropertyTagGpsLatitudeRef = srcImg.GetPropertyItem(1);
PropertyTagGpsLatitudeRef.Value = System.Text.ASCIIEncoding.ASCII.GetBytes("N");
srcImg.SetPropertyItem(PropertyTagGpsLatitudeRef);
我没有遇到任何异常,我只是使用 Exif Pilot 实用程序验证 exif 数据,发现它无法正常工作
我终于想出了一个可行的解决方案。我加载了一张包含 GPS 信息的现有图像,以检查数据的结构。 Ultimatley 我能够在这里想出这个方法
/// <summary>
/// Prepares a byte array that hold EXIF latitude/longitude data
/// </summary>
/// <param name="degrees">There are 360° of longitude (180° E ↔ 180° W) and 180° of latitude (90° N ↔ 90° S)</param>
/// <param name="minutes">Each degree can be broken into 60 minutes</param>
/// <param name="seconds">Each minute can be divided into 60 seconds (”). For finer accuracy, fractions of seconds given by a decimal point are used. Seconds unit multiplied by 100. For example 33.77 seconds is passed as 3377. This gives adequate GPS precision</param>
/// <returns></returns>
private static byte[] FloatToExifGps(int degrees, int minutes, int seconds)
{
var secBytes = BitConverter.GetBytes(seconds);
var secDivisor = BitConverter.GetBytes(100);
byte[] rv = { (byte)degrees, 0, 0, 0, 1, 0, 0, 0, (byte)minutes, 0, 0, 0, 1, 0, 0, 0, secBytes[0], secBytes[1], 0, 0, secDivisor[0], 0, 0, 0 };
return rv;
}
然后像这样使用它
PropertyItem PropertyTagGpsLongitude = srcImg.GetPropertyItem(4);
PropertyTagGpsLongitude.Value = FloatToExifGps(79, 48, 3377);
srcImg.SetPropertyItem(PropertyTagGpsLongitude);
我希望这对以后的人有所帮助
我最近遇到了同样的问题,想分享对我有用的解决方案。 LongitudeDegreeNumerator等变量都是uint类型,提前计算。
// Longitude: Build a whole property value
byte[] propertyTagGpsLongitude = new byte[24];
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeDegreeNumerator), 0, propertyTagGpsLongitude, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeDegreeDenominator), 0, propertyTagGpsLongitude, 4, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeMinuteNumerator), 0, propertyTagGpsLongitude, 8, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeMinuteDenominator), 0, propertyTagGpsLongitude, 12, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeSecondNumerator), 0, propertyTagGpsLongitude, 16, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeSecondDenominator), 0, propertyTagGpsLongitude, 20, 4);
也许这对某人有用。
我正在以编程方式更新一堆扫描的 jpg 图像的 exif 数据
我更新大多数 exif 数据没有太大问题,但我很难设置 gps 坐标
例如我正在尝试按如下方式保存纬度坐标
PropertyItem PropertyTagGpsLatitude = srcImg.GetPropertyItem(2);
PropertyTagGpsLatitude.Value = System.Text.ASCIIEncoding.ASCII.GetBytes("42/1,5/1,33/1");
srcImg.SetPropertyItem(PropertyTagGpsLatitude);
根据其说明的文档
Latitude is expressed as three rational values giving the degrees, minutes, and seconds respectively. When degrees, minutes, and seconds are expressed, the format is dd/1, mm/1, ss/1. When degrees and minutes are used and, for example, fractions of minutes are given up to two decimal places, the format is dd/1, mmmm/100, 0/1.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
我可以设置其他 gps 相关数据,例如这个转换正确
PropertyItem PropertyTagGpsLatitudeRef = srcImg.GetPropertyItem(1);
PropertyTagGpsLatitudeRef.Value = System.Text.ASCIIEncoding.ASCII.GetBytes("N");
srcImg.SetPropertyItem(PropertyTagGpsLatitudeRef);
我没有遇到任何异常,我只是使用 Exif Pilot 实用程序验证 exif 数据,发现它无法正常工作
我终于想出了一个可行的解决方案。我加载了一张包含 GPS 信息的现有图像,以检查数据的结构。 Ultimatley 我能够在这里想出这个方法
/// <summary>
/// Prepares a byte array that hold EXIF latitude/longitude data
/// </summary>
/// <param name="degrees">There are 360° of longitude (180° E ↔ 180° W) and 180° of latitude (90° N ↔ 90° S)</param>
/// <param name="minutes">Each degree can be broken into 60 minutes</param>
/// <param name="seconds">Each minute can be divided into 60 seconds (”). For finer accuracy, fractions of seconds given by a decimal point are used. Seconds unit multiplied by 100. For example 33.77 seconds is passed as 3377. This gives adequate GPS precision</param>
/// <returns></returns>
private static byte[] FloatToExifGps(int degrees, int minutes, int seconds)
{
var secBytes = BitConverter.GetBytes(seconds);
var secDivisor = BitConverter.GetBytes(100);
byte[] rv = { (byte)degrees, 0, 0, 0, 1, 0, 0, 0, (byte)minutes, 0, 0, 0, 1, 0, 0, 0, secBytes[0], secBytes[1], 0, 0, secDivisor[0], 0, 0, 0 };
return rv;
}
然后像这样使用它
PropertyItem PropertyTagGpsLongitude = srcImg.GetPropertyItem(4);
PropertyTagGpsLongitude.Value = FloatToExifGps(79, 48, 3377);
srcImg.SetPropertyItem(PropertyTagGpsLongitude);
我希望这对以后的人有所帮助
我最近遇到了同样的问题,想分享对我有用的解决方案。 LongitudeDegreeNumerator等变量都是uint类型,提前计算。
// Longitude: Build a whole property value
byte[] propertyTagGpsLongitude = new byte[24];
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeDegreeNumerator), 0, propertyTagGpsLongitude, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeDegreeDenominator), 0, propertyTagGpsLongitude, 4, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeMinuteNumerator), 0, propertyTagGpsLongitude, 8, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeMinuteDenominator), 0, propertyTagGpsLongitude, 12, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeSecondNumerator), 0, propertyTagGpsLongitude, 16, 4);
Buffer.BlockCopy(BitConverter.GetBytes(LongitudeSecondDenominator), 0, propertyTagGpsLongitude, 20, 4);
也许这对某人有用。