Как преобразовать долготу и широту в байтовый массив GPS Exif


Я пытаюсь поместить широту = 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
2 2

2 ответа:

В соответствии сэтой спецификацией долгота и широта кодируются как

PropertyTagTypeRational

Указывает, что элемент данных value представляет собой массивпар беззнаковых длинныхцелых чисел . Каждая пара представляет собой дробь ; первое целое число является числителем , а второе целое-знаменателем .

Кодированный макет должен быть (всего 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

Широта и долгота GPS для данных exif - это "рациональный" тип данных, или два 32-разрядных целых числа. Например, для представления 34,46 можно использовать два 32-разрядных целых числа 3,446 (числитель) и 100 (знаменатель), или 344,600 и 10,000. Для целочисленного значения степеней, например, можно использовать 8 со знаменателем 1.

Вы можете получить спецификацию exif здесь.