Ottenere informazioni da un file GEOTIFF con l'API di libgeotiff

Da Gambas-it.org - Wikipedia.

Il file GEOTIFF è un file di formato TIFF georeferenziato. Esso contiene Metadati in forma di tag che fanno riferimento ad informazioni geografiche.

Per estrarre da un file tiff georeferenziato (geotiff) tali informazioni, è necessario avere installata nel sistema e richiamare in Gambas la libreria condivisa: "libgeotiff.so.5.2.1 ".

Mostriamo un esempio pratico:

Library "libgeotiff:5.2.1"

Public Struct TIFFMethod_t
  get As Pointer
  set As Pointer
  type As Pointer
End Struct

Public Struct gtiff
  gt_tif As Pointer
  gt_methods As Struct TIFFMethod_t
  gt_flags As Integer
  gt_version As Short
  gt_rev_major As Short
  gt_rev_minor As Short
  gt_num_keys As Integer
  gt_keys As Pointer
  gt_keyindex As Pointer
  gt_keymin As Integer
  gt_keymax As Integer
  gt_short As Pointer
  gt_double As Pointer
  gt_nshorts As Integer
  gt_ndoubles As Integer
End Struct

Public Struct GTIFDefn
  Model As Short
  PCS As Short
  GCS As Short
  UOMLength As Short
  UOMLengthInMeters As Float
  UOMAngle As Short
  UOMAngleInDegrees As Float
  Datum As Short
  PM As Short
  PMLongToGreenwich As Float
  Ellipsoid As Short
  SemiMajor As Float
  SemiMinor As Float
  TOWGS84Count As Short
  TOWGS84[7] As Float
  ProjCode As Short
  Projection As Short
  CTProjection As Short
  nParms As Integer
  ProjParm[10] As Float
  ProjParmId[10] As Integer
  MapSys As Integer
  Zone As Integer
  DefnSet As Integer
End Struct

Private Const ModelTypeGeographic As Integer = 2

' TIFF * XTIFFOpen(const char* name, const char* mode)
' Open GeoTIFF files.
Private Extern XTIFFOpen(name As String, mode As String) As Pointer

' GTIF *GTIFNew(void *tif)
' Set up a new GeoTIFF file Descriptor.
Private Extern GTIFNew(tif As Pointer) As Gtiff

' void GTIFPrint(GTIF *gtif, GTIFPrintMethod print, void *aux)
' Dumps a GeoTIFF metadata stream out to a specified file <fd>.
Private Extern GTIFPrint(gtif As Gtiff, print_ As Pointer, aux As Pointer)

' int GTIFGetDefn(GTIF *psGTIF, GTIFDefn *psDefn)
' Reads the coordinate system definition from a GeoTIFF file, and normalizes it.
Private Extern GTIFGetDefn(psGTIF As Gtiff, psDefn As GTIFDefn) As Integer

' void GTIFPrintDefn(GTIFDefn *psDefn, FILE *fp)
' Report the contents of a GTIFDefn structure.
Private Extern GTIFPrintDefn(psDefn As GTIFDefn, fp As Pointer)

' int GTIFImageToPCS(GTIF *gtif, double *x, double *y)
' Translate a pixel/line coordinate to projection coordinates.
Private Extern GTIFImageToPCS(gtif As Gtiff, x As Pointer, y As Pointer) As Integer

' int GTIFProj4ToLatLong(GTIFDefn * psDefn, int nPoints, double *padfX, double *padfY)
' Convert projection coordinates to lat/long for a particular definition.
Private Extern GTIFProj4ToLatLong(psDefn As GTIFDefn, nPoints As Integer, padfX As Float, padfY As Float) As Integer

' const char *GTIFDecToDMS(double dfAngle, const char * pszAxis, int nPrecision)
' Translate decimal degrees to DMS.
Private Extern GTIFDecToDMS(dfAngle As Float, pszAxis As String, nPrecision As Integer) As String

' void GTIFFree(GTIF *gtif)
' Destroys the GeoTIFF file descriptor.
Private Extern GTIFFree(gtif As Gtiff)

