Как преобразовать долготу и широту в байтовый массив 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

person john jagneil vincent t Licardo    schedule 21.04.2015    source источник
comment
Пожалуйста, опубликуйте код, который вы используете для преобразования, и выделите место, где, по вашему мнению, возникает проблема.   -  person Alex    schedule 21.04.2015


Ответы (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
person Alex    schedule 21.04.2015
comment
Это отличный ответ - person Keith Beard; 21.04.2015
comment
Спасибо, сэр. ваш код очень полезен. ты спасаешь мой день. - person john jagneil vincent t Licardo; 21.04.2015

Широта и долгота GPS для данных exif являются «рациональным» типом данных или двумя 32-битными целыми числами. Например, для представления 34,46 можно использовать два 32-битных целых числа 3446 (числитель) и 100 (знаменатель) или 344 600 и 10 000. Для целочисленного значения градусов, например, вы можете использовать 8 со знаменателем 1.

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

person xpda    schedule 21.04.2015