Differenze tra le versioni di "Estrarre le coordinate geografiche dai TAG GPS eventualmente presenti in un file immagine JPEG"

Da Gambas-it.org - Wikipedia.
(Creata pagina con "I file immagine di formato JPEG (.jpg) possono contenere TAG che rappresentano varie informazioni relative all'immagine. <BR>Essi possono contenere anche informazioni GPS ed i...")
 
 
(7 versioni intermedie di uno stesso utente non sono mostrate)
Riga 13: Riga 13:
 
Dopo ciò, si individueranno e interpreteranno i dati afferenti ai valori delle Coordinate geografiche, dei quali sarà presente prima quello della Latitudine seguito da quello della Longitudine.
 
Dopo ciò, si individueranno e interpreteranno i dati afferenti ai valori delle Coordinate geografiche, dei quali sarà presente prima quello della Latitudine seguito da quello della Longitudine.
 
<BR>Al 12° byte dopo il valore del carattere ASCII "N" è presente il valore di 4 byte che rappresenta il numero d'indice (''offset'') all'interno del file ove inizia il blocco relativo ai dati della Latitudine e della Longitudine. A tale valore vanno sommate 12 unità. Tale somma indica il numero d'indice ove incominciano precisamente i valori della Latitudine.
 
<BR>Al 12° byte dopo il valore del carattere ASCII "N" è presente il valore di 4 byte che rappresenta il numero d'indice (''offset'') all'interno del file ove inizia il blocco relativo ai dati della Latitudine e della Longitudine. A tale valore vanno sommate 12 unità. Tale somma indica il numero d'indice ove incominciano precisamente i valori della Latitudine.
<BR>In particolare i valori delle due coordinate geografiche sono espressi nel formato Gradi-Minuti-Secondi (DMS). Ogni singolo valore di detto formato è un numero in virgola mobile espresso nel tipo di dato "rational64u", che è sostanzialmente formato da due interi di 4 byte ciascuno: un numeratore e un denominatore.
+
<BR>In particolare i valori delle due coordinate geografiche sono espressi nel formato Gradi-Minuti-Secondi (DMS). Ogni singolo valore di detto formato è un numero in virgola mobile, espresso nel tipo di dato "rational64u", che è sostanzialmente formato da due interi di 4 byte ciascuno: un numeratore e un denominatore.
<BR>Il primo intero di 4 byte (numeratore) è quello che si riferisce dunque al valore dei Gradi della Latitudine, e si incontra dopo 68 byte dal TAG, sopra descritto, corrispondente al carattere ASCII "E" della Longitudine Est.
+
<BR>Il primo intero di 4 byte (numeratore) è quello che si riferisce dunque al valore dei Gradi della Latitudine.
 
<BR>Per ottenere il numero effettivo di ogni valore delle due coordinate geografiche, si dividerà il numeratore per il denominatore.
 
<BR>Per ottenere il numero effettivo di ogni valore delle due coordinate geografiche, si dividerà il numeratore per il denominatore.
 
<BR>Così in astratto:
 
<BR>Così in astratto:
 
  Gradi = numeratore / denominatore
 
  Gradi = numeratore / denominatore
Immediatamente dopo l'ultimo valore/denominatore dei secondi della Longitudine sono presenti i valori dell'Altitudine (TAG: GPSAltitude), anch'essi espressi nel tipo "rational64u".
+
Immediatamente dopo l'ultimo valore/denominatore dei secondi della Latitudine iniziano i valori sono presenti i valori della Longitudine, anch'essi espressi nel tipo "rational64u".
  
 
Più in particolare la sequenza dei valori è la seguente:
 
