Преобразование координат широты / долготы GPS в байтовый массив EXIF Rational
У меня проблемы с преобразованием GPS-координат в байтовый массив, который может быть сохранен как информация EXIF.
Этот вопрос гласит, что координаты EXIF должны быть выражены в виде трех рациональных чисел: degrees/1, minutes/1, seconds/1
, У меня нет проблем с преобразованием десятичной координаты в это. Например 42.1234567
легко конвертируется в 42/1, 7/1, 24/1
,
Моя проблема в том, что я не понимаю, как представить это как байтовый массив, когда я записываю его в информацию EXIF изображения. Библиотека, которую я использую, называется ExifWorks, и я использую ее в VB.NET.
ExifWorks setProperty
Метод принимает три вещи: идентификатор поля EXIF, массив байтов в качестве данных и тип данных. Вот как я это использую:
ew.SetProperty(TagNames.GpsLatitude, byteArrayHere, ExifWorks.ExifDataTypes.UnsignedRational)
Я также попробовал:
ew.SetPropertyString(TagNames.GpsLatitude, "42/1, 7/1, 24/1")
Что тоже не работает.
Итак, мой вопрос, как мне преобразовать мои координаты градус-минуты-секунды в байтовый массив? Все, что я пробовал до сих пор, оказывается неверной информацией EXIF и не работает. Общее решение хорошо... не обязательно должно работать в VB.net.
2 ответа
Я понял это. Вот решение:
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 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 = Math.Truncate(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(intToByteArray(seconds), 0, result, 16, 4)
Array.Copy(intToByteArray(1), 0, result, 20, 4)
Return result
End Function
Вы получите лучшую точность (до 0,001 угловых секунд, что составляет дюйм), делая
Dim milliseconds = Math.Truncate(temp* 1000.0)
...
Array.Copy(intToByteArray(milliseconds), 0, result, 16, 4)
Array.Copy(intToByteArray(1000), 0, result, 20, 4)