I am having problems converting GPS coordinates to a byte array that can be stored as EXIF information.
This questions states that EXIF coordinates should be expressed as three rational numbers: degrees/1, minutes/1, seconds/1
. I'm having no trouble converting a decimal coordinate to that. For example 42.1234567
is easily converted to 42/1, 7/1, 24/1
.
My problem is that I don't understand how to represent this as a byte array when I write it to the image EXIF information. The library that I'm using is called ExifWorks, and I'm using it in VB.NET.
The ExifWorks setProperty
method takes three things: the EXIF field ID, an array of bytes as data, and the data type. Here's how I use it:
ew.SetProperty(TagNames.GpsLatitude, byteArrayHere, ExifWorks.ExifDataTypes.UnsignedRational)
I've also tried:
ew.SetPropertyString(TagNames.GpsLatitude, "42/1, 7/1, 24/1")
Which also doesn't work.
So, my question is, how do I convert my degree-minute-second coordinate into a byte array? Everything I've tried thus far ends up as invalid EXIF information, and doesn't work. A general solution is fine... doesn't necessarily have to work in VB.net.
I've figured it out. Here's the solution:
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