Più in particolare la sequenza dei valori è la seguente:
"N" (1 byte)
+
<BR>- individuazione del valore di un solo byte &h4E relativo al carattere ASCII "N" e alla direzione "Nord" della Latitudine;
<BR>salto di 12 byte e legge 4 byte per individuare l'offset ove leggere le coordinate geografiche
+
<BR>- salto di 24 byte per verificare se è presente il valore di un solo byte &h45 relativo al carattere ASCII "E" e alla direzione "Est" della Longitudine;
<BR>salto ancora di 9 byte, per verificare se il byte si riferisce alla direzione della ongitudine
+
<BR>- in caso affermativo, salto di 12 byte, a cominciare dal byte successivo a quello della lettera "N", per leggere 4 byte e individuare l'offset ove leggere le coordinate geografiche;
<BR>"E" (1 byte)
+
<BR>- salto quindi al byte di numero d'indice sopra individuato per conoscere i dati relativi alle due coordinate geografiche;
<BR>salto al byte di numero d'indice sopra individuato per conoscere i dati relativi alle due coordinate geografiche
+
<BR>- LAT. Gradi (4 byte: Numeratore);
<BR>LAT. Gradi (4 byte: Numeratore)
+
<BR>- LAT. Gradi (4 byte: Denominatore);
<BR>LAT. Gradi (4 byte: Denominatore)
+
<BR>- LAT. Minuti (4 byte: Numeratore);
<BR>LAT. Minuti (4 byte: Numeratore)
+
<BR>- LAT. Minuti (4 byte: Denominatore);
<BR>LAT. Minuti (4 byte: Denominatore)
+
<BR>- LAT. Secondi (4 byte: Numeratore);
<BR>LAT. Secondi (4 byte: Numeratore)
+
<BR>- LAT. Secondi (4 byte: Denominatore);
<BR>LAT. Secondi (4 byte: Denominatore)
+
<BR>- LONG. Gradi (4 byte: Numeratore);
<BR>LONG. Gradi (4 byte: Numeratore)
+
<BR>- LONG. Gradi (4 byte: Denominatore);
<BR>LONG. Gradi (4 byte: Denominatore)
+
<BR>- LONG. Minuti (4 byte: Numeratore);
<BR>LONG. Minuti (4 byte: Numeratore)
+
<BR>- LONG. Minuti (4 byte: Denominatore);
<BR>LONG. Minuti (4 byte: Denominatore)
+
<BR>- LONG. Secondi (4 byte: Numeratore);
<BR>LONG. Secondi (4 byte: Numeratore)
+
<BR>- LONG. Secondi (4 byte: Denominatore).
<BR>LONG. Secondi (4 byte: Denominatore)
 
  
 
Mostriamo di seguito un semplice codice per leggere i dati sopra descritti:
 
Mostriamo di seguito un semplice codice per leggere i dati sopra descritti:
  '''Public''' Sub Main()
+
  Public Sub Main()
 
    
 
    
 
   Dim filejpg, jpg As String
 
   Dim filejpg, jpg As String
Riga 47: Riga 46:
 
   Dim fl As File
 
   Dim fl As File
 
   
 
   
   filejpg = "<FONT Coor=gray>''/percorso/del/file.jpg''</font>"
+
   filejpg = "<FONT Color=darkgreen>''/percorso/del/file.jpg''</font>"
 
   jpg = File.Load(filejpg)
 
   jpg = File.Load(filejpg)
 
    
 
    
  <FONT Coor=gray>' ''Verifica la presenza del valore &4E (caratterre ASCII "N") e del valore &45 (caratterre ASCII "E"):''</font>
+
  <FONT Color=gray>' ''Verifica la presenza del valore &4E (caratterre ASCII "N") e del valore &45 (caratterre ASCII "E"):''</font>
 
   Repeat  
 
   Repeat  
 
     n = InStr(jpg, MkShort(&4e), e)  ' oppure: Chr(&4E) & Chr(&00) & Chr(&00) & Chr(&00), e)
 
     n = InStr(jpg, MkShort(&4e), e)  ' oppure: Chr(&4E) & Chr(&00) & Chr(&00) & Chr(&00), e)
