Contents ...
udn網路城邦
EXIF的GPS資料格式很搞怪!但是我搞定了!
2022/10/26 11:12
瀏覽1,980
迴響0
推薦7
引用0

用數位相機或手機拍的影像都會有個EXIF資訊,裡面會有很多資訊,上面是我寫的一個小程式可以抓出這些資訊,但是對我有用的就是上面幾個而已,所以只抓他們出來。我之前做過很多聲納二進位檔案的資料處理,所以寫這個程式不難!

PhotoShop等軟體也有類似的讀取這些資訊的功能,但是多數軟體工程師都會希望自己寫這些程式,可以融入到自己的軟體中。大多數的資料項目要讀取都不難,但是顯然GPS的資料讀取讓網路上的工程師們頭痛不已怎麼讀都不對?下面就是某張影像在PhotoShop裡面顯示的經緯度,是我們參考的標準答案。

然後我們去讀取同檔案中相對以上資訊的Byte陣列如下:

我們很快可以看到相對應的的數字,但是的部分卻考倒了幾乎所有工程師,我一開始當然也想偷懶,直接找到現成的原始碼,但是這一部份只看到一大堆討論,卻沒有看到結論?也許有吧?但是我不耐煩繼續Google爬文了,把它當作謎題自己來解!

簡單說就是要如何翻譯後段的164 156等等數字成為30.2245.61啦!我試過把他們當作SingleDouble資料型態去讀,結果都是沒意義的天文數字!直接讀Byte值則根本不是數字,不像前面的度與分。怎麼辦?其實可以嘗試的狀況也不多,我就試著將164 156 4 0當作一個Byte的整數讀取,答案是302244Bingo!原來他們是將秒也用整數儲存的!

簡單說,如果是30.2244就以整數302244儲存!讀出之後除以10000就是正確的秒數了!但是如果文件沒說清楚誰知道呢?真的很搞怪整人了!同理可證,183 245 6 0讀成四Byte整數就是456119,正確秒數是:45.6119。答案與PhotoShop軟體顯示的完全一樣還多兩位數。但是我的程式會自動把它們變成幾點幾度,方便用Google Maps查詢。

我可以破解這個數位資料的特殊寫法,功力來自我以前玩過很多特殊格式的二進位聲納資料,總算在此有用到了!就此分享給有此需要的軟體工程師們!   

    Structure PicInfo

        Dim Camera As String

        Dim Time As Date

        Dim Lat As String

        Dim Lon As String

        Dim Orientation As Int16

        Dim width As Int16, height As Int16

    End Structure

Private Function getPicInfo(ByVal picFullPath As String) As PicInfo

        Dim bmp As New Bitmap(picFullPath)

        Dim p As New PicInfo

        Dim B(47) As Byte

        For Each pro As Imaging.PropertyItem In bmp.PropertyItems

            Select Case pro.Id

                Case 2 

                    Array.Copy(pro.Value, 0, B, 0, 24)

                Case 4 

                   Array.Copy(pro.Value, 0, B, 24, 24)

                Case 256 

                    Dim q() As Byte = pro.Value

                    p.width = BitConverter.ToInt16(q, 0)

                Case 257 

                    Dim q() As Byte = pro.Value

                    p.height = BitConverter.ToInt16(q, 0)

                Case 271 

                    p.Camera = System.Text.Encoding.ASCII.GetString(pro.Value).Replace(Chr(0), "")

                Case 36867 

                    Dim s As String = System.Text.Encoding.ASCII.GetString(pro.Value).Replace(Chr(0), "")

                    Dim C() As String = s.Split(" ")

                    Dim D() As String = C(0).Split(":")

                    Dim K() As String = C(1).Split(":")

                    p.Time = New Date(Val(D(0)), Val(D(1)), Val(D(2)), Val(K(0)), Val(K(1)), Val(K(2)))

            End Select

        Next

            Dim G(11) As Integer

            For i As Integer = 0 To 11

                G(i) = BitConverter.ToInt32(q,  i * 4)

            Next

            Dim Lat As Double = G(0) + G(2) / 60.0 + G(4) / 10000 / 3600

            Dim Lon As Double = G(6) + G(8) / 60.0 + G(10) / 10000 / 3600

            p.Lat = Format(Lat, "00.00000")

            p.Lon = Format(Lon, "000.00000")

        Return p

    End Function

有誰推薦more
全站分類:心情隨筆 工作職場
自訂分類:不分類

限會員,要發表迴響,請先登入