Преобразование координат широты / долготы 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)
Другие вопросы по тегам