' void XTIFFClose(TIFF *tif)
' Close an extended TIFF file.
Private Extern XTIFFClose(tif As Pointer)


Library "libc:6"

' FILE *fopen (const char *__filename, const char *__modes)
' Open a file and create a new stream for it.
Private Extern fopen(__filename As String, __modes As String) As Pointer

' int fclose (FILE *__stream)
' Close STREAM.
Private Extern fclose(__stream As Pointer) As Integer


Library "libtiff:5.7.0"

Private Const TIFFTAG_IMAGEWIDTH As Integer = 256
Private Const TIFFTAG_IMAGELENGTH As Integer = 257

' int TIFFGetField(TIFF* tif, uint32 tag, ...)
' TIFFGetField returns the value of a tag or pseudo-tag.
Private Extern TIFFGetField(tif As Pointer, tag As Integer, vl As Pointer) As Integer


Public Sub Main()
 
 Dim tf, p As Pointer
 Dim gt As Gtiff
 Dim df As New GTIFDefn
 Dim x, y As Integer
 
' Carica un file georeferenziato (GEOTIFF):
 tf = XTIFFOpen("/percorso/del/file.tif", "r")
 If tf == 0 Then Error.Raise("Errore !")
 
 gt = GTIFNew(tf)
 If Not Object.IsValid(gt) Then
   XTIFFClose(tf)
   Error.Raise("Errore !")
 Endif
 
 GTIFPrint(gt, 0, 0)
 Print
 p = fopen("/dev/stdout", "w")
 
 If GTIFGetDefn(gt, df) Then GTIFPrintDefn(df, p)
 
 TIFFGetField(tf, TIFFTAG_IMAGEWIDTH, VarPtr(x))
 TIFFGetField(tf, TIFFTAG_IMAGELENGTH, VarPtr(y))
 
 GTIFPrintCorners(gt, df, x, y)
 
' Libera la memoria precedentemente occupata:
 fclose(p)
 GTIFFree(gt)
 XTIFFClose(tf)
  
End

Private Procedure GTIFPrintCorners(gtif As Gtiff, defn As GTIFDefn, xsize As Integer, ysize As Integer)
 
 Print "\n== Coordinate degli angoli =="
 
 If Not GTIFReportACorner(gtif, defn, "Superiore sinistro", 0.0, 0.0) Then
   Print "\e[5mImpossibile trasformare punti tra pixel/linee e spazio PCS !\e[0m"
   Return
 Endif
 
 GTIFReportACorner(gtif, defn, "Inferiore sinistro", 0.0, CFloat(ysize))
 GTIFReportACorner(gtif, defn, "Superiore destro", CFloat(xsize), 0.0)
 GTIFReportACorner(gtif, defn, "Inferiore destro", CFloat(xsize), CFloat(ysize))
 GTIFReportACorner(gtif, defn, "Centro", xsize / 2.0, ysize / 2.0)
 
End

Private Function GTIFReportACorner(gtif As Gtiff, defn As GTIFDefn, angolo As String, xf As Float, yf As Float) As Boolean
 
 If Not GTIFImageToPCS(gtif, VarPtr(xf), VarPtr(yf)) Then Return False
 
 Print "   \e[1m"; angolo; "\e[0m"
 
 If defn.Model == ModelTypeGeographic Then
   Print String(6, Chr(32)); Format(xf, "#.0000000") & Chr(32) & GTIFDecToDMS(xf, "Long", 2)
   Print String(6, Chr(32)); Format(yf, "#.0000000") & Chr(32) & GTIFDecToDMS(yf, "Lat", 2)
 Else
   Print "("; Format(xf, "############.000"); ", "; Format(yf, "############.000"); ")"
   If GTIFProj4ToLatLong(defn, 1, VarPtr(xf), VarPtr(yf)) Then
     Print String(6, Chr(32)); Format(xf, "#.0000000") & Chr(32) & GTIFDecToDMS(xf, "Long", 2)
     Print String(6, Chr(32)); Format(yf, "#.0000000") & Chr(32) & GTIFDecToDMS(yf, "Lat", 2)
   Endif
 Endif
 
 Return True
 
End


Riferimenti