martedì 28 giugno 2016

.Net rilevare da un file immagine dati gps e indirizzo in C# e VB.Net

Si riporta l'articolo scritto per il sito http://www.iprogrammatori.it/articoli/programmazione/art_net-rilevare-da-un-file-immagine-dati-gp_1441.aspx

Con le nuove tecnologie in cui sono presenti funzionalità come la geo localizzazione che permette di rilevare la posizione in cui ci si trova, è possibile sapere in quale posto è stata scattata  una foto tanto per fare unesempio.
In questo articolo, vedremo come realizzare un semplice programma, che data una foto scattata con uno SmartPhone, possiamo rilevare l’indirizzo del luogo in cui è avvenuto tale avvenimento ed informazioni sul dispositivo.
Tramite la tecnologia .Net rileveremo queste informazioni su un file Immagine, e tramite le API di google maps avremmo informazioni sulle coordinate riguardante il GPS.
Creazione del progetto per ottenere le coordinate GPS
Si crea un nuovo progetto di tipo Windows Application, selezionando il linguaggio di programmazione di proprio interesse.
Una volta aperto il progetto, inseriamo nella form 7 caselle di testo, sette controlli label, un controllo di tipo WebBrowser che avrà il compito di visualizzare la cartina ed un pulsante, il tutto come mostrato in figura 1.


Figura 1 – il programma in esecuzione

Una volta posizionati i controlli non ci resta che scrivere il codice.
Per eseguire il codice, dovremmo avere un file di tipo “jpg” nel quale sono presenti le proprietà “GPS” nel nostro caso, tramite lo smartphone Nokia Lumia 520 è stata effettuata la prova.

Stesura del codice
Passiamo in visualizzazione codice in modo che scriviamo il codice per estrapolare le informazioni dal file.
Inseriamo in alto, sopra ad ogni riga di codice, lo spazio dei nomi che ci permette di utilizzare determinate classi.
Qui di seguito si riporta i frammenti di codice per entrambi i linguaggi.


VB.Net

Imports System.Drawing.Imaging

Imports System.Net

Imports System.Text

Imports System.IO

 

C#

using System.Drawing.Imaging;

using System.Net;

using System.IO;

Gli spazi di nomi ci permettono di gestire i file, richiamare il sito web di Google e la gestione delle immagini.
Si crea una funzione, la quale date le informazioni presenti nel file jpeg, ed in particolare le proprietà relative alle coordinate GPS, quali latitudine e longitudine, rileviamo il dato di tipo float che tramite le api di Google otteniamo l’indirizzo.
Qui di seguito si riporta la funzione che ci permette di ottenere la latitudine e longitudine.



VB.Net

Private Function GpsToFloat(propItemRef As PropertyItem, propItem As PropertyItem) As Single

        Dim gradiNumeratore As UInteger = BitConverter.ToUInt32(propItem.Value, 0)

        Dim gradiDenominatore As UInteger = BitConverter.ToUInt32(propItem.Value, 4)

        Dim gradi As Single = gradiNumeratore / CSng(gradiDenominatore)

 

        Dim minutiNumeratore As UInteger = BitConverter.ToUInt32(propItem.Value, 8)

        Dim minutiDenominatore As UInteger = BitConverter.ToUInt32(propItem.Value, 12)

        Dim minuti As Single = minutiNumeratore / CSng(minutiDenominatore)

 

        Dim secondiNumeratore As UInteger = BitConverter.ToUInt32(propItem.Value, 16)

        Dim secondiDenominatore As UInteger = BitConverter.ToUInt32(propItem.Value, 20)

        Dim secondi As Single = secondiNumeratore / CSng(secondiDenominatore)

 

        Dim coordinate As Single = gradi + (minuti / 60.0F) + (secondi / 3600.0F)

        Dim gpsRef As String = System.Text.Encoding.ASCII.GetString(New Byte(0) {propItemRef.Value(0)})

        'N, S, E, W

        If gpsRef = "S" OrElse gpsRef = "W" Then

            coordinate = 0 - coordinate

        End If

        Return coordinate

    End Function

 