Riga 60: Riga 59:
 
   fl = Open filejpg For Read  
 
   fl = Open filejpg For Read  
 
   
 
   
  <FONT Coor=gray>' ''Il numero d'indice (''offset'') del byte iniziale del primo Intero afferente ai dati della Latitudine èindicato dal valore di tipo Integer posto 12 byte più avanti rispetto al già visto valore &4E:''<font>
+
  <FONT Color=gray>' ''Il numero d'indice (''offset'') del byte iniziale del primo Intero afferente ai dati della Latitudine è indicato dal valore di tipo Integer posto 12 byte più avanti rispetto al già visto valore &4E. Tale valore dell'offset deve essere aumentato di 12 unità.''</font>
 
   Seek #fl, (n - 1) + 12
 
   Seek #fl, (n - 1) + 12
 
   Read #fl, i
 
   Read #fl, i
 
   
 
   
  <FONT Coor=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Gradi" della Latitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Gradi" della Latitudine:''</font>
 
   Seek #fl, i + 12
 
   Seek #fl, i + 12
 
   Read #fl, n
 
   Read #fl, n
  <FONT Coor=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Gradi" della Latitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Gradi" della Latitudine:''</font>
 
   Read #fl, e
 
   Read #fl, e
 
   g = CSingle(n / e)
 
   g = CSingle(n / e)
  <FONT Coor=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Minuti" della Latitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Minuti" della Latitudine:''</font>
 
   Read #fl, n
 
   Read #fl, n
  <FONT Coor=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Minuti" della Latitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Minuti" della Latitudine:''</font>
 
   Read #fl, e
 
   Read #fl, e
 
   m = CSingle(n / e)
 
   m = CSingle(n / e)
  <FONT Coor=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Secondi" della Latitudine:''<font>
+
  <FONT Coor=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Secondi" della Latitudine:''</font>
 
   Read #fl, n
 
   Read #fl, n
  <FONT Coor=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Secondi" della Latitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Secondi" della Latitudine:''</font>
 
   Read #fl, e
 
   Read #fl, e
 
   s = CSingle(n / e)
 
   s = CSingle(n / e)
   Print "Latitudine:  "; g; "°"; m; "'"; s; "\"", g + m / 60 + s / 3600 '' = Gradi + Minuti/60 + Secondi/3600
+
   Print "Latitudine:  "; g; "°"; m; "'"; s; "\"", g + m / 60 + s / 3600 <Font color=gray>' ''(gradi decimali = Gradi + Minuti/60 + Secondi/3600)''</font>
 
   
 
   
  <FONT Coor=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Gradi" della Longitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Gradi" della Longitudine:''</font>
 
   Read #fl, n
 
   Read #fl, n
  <FONT Coor=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Gradi" della Longitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Gradi" della Longitudine:''</font>
 
   Read #fl, e
 
   Read #fl, e
 
   g = CSingle(n / e)
 
   g = CSingle(n / e)
  <FONT Coor=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Minuti" della Longitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Minuti" della Longitudine:''</font>
 
   Read #fl, n
 
   Read #fl, n
  <FONT Coor=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Minuti" della Longitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Minuti" della Longitudine:''</font>
 
   Read #fl, e
 
   Read #fl, e
 
   m = CSingle(n / e)
 
   m = CSingle(n / e)
  <FONT Coor=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Secondi" della Longitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 1° valore del formato "rational64u" relativo ai "Secondi" della Longitudine:''</font>
 
   Read #fl, n
 
   Read #fl, n
  <FONT Coor=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Secondi" della Longitudine:''<font>
+
  <FONT Color=gray>' ''Legge il 2° valore del formato "rational64u" relativo ai "Secondi" della Longitudine:''</font>
 
   Read #fl, e
 
   Read #fl, e
 
   s = CSingle(n / e)
 
   s = CSingle(n / e)
   Print "Longitudine: "; g; "°"; m; "'"; s; "\"", g + m / 60 + s / 3600 '' = Gradi + Minuti/60 + Secondi/3600
+
   Print "Longitudine: "; g; "°"; m; "'"; s; "\"", g + m / 60 + s / 3600 <Font color=gray>' ''(gradi decimali = Gradi + Minuti/60 + Secondi/3600)''</font>
 
   
 
   
 
   fl.Close
 
   fl.Close
 
   
 
   
  '''End'''
+
  End
  
  

Versione attuale delle 05:08, 18 gen 2024

I file immagine di formato JPEG (.jpg) possono contenere TAG che rappresentano varie informazioni relative all'immagine.
Essi possono contenere anche informazioni GPS ed in particolare i dati relativi alle coordinate geografiche (Latitudine e Longitudine), nonché all'Altitudine del punto ove si trovava colui che ha scattato la foto.

Qui dunque prenderemo in considerazione i seguenti TAG GPS:
- GPSLatitudeRef
- GPSLatitude
- GPSLongitudeRef
- GPSLongitude

Per interpretare i dati presenti nel file immagine JPEG relativi ai TAG GPS, sopra elencati, bisogna innanzitutto individuare i dati che si riferiscono alla direzione della Latitudine e della Longitudineove è stata scattata la foto-immagine. In particolare la direzione della Latitudine può essere "Nord" o "Sud", mentre quella della Longitudine può essere "Est" oppure "Ovest".
In particolare - per quello che a noi interessa - il TAG relativo alla Latitudine Nord è indicato nel file con il valore ASCII del carattere "N" espresso all'interno del codice con un valore a 16-bit che in esadecimale è rappresentato dal valore &h004E. L'altro valore a 16-bit, rappresentato dal valore &h0045 e corrispondente al carattere ASCII "E", si trova esattamente dopo 24 byte dopo il byte &h4E. Pertanto, per essere sicuri che effettivamente si tratta del valore riferito alla Latitudine Nord, si dovrà verificare la presenta dopo 24 byte del valore &h45 corrispondente al carattere ASCII "E".

Dopo ciò, si individueranno e interpreteranno i dati afferenti ai valori delle Coordinate geografiche, dei quali sarà presente prima quello della Latitudine seguito da quello della Longitudine.
Al 12° byte dopo il valore del carattere ASCII "N" è presente il valore di 4 byte che rappresenta il numero d'indice (offset) all'interno del file ove inizia il blocco relativo ai dati della Latitudine e della Longitudine. A tale valore vanno sommate 12 unità. Tale somma indica il numero d'indice ove incominciano precisamente i valori della Latitudine.
In particolare i valori delle due coordinate geografiche sono espressi nel formato Gradi-Minuti-Secondi (DMS). Ogni singolo valore di detto formato è un numero in virgola mobile, espresso nel tipo di dato "rational64u", che è sostanzialmente formato da due interi di 4 byte ciascuno: un numeratore e un denominatore.
Il primo intero di 4 byte (numeratore) è quello che si riferisce dunque al valore dei Gradi della Latitudine.
Per ottenere il numero effettivo di ogni valore delle due coordinate geografiche, si dividerà il numeratore per il denominatore.
Così in astratto:

Gradi = numeratore / denominatore

Immediatamente dopo l'ultimo valore/denominatore dei secondi della Latitudine iniziano i valori sono presenti i valori della Longitudine, anch'essi espressi nel tipo "rational64u".

