ASP.NET-细节-读取图片中的GPS

2020-05-20  本文已影响0人  柠檬正在努力

之前在网上看见了图片中含义GPS信息的说法,兴起就写写代码尝试一下发现果然可以读到,只有图片中含义GPS信息才可以读到

原理:
将图片转换为二进制数据,然后根据二进制数据获取Drawing.Image对象,再对PropertyItems中ID为前30的数据进行处理

直接上代码:

#Region "读取图片中GPS点"
    /*
    ''' <summary>
    ''' 传入图片二进制获取图片中的GPS坐标点
    ''' </summary>
    ''' <param name="path">图片路径</param>
    ''' <returns>返回坐标【纬度+经度】用"+"分割 取数组中第0和1个位置的值</returns>
    */
    Public Function fnGPS(ByVal sFileContent As Byte()) As Strin
        Dim strPro As String = "" /* 返回值 */
        Dim chrGPSLatitudeRef As Char = "N" /* 暂定纬度N(北纬)  */
        Dim chrGPSLongitudeRef As Char = "E" /* 暂定经度为E(东经)  */
        For Each objItem As Drawing.Imaging.PropertyItem In GetImageFromStream(sFileContent).PropertyItems
            /* 只取Id范围为0x0000到0x001e  */
            If objItem.Id >= Convert.ToInt32("0x0000", 16) And objItem.Id <= Convert.ToInt32("0x001e", 16) Then
                Select Case objItem.Id
                    Case Convert.ToInt32("0x0000", 16)
                        /* GPSVersion */
                        Dim sVersion As String() = BitConverter.ToString(objItem.Value).Split("-")
                        For i As Integer = 0 To sVersion.Length - 1
                            If IsNumeric(sVersion(i)) Then
                                sVersion(i) = Integer.Parse(sVersion(i))
                            End If
                        Next
                        Dim sreVersion As String = String.Join(".", sVersion)
                        strPro += "GPS版本:" + sreVersion
                    Case Convert.ToInt32("0x0001", 16)
                        /* 透过BitConverter, 将Value转成Char(N / S)     */
                        /* 经纬度,此值在后续的Longitude计算上会用到  */
                        chrGPSLatitudeRef = BitConverter.ToChar(objItem.Value, 0)
                    Case Convert.ToInt32("0x0002", 16)
                        If objItem.Value.Length = 24 Then
                            Dim d As Double = BitConverter.ToUInt32(objItem.Value, 0) * 1D / BitConverter.ToUInt32(objItem.Value, 4)
                            Dim m As Double = BitConverter.ToUInt32(objItem.Value, 8) * 1D / BitConverter.ToUInt32(objItem.Value, 12)
                            Dim s As Double = BitConverter.ToUInt32(objItem.Value, 16) * 1D / BitConverter.ToUInt32(objItem.Value, 20)
                            /* 计算纬度数值, 如果是南纬, 要乘上(-1)  */
                            Dim dblGPSLatitude As Double = (((s / 60 + m) / 60) + d) * IIf(chrGPSLatitudeRef.ToString.Equals("N"), 1, -1)
                            strPro += vbCrLf + "经纬度:" + dblGPSLatitude.ToString + ","
                        End If
                    Case Convert.ToInt32("0x0003", 16)
                        /* 透过BitConverter, 将Value转成Char(E/W)     */
                        /* 经纬度,此值在后续的Longitude计算上会用到  */
                        chrGPSLongitudeRef = BitConverter.ToChar(objItem.Value, 0)
                    Case Convert.ToInt32("0x0004", 16)
                        If objItem.Value.Length = 24 Then
                            Dim d As Double = BitConverter.ToUInt32(objItem.Value, 0) * 1D / BitConverter.ToUInt32(objItem.Value, 4)
                            Dim m As Double = BitConverter.ToUInt32(objItem.Value, 8) * 1D / BitConverter.ToUInt32(objItem.Value, 12)
                            Dim s As Double = BitConverter.ToUInt32(objItem.Value, 16) * 1D / BitConverter.ToUInt32(objItem.Value, 20)
                            /* 计算经度数值, 如果是西经, 要乘上(-1)  */
                            Dim dblGPSLatitude As Double = (((s / 60 + m) / 60) + d) * IIf(chrGPSLongitudeRef.ToString.Equals("E"), 1, -1)
                            strPro += dblGPSLatitude.ToString
                        End If
                    Case Convert.ToInt32("0x0005", 16)
                        Dim strAltitude As String = IIf(BitConverter.ToBoolean(objItem.Value, 0), "1", "0")
                        strPro += vbCrLf + "海拔参考值:" + strAltitude
                    Case Convert.ToInt32("0x0006", 16)
                        If objItem.Value.Length = 8 Then
                            Dim dblAltitude As Double = BitConverter.ToUInt32(objItem.Value, 0) * 1D / BitConverter.ToUInt32(objItem.Value, 4)
                            strPro += vbCrLf + "海拔:" + dblAltitude.ToString
                        End If
                End Select
            End If
        Next
        Return strPro
    End Function
    /*
    ''' <summary>
    ''' 根据二进制数据获取Drawing.Image对象
    ''' </summary>
    ''' <param name="ImageStream"></param>
    ''' <returns></returns>
    */
    Public Function GetImageFromStream(ByVal ImageStream As Byte()) As Drawing.Image
        Dim objImage As Drawing.Image = Nothing
        If (ImageStream Is Nothing) Then
            Return Nothing
        End If
        Dim index As Integer = 0
        If (((ImageStream(0) = &H15) AndAlso (ImageStream(1) = &H1C)) AndAlso (ImageStream.Length >= 80)) Then
            index = &H4E
            Do While (index < (ImageStream.Length - 1))
                If ((ImageStream(index) = &H42) AndAlso (ImageStream((index + 1)) = &H4D)) Then
                    Exit Do
                End If
                index += 1
            Loop
            If ((ImageStream(index) <> &H42) OrElse (ImageStream((index + 1)) <> &H4D)) Then
                index = &H87
            End If
        End If
        Try
            Dim stream As New MemoryStream(ImageStream, index, (ImageStream.Length - index))
            objImage = Drawing.Image.FromStream(stream)
        Catch obj1 As Exception
            Return Nothing
        End Try
        Return objImage
    End Function
#End Region

在主函数中的使用

Dim sFileContent As Byte() = New Byte(UpPhoto.PostedFile.ContentLength) {}
UpPhoto.PostedFile.InputStream.Read(sFileContent, 0, UpPhoto.PostedFile.ContentLength)
fnGPS(sFileContent)

其中UpPhoto是type="file"的上传控件

    '''<summary>
    '''UpPhoto 控件。
    '''</summary>
    '''<remarks>
    '''自动生成的字段。
    '''若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
    '''</remarks>
    Protected WithEvents UpPhoto As Global.System.Web.UI.HtmlControls.HtmlInputFile


<input id="UpPhoto" runat="server" name="File1" size="43" style="width: 374px; height: 22px; padding-left: 10px;" type="file/>

测试的效果图,只要图片中有GPS数据,就可以获取到拍摄的GPS和海拔


实例效果图

这里最后再推荐两个辅助验证网站
1. 图片EXIF信息获取可以验证获取的GPS信息是否正确和查看其它图片包含信息
2. 拾取坐标系统可以验证获取的GPS是哪个位置的

上一篇下一篇

猜你喜欢

热点阅读