如何将经度和纬度转换为 GPS Exif 字节数组
How do I convert longitude and latitude to GPS Exif byte array
我正在尝试将纬度 = 8°50'34.46" 和经度 = 125° 9'50.82" 放入图像的 exif 文件中。我正在使用 vb.net.
我在将度数和分钟转换为字节时没有问题,因为它是一个整数,但是当我将具有十进制值的秒 (34.46") 转换为字节时。它给出不同的结果,如 0.9856。
请大家帮助我如何将十进制数字转换为字节。
这里是代码:
Private Shared Function intToByteArray(ByVal int As Int32) As Byte()
' a necessary wrapper because of the cast to Int32
Return BitConverter.GetBytes(int)
End Function
Private Shared Function doubleToByteArray(ByVal dbl As Double) As Byte()
Return BitConverter.GetBytes(Convert.ToDecimal(dbl))
End Function
Private Shared Function doubleCoordinateToRationalByteArray(ByVal doubleVal As Double) As Byte()
Dim temp As Double
temp = Math.Abs(doubleVal)
Dim degrees = Math.Truncate(temp)
temp = (temp - degrees) * 60
Dim minutes = Math.Truncate(temp)
temp = (temp - minutes) * 60
Dim seconds = temp
Dim result(24) As Byte
Array.Copy(intToByteArray(degrees), 0, result, 0, 4)
Array.Copy(intToByteArray(1), 0, result, 4, 4)
Array.Copy(intToByteArray(minutes), 0, result, 8, 4)
Array.Copy(intToByteArray(1), 0, result, 12, 4)
Array.Copy(doubleToByteArray(seconds), 0, result, 16, 4)
Array.Copy(intToByteArray(1), 0, result, 20, 4)
Return result
End Function
根据this规范,经纬度编码为
Specifies that the value data member is an array of pairs of unsigned long integers. Each pair represents a fraction; the first integer is the numerator and the second integer is the denominator.
编码布局应为(共 24 个字节)
Byte Offset Length Encoding Field
0 4 uint Degrees Nominator
4 4 uint Degrees Denominator
8 4 uint Minutes Nominator
12 4 uint Minutes Denominator
16 4 uint Seconds Nominator
20 4 uint Seconds Denominator
鉴于您的输入使用整数度和分而不是分数,您对这两者的编码将正常工作,使用值 1 作为分母。
对于作为浮点值的秒数,情况并非如此。您必须使用分母和分母部分将其编码为有理数。
我不确定您想要的精度是多少,但是考虑到您 34.46
秒的示例,似乎乘以 1000 并使用 1000 作为分母会更好够了:
Dim secondsNominator = Math.Truncate(1000 * seconds)
Dim secondsDenoninator = 1000
那么你的编码函数就变成了:
Private Shared Function doubleCoordinateToRationalByteArray(ByVal doubleVal As Double) As Byte()
Dim temp As Double
temp = Math.Abs(doubleVal)
Dim degrees = Math.Truncate(temp)
temp = (temp - degrees) * 60
Dim minutes = Math.Truncate(temp)
temp = (temp - minutes) * 60
Dim secondsNominator = Math.Truncate(1000 * temp)
Dim secondsDenoninator = 1000
Dim result(24) As Byte
' Degrees (nominator, and 1 for denominator)
Array.Copy(intToByteArray(degrees), 0, result, 0, 4)
Array.Copy(intToByteArray(1), 0, result, 4, 4)
' Minutes (nominator, and 1 for denominator)
Array.Copy(intToByteArray(minutes), 0, result, 8, 4)
Array.Copy(intToByteArray(1), 0, result, 12, 4)
' Seconds (1000 for denominator: ms resolution)
Array.Copy(intToByteArray(secondsNominator), 0, result, 16, 4)
Array.Copy(intToByteArray(secondsDenominator), 0, result, 20, 4)
Return result
End Function
exif数据的GPS经纬度为"rational"数据类型,即两个32位整数。例如,要表示 34.46,您可以使用两个 32 位整数 3,446(分子)和 100(分母),或 344,600 和 10,000。对于度数的整数值,例如,您可以使用分母为 1 的 8。
您可以获得exif规范here。
我正在尝试将纬度 = 8°50'34.46" 和经度 = 125° 9'50.82" 放入图像的 exif 文件中。我正在使用 vb.net.
我在将度数和分钟转换为字节时没有问题,因为它是一个整数,但是当我将具有十进制值的秒 (34.46") 转换为字节时。它给出不同的结果,如 0.9856。
请大家帮助我如何将十进制数字转换为字节。
这里是代码:
Private Shared Function intToByteArray(ByVal int As Int32) As Byte()
' a necessary wrapper because of the cast to Int32
Return BitConverter.GetBytes(int)
End Function
Private Shared Function doubleToByteArray(ByVal dbl As Double) As Byte()
Return BitConverter.GetBytes(Convert.ToDecimal(dbl))
End Function
Private Shared Function doubleCoordinateToRationalByteArray(ByVal doubleVal As Double) As Byte()
Dim temp As Double
temp = Math.Abs(doubleVal)
Dim degrees = Math.Truncate(temp)
temp = (temp - degrees) * 60
Dim minutes = Math.Truncate(temp)
temp = (temp - minutes) * 60
Dim seconds = temp
Dim result(24) As Byte
Array.Copy(intToByteArray(degrees), 0, result, 0, 4)
Array.Copy(intToByteArray(1), 0, result, 4, 4)
Array.Copy(intToByteArray(minutes), 0, result, 8, 4)
Array.Copy(intToByteArray(1), 0, result, 12, 4)
Array.Copy(doubleToByteArray(seconds), 0, result, 16, 4)
Array.Copy(intToByteArray(1), 0, result, 20, 4)
Return result
End Function
根据this规范,经纬度编码为
Specifies that the value data member is an array of pairs of unsigned long integers. Each pair represents a fraction; the first integer is the numerator and the second integer is the denominator.
编码布局应为(共 24 个字节)
Byte Offset Length Encoding Field
0 4 uint Degrees Nominator
4 4 uint Degrees Denominator
8 4 uint Minutes Nominator
12 4 uint Minutes Denominator
16 4 uint Seconds Nominator
20 4 uint Seconds Denominator
鉴于您的输入使用整数度和分而不是分数,您对这两者的编码将正常工作,使用值 1 作为分母。
对于作为浮点值的秒数,情况并非如此。您必须使用分母和分母部分将其编码为有理数。
我不确定您想要的精度是多少,但是考虑到您 34.46
秒的示例,似乎乘以 1000 并使用 1000 作为分母会更好够了:
Dim secondsNominator = Math.Truncate(1000 * seconds)
Dim secondsDenoninator = 1000
那么你的编码函数就变成了:
Private Shared Function doubleCoordinateToRationalByteArray(ByVal doubleVal As Double) As Byte()
Dim temp As Double
temp = Math.Abs(doubleVal)
Dim degrees = Math.Truncate(temp)
temp = (temp - degrees) * 60
Dim minutes = Math.Truncate(temp)
temp = (temp - minutes) * 60
Dim secondsNominator = Math.Truncate(1000 * temp)
Dim secondsDenoninator = 1000
Dim result(24) As Byte
' Degrees (nominator, and 1 for denominator)
Array.Copy(intToByteArray(degrees), 0, result, 0, 4)
Array.Copy(intToByteArray(1), 0, result, 4, 4)
' Minutes (nominator, and 1 for denominator)
Array.Copy(intToByteArray(minutes), 0, result, 8, 4)
Array.Copy(intToByteArray(1), 0, result, 12, 4)
' Seconds (1000 for denominator: ms resolution)
Array.Copy(intToByteArray(secondsNominator), 0, result, 16, 4)
Array.Copy(intToByteArray(secondsDenominator), 0, result, 20, 4)
Return result
End Function
exif数据的GPS经纬度为"rational"数据类型,即两个32位整数。例如,要表示 34.46,您可以使用两个 32 位整数 3,446(分子)和 100(分母),或 344,600 和 10,000。对于度数的整数值,例如,您可以使用分母为 1 的 8。
您可以获得exif规范here。