C#

private   float GpsToFloat(PropertyItem propItemRef, PropertyItem propItem)

        {

            uint gradiNumeratore = BitConverter.ToUInt32(propItem.Value, 0);

            uint gradiDenominatore = BitConverter.ToUInt32(propItem.Value, 4);

            float gradi = gradiNumeratore / (float)gradiDenominatore;

 

            uint minutiNumeratore = BitConverter.ToUInt32(propItem.Value, 8);

            uint minutiDenominatore = BitConverter.ToUInt32(propItem.Value, 12);

            float minuti = minutiNumeratore / (float)minutiDenominatore;

 

            uint secondiNumeratori = BitConverter.ToUInt32(propItem.Value, 16);

            uint secondiDenominatori = BitConverter.ToUInt32(propItem.Value, 20);

            float secondi = secondiNumeratori / (float) secondiDenominatori;

 

            float coordinate = gradi + (minuti / 60f) + (secondi / 3600f);

            string gpsRef = System.Text.Encoding.ASCII.GetString(new byte[1] { propItemRef.Value[0] }); //N, S, E, W

            if (gpsRef == "S" || gpsRef == "W")

                coordinate = 0 - coordinate;

            return coordinate;

        }


Nell’evento click, inseriamo il codice che permette di rilevare le informazioni dal file, ed in particolare ottenere la proprietà GPS, la proprietà del dispositivo con il quale abbiamo scattato la foto, la proprietà del sistema operativo del dispositivo ed infine data ed ora della foto.
Queste informazioni le otteniamo tramite il metodo “GEtPropertyItem” che tramite l’id otteniamo queste informazioni dall’oggetto di tipo Image che sarà il file jpeg posizionato nel nostro computer.
Mentre le classi di tipo webrequest e webresponse, otteniamo informazioni dalle api di Google sulle coordinate, e la mappa.
Qui di seguito si riporta il codice completo dell’evento click del pulsante per entrambi i linguaggi.


VB.Net

Private Sub btnRileva_Click(sender As System.Object, e As System.EventArgs) Handles btnRileva.Click

        Dim image As Image = New Bitmap("E:\TestGPS.jpg")

 

        'Latitudine

        Dim propItemRef As PropertyItem = image.GetPropertyItem(1)

        Dim propItemLat As PropertyItem = image.GetPropertyItem(2)

        Dim datiLatitudine As System.Nullable(Of Single) = GpsToFloat(propItemRef, propItemLat)

        TxtLatitudine.Text = datiLatitudine.ToString()

        'logitudine

 

        propItemRef = image.GetPropertyItem(3)

        Dim propItemLong As PropertyItem = image.GetPropertyItem(4)

        Dim datiLogitudine As System.Nullable(Of Single) = GpsToFloat(propItemRef, propItemLong)

 

        txtLogitudine.Text = datiLogitudine.ToString()

 

        'Rilevo da google le informazioni

 

        Dim url As String = "http://maps.google.com/maps/api/geocode/xml?latlng={0},{1}&sensor=false"

        url = String.Format(url, TxtLatitudine.Text.Trim().Replace(",", "."), txtLogitudine.Text.Trim().Replace(",", "."))

        Dim request As WebRequest = WebRequest.Create(url)

        Using response As WebResponse = DirectCast(request.GetResponse(), HttpWebResponse)

            Using reader As New StreamReader(response.GetResponseStream(), Encoding.UTF8)

                Dim dsResult As New DataSet()

                dsResult.ReadXml(reader)

                txtIndirizzo.Text = dsResult.Tables("result").Rows(0)("formatted_address").ToString()

            End Using

        End Using

        Dim ascii As Encoding = Encoding.ASCII

        TxtNomeDispositovo.Text = ascii.GetString(image.GetPropertyItem(272).Value, 0, image.GetPropertyItem(272).Len - 1)

        TxtSistema.Text = ascii.GetString(image.GetPropertyItem(305).Value, 0, image.GetPropertyItem(305).Len - 1)

        Dim DataFoto As String = ascii.GetString(image.GetPropertyItem(36867).Value, 0, image.GetPropertyItem(36867).Len - 1)

        Dim Data As String() = DataFoto.Split(" "c)

 

        Dim DataDellaFoto As String = DateTime.Parse(Data(0).Replace(":", "/")).ToString("dd/MM/yyyy") + " " + Data(1)

 

 

 

        webBrowser1.Navigate("http://maps.googleapis.com/maps/api/staticmap?center=" + TxtLatitudine.Text.Trim().Replace(",", ".") + "," + txtLogitudine.Text.Trim().Replace(",", ".") + "&zoom=15&size=200x200")

 

        TxtTelecamera.Text = ascii.GetString(image.GetPropertyItem(271).Value, 0, image.GetPropertyItem(271).Len - 1)

        TxtDataFoto.Text = DataDellaFoto

    End Sub

 

