美文网首页
ASP.NET-细节-读取图片中的GPS

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

作者: 柠檬正在努力 | 来源:发表于2020-05-20 11:37 被阅读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是哪个位置的

    相关文章

      网友评论

          本文标题:ASP.NET-细节-读取图片中的GPS

          本文链接:https://www.haomeiwen.com/subject/wlabohtx.html