Più in particolare la sequenza dei valori è la seguente:
- individuazione del valore di un solo byte &h4E relativo al carattere ASCII "N" e alla direzione "Nord" della Latitudine;
- salto di 24 byte per verificare se è presente il valore di un solo byte &h45 relativo al carattere ASCII "E" e alla direzione "Est" della Longitudine;
- in caso affermativo, salto di 12 byte, a cominciare dal byte successivo a quello della lettera "N", per leggere 4 byte e individuare l'offset ove leggere le coordinate geografiche;
- salto quindi al byte di numero d'indice sopra individuato per conoscere i dati relativi alle due coordinate geografiche;
- LAT. Gradi (4 byte: Numeratore);
- LAT. Gradi (4 byte: Denominatore);
- LAT. Minuti (4 byte: Numeratore);
- LAT. Minuti (4 byte: Denominatore);
- LAT. Secondi (4 byte: Numeratore);
- LAT. Secondi (4 byte: Denominatore);
- LONG. Gradi (4 byte: Numeratore);
- LONG. Gradi (4 byte: Denominatore);
- LONG. Minuti (4 byte: Numeratore);
- LONG. Minuti (4 byte: Denominatore);
- LONG. Secondi (4 byte: Numeratore);
- LONG. Secondi (4 byte: Denominatore).

Mostriamo di seguito un semplice codice per leggere i dati sopra descritti:

Public Sub Main()
 
 Dim filejpg, jpg As String
 Dim i, n, e As Integer
 Dim g, m, s As Single
 Dim fl As File

 filejpg = "/percorso/del/file.jpg"
 jpg = File.Load(filejpg)
 
' Verifica la presenza del valore &4E (caratterre ASCII "N") e del valore &45 (caratterre ASCII "E"):
 Repeat 
   n = InStr(jpg, MkShort(&4e), e)   ' oppure: Chr(&4E) & Chr(&00) & Chr(&00) & Chr(&00), e)
   e = n + 23
 Until (jpg[e, 2] = MkShort(&45)) Or (n == 0)

 If n == 0 Then Error.Raise("Non ci sono TAG GPS !")

 fl = Open filejpg For Read 

' Il numero d'indice (offset) del byte iniziale del primo Intero afferente ai dati della Latitudine è indicato dal valore di tipo Integer posto 12 byte più avanti rispetto al già visto valore &4E. Tale valore dell'offset deve essere aumentato di 12 unità.
 Seek #fl, (n - 1) + 12
 Read #fl, i

' Legge il 1° valore del formato "rational64u" relativo ai "Gradi" della Latitudine:
 Seek #fl, i + 12
 Read #fl, n
' Legge il 2° valore del formato "rational64u" relativo ai "Gradi" della Latitudine:
 Read #fl, e
 g = CSingle(n / e)
' Legge il 1° valore del formato "rational64u" relativo ai "Minuti" della Latitudine:
 Read #fl, n
' Legge il 2° valore del formato "rational64u" relativo ai "Minuti" della Latitudine:
 Read #fl, e
 m = CSingle(n / e)
' Legge il 1° valore del formato "rational64u" relativo ai "Secondi" della Latitudine:
 Read #fl, n
' Legge il 2° valore del formato "rational64u" relativo ai "Secondi" della Latitudine:
 Read #fl, e
 s = CSingle(n / e)
 Print "Latitudine:  "; g; "°"; m; "'"; s; "\"", g + m / 60 + s / 3600 ' (gradi decimali = Gradi + Minuti/60 + Secondi/3600)

' Legge il 1° valore del formato "rational64u" relativo ai "Gradi" della Longitudine:
 Read #fl, n
' Legge il 2° valore del formato "rational64u" relativo ai "Gradi" della Longitudine:
 Read #fl, e
 g = CSingle(n / e)
' Legge il 1° valore del formato "rational64u" relativo ai "Minuti" della Longitudine:
 Read #fl, n
' Legge il 2° valore del formato "rational64u" relativo ai "Minuti" della Longitudine:
 Read #fl, e
 m = CSingle(n / e)
' Legge il 1° valore del formato "rational64u" relativo ai "Secondi" della Longitudine:
 Read #fl, n
' Legge il 2° valore del formato "rational64u" relativo ai "Secondi" della Longitudine:
 Read #fl, e
 s = CSingle(n / e)
 Print "Longitudine: "; g; "°"; m; "'"; s; "\"", g + m / 60 + s / 3600 ' (gradi decimali = Gradi + Minuti/60 + Secondi/3600)

 fl.Close

End


Riferimenti