C#

private void btnRileva_Click(object sender, EventArgs e)

        {

 

            Image image = new Bitmap(@"E:\TestGPS2.jpg");

 

            //Latitudine

            PropertyItem propItemRef = image.GetPropertyItem(1);

            PropertyItem propItemLat = image.GetPropertyItem(2);

            float? datiLatitudine = GpsToFloat(propItemRef, propItemLat);

            TxtLatitudine.Text = datiLatitudine.ToString();

            //logitudine

 

            propItemRef = image.GetPropertyItem(3);

            PropertyItem propItemLong = image.GetPropertyItem(4);

            float? datiLogitudine = GpsToFloat(propItemRef, propItemLong);

 

            txtLogitudine.Text = datiLogitudine.ToString();

 

            //Rilevo da google le informazioni

 

            string url = "http://maps.google.com/maps/api/geocode/xml?latlng={0},{1}&sensor=false";

            url = string.Format(url, TxtLatitudine.Text.Trim().Replace(",", "."), txtLogitudine.Text.Trim().Replace(",", "."));

            WebRequest request = WebRequest.Create(url);

            using (WebResponse response = (HttpWebResponse)request.GetResponse())

            {

                using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))

                {

                    DataSet dsResult = new DataSet();

                    dsResult.ReadXml(reader);

                     txtIndirizzo.Text = dsResult.Tables["result"].Rows[0]["formatted_address"].ToString();

                }

            }

             Encoding ascii = Encoding.ASCII;

             TxtNomeDispositovo.Text =  ascii.GetString(image.GetPropertyItem(272).Value, 0, image.GetPropertyItem(272).Len - 1);

             TxtSistema.Text = ascii.GetString(image.GetPropertyItem(305).Value, 0, image.GetPropertyItem(305).Len - 1);

             string DataFoto = ascii.GetString(image.GetPropertyItem(36867).Value, 0, image.GetPropertyItem(36867).Len - 1);

            string[]Data = DataFoto.Split(' ');

 

            string DataDellaFoto = DateTime.Parse(Data[0].Replace(":", "/")).ToString("dd/MM/yyyy") + " " + Data[1];

 

            

 

             webBrowser1.Navigate("http://maps.googleapis.com/maps/api/staticmap?center=" + TxtLatitudine.Text.Trim().Replace(",", ".") + "," + txtLogitudine.Text.Trim().Replace(",", ".") + "&zoom=15&size=200x200");

 

             TxtTelecamera.Text = ascii.GetString(image.GetPropertyItem(271).Value, 0, image.GetPropertyItem(271).Len - 1);

             TxtDataFoto.Text = DataDellaFoto;

 

        }




Ora non ci resta che eseguire il programma per rilevare i dati dalla nostra immagine.

Conclusioni
In questo articolo abbiamo visto come realizzare un semplice programma, che può tornare utile soprattutto in ambito di investigazione, per rilevare informazioni su una determinata immagine. Con poche righe di codice, possiamo rilevare  dati dai file carpendo molte cose sulle persone ed in particolare gli spostamenti o luoghi che hanno visitato, un articolo che introduce il lettore alla realizzazione di un programma più complesso per rilevamento dei dati importanti.

Nessun commento: